forked from Gitlink/forgeplus-react
@我功能。
This commit is contained in:
parent
b1ead191a6
commit
f003a99779
|
@ -224,7 +224,7 @@ function NoticeContent({ visible, showNotification, resetUserInfo, current_user:
|
|||
<Badge color="#FA2020" />
|
||||
</span>
|
||||
<div className="noticeCont-text">
|
||||
<span className="content-span atme-cont-span" dangerouslySetInnerHTML={{ __html: "<b>" + (item.sender ? item.sender.name : '') + "</b> " + item.content + " 中@我" }}></span>
|
||||
<span className="content-span atme-cont-span" dangerouslySetInnerHTML={{ __html: item.content }}></span>
|
||||
<span className="timeSpan">{item.time_ago}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -17,7 +17,7 @@ function MyNotice(props) {
|
|||
const [selectedNum, setSelectedNum] = useState(0);//@我批量删除选择消息条数
|
||||
const [isBatchDelete, setIsBatchDelete] = useState(false);//@我是否批量删除
|
||||
const [batchDeleteCheckedAll, setBatchDeleteCheckAll] = useState(false);//@我批量删除--全选
|
||||
|
||||
const [messageType, setMessageType] = useState(undefined);
|
||||
const [noticeUnreadCount, setNoticeUnreadCount] = useState();//未读系统通知数量
|
||||
// const [letterUnreadCount, setLetterUnreadCount] = useState(0);//未读私信数量
|
||||
const [atUnreadCount, setAtUnreadCount] = useState();//未读@我数量
|
||||
|
@ -65,6 +65,7 @@ function MyNotice(props) {
|
|||
setAtUnreadCount(response.data.unread_atme);
|
||||
setMessageList(response.data.messages);
|
||||
setMessTotalCount(response.data.total_count);
|
||||
setMessageType(response.data.type);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -203,7 +204,46 @@ function MyNotice(props) {
|
|||
</div>
|
||||
</div>}
|
||||
|
||||
{messageList && messageList.map(item => {
|
||||
{/* 系统消息 */}
|
||||
{messageType === "notification" && messageList && messageList.map(item =>{
|
||||
return (
|
||||
<div className="mynotice-content vertical-center-style" key={item.id}>
|
||||
<div className="mynotice-cont stretch-style">
|
||||
{item.status === 1 ? <Badge color="#FA2020" /> : <span className="system-notice-blank"></span>}
|
||||
<i className={"iconfont "+noticeSourceType[item.source]}></i>
|
||||
<span className={`sysNotice-length ${item.notification_url?'highlightSpan':''}`} onClick={() => {turnToMess(item)}} dangerouslySetInnerHTML={{__html: item.content}}></span>
|
||||
</div>
|
||||
<div className="mynotice-cont vertical-center-style float-left-little">
|
||||
<span className={item.status === 1?"timeSpan":""}>{item.time_ago}</span>
|
||||
{item.status === 1 && <span className="invisable-read" onClick={()=>readNotice([item.id])}>标记为已读</span>}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
|
||||
{/* @我消息 */}
|
||||
{messageType === "atme" && messageList && messageList.map(item =>{
|
||||
return (
|
||||
<div className={`mynotice-content vertical-center-style ${isBatchDelete?'batchDel':''}`} key={item.id}>
|
||||
<div className="mynotice-cont vertical-center-style">
|
||||
<Checkbox value={item.id} className={isBatchDelete ? 'visible-checkbox' : 'invisible-checkbox'} onChange={onChange} checked={item.checkedBatch}></Checkbox>
|
||||
{item.sender && <img src={`https://testforgeplus.trustie.net//${item.sender.image_url}`} className="currentImg" onClick={()=>{window.open(`/${item.sender && item.sender.login}`);}}/>}
|
||||
<div className={`atme-notice-text stretch-style ${item.notification_url && 'highlightSpan'}`} onClick={() => {turnToMess(item)}}>
|
||||
{item.status === 1 ? <Badge color="#FA2020"/> : <span className="system-notice-blank"></span>}
|
||||
{item.sender && <span className="atme-length" dangerouslySetInnerHTML={{__html: item.content}}></span>}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mynotice-cont vertical-center-style">
|
||||
<span className={!isBatchDelete && item.status === 1?"timeSpan":""}>{item.time_ago}</span>
|
||||
{!isBatchDelete && item.status === 1 && <span className="invisable-read" onClick={()=>readNotice([item.id])}>标记为已读</span>}
|
||||
{!isBatchDelete && <span className="invisable-read float-left-little" onClick={()=>deleteNotice([item.id])}>删除</span>}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
|
||||
{false && messageList && messageList.map(item => {
|
||||
console.log('item',item);
|
||||
// 系统消息
|
||||
if (noticeType === "0") {
|
||||
// 消息类别
|
||||
|
@ -229,7 +269,7 @@ function MyNotice(props) {
|
|||
{item.sender && <img src={`https://testforgeplus.trustie.net//${item.sender.image_url}`} className="currentImg" onClick={()=>{window.open(`/${item.sender && item.sender.login}`);}}/>}
|
||||
<div className={`atme-notice-text stretch-style ${item.notification_url && 'highlightSpan'}`} onClick={() => {turnToMess(item)}}>
|
||||
{item.status === 1 ? <Badge color="#FA2020"/> : <span className="system-notice-blank"></span>}
|
||||
{item.sender && <span className="atme-length" dangerouslySetInnerHTML={{__html: "<b class = 'atme-notice-name'>" + item.sender.name+ "</b> "+ item.content +" 中@我"}}></span>}
|
||||
{item.sender && <span className="atme-length" dangerouslySetInnerHTML={{__html: "<b class = 'atme-notice-name'>" + item.sender.name+ "</b> "+ item.content}}></span>}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mynotice-cont vertical-center-style">
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
border-bottom: 1px solid rgba(212, 212, 212, 0.5);
|
||||
padding: 0 4px;
|
||||
}
|
||||
.active{
|
||||
.at_who.active{
|
||||
background: #F3F4F6;
|
||||
}
|
||||
.at_who img{
|
||||
|
@ -39,8 +39,4 @@
|
|||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.blur_atWho{
|
||||
position: absolute;
|
||||
top: -100px;
|
||||
}
|
|
@ -75,30 +75,35 @@ function md_elocalStorage(editor, mdu, id) {
|
|||
}
|
||||
|
||||
export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, className = '', noStorage = false, imageExpand = true, placeholder = '', width = '100%', height = 400, initValue = '', emoji, watch, showNullButton = false, showResizeBar = false, startInit = true , forMember = true , isCanAtme = false , changeAtWhoLoginList, owner, projectsId }) => {
|
||||
|
||||
|
||||
const editorEl = useRef();
|
||||
const resizeBarEl = useRef();
|
||||
const [editorInstance, setEditorInstance] = useState();
|
||||
const [atWhoVisible, setAtWhoVisible] = useState(false);
|
||||
const [atWhoLoginListState, setAtWhoLoginListState] = useState([]);
|
||||
//调用member.json接口获取到的用户列表
|
||||
const [users, setUsers] = useState([]);
|
||||
//用户输入的@之后的搜索词
|
||||
const [search, setSeacrch] = useState(undefined);
|
||||
//可以@的全部用户
|
||||
const [allUsers, setAllUsers] = useState([]);
|
||||
const atWhoLoginList = useRef([]);
|
||||
const atWhoVisibleRef = useRef(false);
|
||||
const containerId = `mdEditor_${mdID}`;
|
||||
const editorBodyId = `mdEditors_${mdID}`;
|
||||
const tipId = `e_tips_mdEditor_${mdID}`;
|
||||
|
||||
useEffect(()=>{
|
||||
isCanAtme && axios.get(`/${owner}/${projectsId}/members.json`,{
|
||||
// params: {
|
||||
// search: 'admin',
|
||||
// },
|
||||
}).then(response=>{
|
||||
if(response && response.status === 200){
|
||||
//请求members接口获取全部可@列表
|
||||
isCanAtme && axios.get(`/${owner}/${projectsId}/members.json`).then(response=>{
|
||||
if(response.data.total_count !== 0){
|
||||
setAllUsers(response.data.users);
|
||||
setUsers(response.data.users);
|
||||
}
|
||||
})
|
||||
//点击其他地方关闭弹框
|
||||
document.addEventListener('click',()=>{
|
||||
atWhoVisibleRef.current = false;
|
||||
setAtWhoVisible(false);
|
||||
})
|
||||
},[])
|
||||
|
||||
function onLayout() {
|
||||
|
@ -119,14 +124,16 @@ export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, cla
|
|||
}
|
||||
|
||||
function selectAtWho(username){
|
||||
atWhoVisibleRef.current = false;
|
||||
setAtWhoVisible(false);
|
||||
const cm = editorInstance.cm;
|
||||
//获取鼠标所在行的行数和ch
|
||||
const cursor = cm.doc.getCursor();
|
||||
const line = cursor.line;//行
|
||||
const ch = cursor.ch;//列
|
||||
const startIndex = cm.getRange({line,ch:0},{line,ch}).lastIndexOf("@")+1;
|
||||
//替换最后的内容
|
||||
cm.replaceRange(username+" ",{line,ch},{line,ch});
|
||||
cm.replaceRange(username+" ",{line,ch:startIndex},{line,ch});
|
||||
//鼠标聚焦
|
||||
cm.focus();
|
||||
//将此user的login存储到atWhoLoginList集合中
|
||||
|
@ -136,155 +143,58 @@ export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, cla
|
|||
})
|
||||
atWhoLoginList.current = Array.from(list);
|
||||
setAtWhoLoginListState(Array.from(list));
|
||||
//销毁atWhoKeyDown键盘监听事件
|
||||
// document.removeEventListener("keydown",atWhoKeyDown);
|
||||
}
|
||||
|
||||
function onMouseOver(key){
|
||||
document.getElementsByClassName("at_who active")[0].className="at_who";
|
||||
document.getElementsByClassName("at_who")[key].className="at_who active";
|
||||
document.getElementsByClassName("at_who active")[0] && (document.getElementsByClassName("at_who active")[0].className="at_who");
|
||||
document.getElementsByClassName("at_who")[key] && (document.getElementsByClassName("at_who")[key].className="at_who active");
|
||||
}
|
||||
|
||||
//markdown编辑器中输入的键盘监听事件
|
||||
function mdKeyDown(e){
|
||||
console.log("markdown编辑器--------键盘监听事件");
|
||||
// document.onkeydown = e=>{
|
||||
if (e.shiftKey && e.key === "@") {
|
||||
// 输入@键后在对应的位置显示可选的项目成员
|
||||
setAtWhoVisible(true);
|
||||
//获取光标位置
|
||||
const cssStyle = document.getElementsByClassName("CodeMirror cm-s-default CodeMirror-wrap")[0].firstChild.style;
|
||||
//设置弹框位置
|
||||
document.getElementById("at_who_list").style.top = (parseInt(cssStyle.getPropertyValue("top").replace("px",""))+60)+"px";
|
||||
document.getElementById("at_who_list").style.left = (parseInt(cssStyle.getPropertyValue("left").replace("px",""))+20)+"px";
|
||||
//将第一个用户默认选中
|
||||
const at_who_divs = document.getElementsByClassName("at_who");
|
||||
at_who_divs[0].className = "at_who active";
|
||||
}
|
||||
//处理本来@了某人 -> 删掉 -> 撤回 的情况
|
||||
if(e.ctrlKey && e.code === "KeyZ" && users.length != 0){
|
||||
const codemirror = editorInstance.cm;
|
||||
let value = codemirror.getValue();
|
||||
//处理初始内容就自带@谁的情况
|
||||
if(initValue){
|
||||
const del = [];
|
||||
users.map(item=>{
|
||||
if(initValue.indexOf(item.username)!=-1 && initValue.charAt(initValue.indexOf(item.username)-1) === "@" && initValue.indexOf(`@${item.username}`)===value.indexOf(`@${item.username}`)){
|
||||
//初始内容中有符合@+名字的格式并且当前内容未删除初始内容
|
||||
del[del.length] = `@${item.username}`;
|
||||
}
|
||||
})
|
||||
del.length!=0 && del.map(str=>{
|
||||
value = value.replace(str,"");
|
||||
})
|
||||
}
|
||||
//判断value是否包含@符号
|
||||
value.indexOf("@") != -1 && users.map(item =>{
|
||||
if(value.indexOf(item.username)!=-1 && value.charAt(value.indexOf(item.username)-1) ==="@"){
|
||||
//将此user的login存储到atWhoLoginList集合中
|
||||
const list = new Set(atWhoLoginList.current);
|
||||
list.add(item.login);
|
||||
atWhoLoginList.current = Array.from(list);
|
||||
setAtWhoLoginListState(Array.from(list));
|
||||
if (e.shiftKey && e.code === "Digit2") {
|
||||
// 输入@键后在对应的位置显示可选的项目成员
|
||||
atWhoVisibleRef.current = true;
|
||||
setAtWhoVisible(true);
|
||||
//获取光标位置
|
||||
const cssStyle = document.getElementsByClassName("CodeMirror cm-s-default CodeMirror-wrap")[0].firstChild.style;
|
||||
//设置弹框位置
|
||||
const newTop = placeholder === "添加评论..." ? 159: placeholder === "请输入合并请求的描述..." ? 172:62;
|
||||
const newLeft = placeholder === "添加评论..." ? 80: 20;
|
||||
document.getElementById("at_who_list").style.top = parseInt(cssStyle.getPropertyValue("top").replace("px","")) + newTop +"px";
|
||||
document.getElementById("at_who_list").style.left = parseInt(cssStyle.getPropertyValue("left").replace("px",""))+newLeft+"px";
|
||||
}
|
||||
//处理本来@了某人 -> 删掉 -> 撤回 的情况
|
||||
if(e.ctrlKey && e.code === "KeyZ" && allUsers.length != 0){
|
||||
const codemirror = editorInstance.cm;
|
||||
let value = codemirror.getValue();
|
||||
//处理初始内容就自带@谁的情况
|
||||
if(initValue){
|
||||
const del = [];
|
||||
allUsers.map(item=>{
|
||||
if(initValue.indexOf(item.username)!=-1 && initValue.charAt(initValue.indexOf(item.username)-1) === "@" && initValue.indexOf(`@${item.username}`)===value.indexOf(`@${item.username}`)){
|
||||
//初始内容中有符合@+名字的格式并且当前内容未删除初始内容
|
||||
del[del.length] = `@${item.username}`;
|
||||
}
|
||||
})
|
||||
del.length!=0 && del.map(str=>{
|
||||
value = value.replace(str,"");
|
||||
})
|
||||
}
|
||||
// const atWhoListDiv = document.getElementById("at_who_list");
|
||||
// if(atWhoListDiv && (e.key === "ArrowUp" || e.key === "ArrowDown" || e.key === "Enter")){
|
||||
// return false;
|
||||
// }
|
||||
// const atWhoDivs = document.getElementsByClassName("at_who");
|
||||
// let index;
|
||||
// for(let i = 0; i<atWhoDivs.length;i++){
|
||||
// atWhoDivs[i].className === "at_who active" && (index = i);
|
||||
// }
|
||||
// //当可选@列表div弹出之后监听上下键(不能通过判断atWhoVisible,因为atWhoVisible还未更新为true)
|
||||
// if(e.key === "ArrowUp" && index > 0){
|
||||
// e.preventDefault();
|
||||
// index <=atWhoDivs.length-4 && (atWhoListDiv.scrollTop -=40)
|
||||
// atWhoDivs[index].className = "at_who";
|
||||
// atWhoDivs[index-1].className = "at_who active";
|
||||
// }
|
||||
// if(e.key === "ArrowDown"){
|
||||
// e.preventDefault();
|
||||
// console.log("ArrowDown",atWhoVisible);
|
||||
// const atWhoListDiv = document.getElementById("at_who_list");
|
||||
// const atWhoDivs = document.getElementsByClassName("at_who");
|
||||
// let index;
|
||||
// for(let i = 0; i<atWhoDivs.length;i++){
|
||||
// atWhoDivs[i].className === "at_who active" && (index = i);
|
||||
// }
|
||||
// index >=3 && (atWhoListDiv.scrollTop +=40)
|
||||
// atWhoDivs[index].className = "at_who";
|
||||
// atWhoDivs[index+1].className = "at_who active";
|
||||
// }
|
||||
// if(e.key === "Enter"){
|
||||
// //阻止默认事件
|
||||
// e.preventDefault();
|
||||
// //找到classname为at_who active的div,执行click事件
|
||||
// document.getElementsByClassName("at_who active")[0].click();
|
||||
// }
|
||||
|
||||
// editorInstance.addKeyMap({
|
||||
// 'ArrowUp':()=>{
|
||||
// index <=atWhoDivs.length-4 && (atWhoListDiv.scrollTop -=40)
|
||||
// atWhoDivs[index].className = "at_who";
|
||||
// atWhoDivs[index-1].className = "at_who active";
|
||||
// },
|
||||
// 'ArrowDown':()=>{
|
||||
// index >=3 && (atWhoListDiv.scrollTop +=40)
|
||||
// atWhoDivs[index].className = "at_who";
|
||||
// atWhoDivs[index+1].className = "at_who active";
|
||||
// },
|
||||
// 'Enter':()=>{
|
||||
// //找到classname为at_who active的div,执行click事件
|
||||
// document.getElementsByClassName("at_who active")[0].click();
|
||||
// },
|
||||
// })
|
||||
|
||||
// }
|
||||
// }
|
||||
//判断value是否包含@符号
|
||||
value.indexOf("@") != -1 && allUsers.map(item =>{
|
||||
if(value.indexOf(item.username)!=-1 && value.charAt(value.indexOf(item.username)-1) ==="@"){
|
||||
//将此user的login存储到atWhoLoginList集合中
|
||||
const list = new Set(atWhoLoginList.current);
|
||||
list.add(item.login);
|
||||
atWhoLoginList.current = Array.from(list);
|
||||
setAtWhoLoginListState(Array.from(list));
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
//弹出可选@用户列表之后的键盘监听事件
|
||||
function atWhoKeyDown(e){
|
||||
//监听上下和enter键
|
||||
// document.onkeydown = (e) =>{
|
||||
const atWhoListDiv = document.getElementById("at_who_list");
|
||||
const atWhoDivs = document.getElementsByClassName("at_who");
|
||||
let index;
|
||||
for(let i = 0; i<atWhoDivs.length;i++){
|
||||
atWhoDivs[i].className === "at_who active" && (index = i);
|
||||
}
|
||||
console.log("监听上下和enter键",e,atWhoListDiv,atWhoDivs,index);
|
||||
if(e.key === "ArrowUp" && index > 0){
|
||||
index <=atWhoDivs.length-4 && (atWhoListDiv.scrollTop -=40)
|
||||
atWhoDivs[index].className = "at_who";
|
||||
atWhoDivs[index-1].className = "at_who active";
|
||||
return;
|
||||
}
|
||||
if(e.key === "ArrowDown" && index < atWhoDivs.length-1){
|
||||
index >=3 && (atWhoListDiv.scrollTop +=40)
|
||||
atWhoDivs[index].className = "at_who";
|
||||
atWhoDivs[index+1].className = "at_who active";
|
||||
return;
|
||||
}
|
||||
if(e.key === "Enter"){
|
||||
//阻止默认事件
|
||||
e.preventDefault();
|
||||
//找到classname为at_who active的div,执行click事件
|
||||
document.getElementsByClassName("at_who active")[0].click();
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
//点击其他地方关闭弹框
|
||||
useEffect(()=>{
|
||||
document.addEventListener('click',()=>{setAtWhoVisible(false)})
|
||||
},[])
|
||||
|
||||
useEffect(()=>{
|
||||
console.log('@谁列表发生变化,atWhoLoginList.current:',atWhoLoginList.current);
|
||||
changeAtWhoLoginList && changeAtWhoLoginList(atWhoLoginListState);
|
||||
},[atWhoLoginListState])
|
||||
|
||||
|
@ -292,8 +202,8 @@ export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, cla
|
|||
<div className="at_who_list" id="at_who_list" >
|
||||
{users && users.map((item,key)=>{
|
||||
return(
|
||||
<div key={key} className="at_who" onClick={()=>{selectAtWho(item.username)}} onMouseOver={()=>{onMouseOver(key)}}>
|
||||
{item.image_url && <img src={getImageUrl(item.image_url)}></img>}
|
||||
<div key={key} className={`at_who ${key===0 && `active`}`} onClick={()=>{selectAtWho(item.username)}} onMouseOver={()=>{onMouseOver(key)}}>
|
||||
{item.image_url && <img src={getImageUrl(`/${item.image_url}`)}></img>}
|
||||
<span>{item.username}</span>
|
||||
</div>
|
||||
)
|
||||
|
@ -301,25 +211,6 @@ export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, cla
|
|||
</div>
|
||||
)
|
||||
|
||||
useEffect(()=>{
|
||||
//当atWhoVisible为true的时候,失焦,监听上下和enter键
|
||||
// atWhoVisible && editorInstance.cm.
|
||||
if(atWhoVisible){
|
||||
const cm = editorInstance.cm;
|
||||
//获取鼠标所在行的行数和ch
|
||||
const line = cm.doc.getCursor().line;//行
|
||||
console.log('useEffect',cm.getLine(line));
|
||||
// document.activeElement.id !== "blur_atWho" && document.getElementById("blur_atWho").focus();
|
||||
// const atWhoDivs = document.getElementsByClassName("at_who");
|
||||
// let index = 0;
|
||||
// for(let i = 0; i<atWhoDivs.length;i++){
|
||||
// atWhoDivs[i].className === "at_who active" && (index = i);
|
||||
// }
|
||||
// const atWhoListDiv = document.getElementById("at_who_list");
|
||||
// document.addEventListener("keydown",atWhoKeyDown);
|
||||
}
|
||||
},[atWhoVisible])
|
||||
|
||||
useEffect(() => {
|
||||
if (editorInstance) {
|
||||
return
|
||||
|
@ -402,6 +293,69 @@ export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, cla
|
|||
|
||||
const cmEl = editorInstance && editorInstance.cm
|
||||
|
||||
useEffect(()=>{
|
||||
if(atWhoVisibleRef.current){
|
||||
// 添加上下键、enter键监听事件
|
||||
cmEl.addKeyMap({
|
||||
'Up':()=>{
|
||||
const atWhoListDiv = document.getElementById("at_who_list");
|
||||
const atWhoDivs = document.getElementsByClassName("at_who");
|
||||
let index;
|
||||
for(let i = 0; i<atWhoDivs.length;i++){
|
||||
atWhoDivs[i].className === "at_who active" && (index = i);
|
||||
}
|
||||
if(index>0){
|
||||
index <=atWhoDivs.length-4 && (atWhoListDiv.scrollTop -=40)
|
||||
atWhoDivs[index].className = "at_who";
|
||||
atWhoDivs[index-1].className = "at_who active";
|
||||
}
|
||||
},
|
||||
'Down':()=>{
|
||||
const atWhoListDiv = document.getElementById("at_who_list");
|
||||
const atWhoDivs = document.getElementsByClassName("at_who");
|
||||
let index;
|
||||
for(let i = 0; i<atWhoDivs.length;i++){
|
||||
atWhoDivs[i].className === "at_who active" && (index = i);
|
||||
}
|
||||
if(index<atWhoDivs.length-1){
|
||||
index >=3 && (atWhoListDiv.scrollTop +=40)
|
||||
atWhoDivs[index].className = "at_who";
|
||||
atWhoDivs[index+1].className = "at_who active";
|
||||
}
|
||||
},
|
||||
'Enter':()=>{
|
||||
//找到classname为at_who active的div,执行click事件
|
||||
if(document.getElementsByClassName("at_who active")[0]){
|
||||
document.getElementsByClassName("at_who active")[0].click()
|
||||
}else{
|
||||
const cm = editorInstance.cm;
|
||||
const cursor = cm.doc.getCursor();
|
||||
const line = cursor.line;//行
|
||||
const ch = cursor.ch;//列
|
||||
//添加换行
|
||||
cm.replaceRange("\n",{line,ch},{line,ch});
|
||||
setAtWhoVisible(false);
|
||||
atWhoVisibleRef.current = false;
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
//移除上下、enter键监听
|
||||
cmEl && cmEl.removeKeyMap();
|
||||
}
|
||||
},[atWhoVisible])
|
||||
|
||||
useEffect(()=>{
|
||||
//当users数组发生变化时改变框的位置
|
||||
if(atWhoVisibleRef.current && users){
|
||||
//获取光标位置
|
||||
const cssStyle = document.getElementsByClassName("CodeMirror cm-s-default CodeMirror-wrap")[0].firstChild.style;
|
||||
//设置弹框位置
|
||||
const newLeft = placeholder === "添加评论..."? 80: 10;
|
||||
document.getElementById("at_who_list").style.left = (parseInt(cssStyle.getPropertyValue("left").replace("px",""))+newLeft)+"px";
|
||||
}
|
||||
},[users])
|
||||
|
||||
useEffect(() => {
|
||||
if (cmEl) {
|
||||
let tid = null
|
||||
|
@ -426,7 +380,34 @@ export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, cla
|
|||
document.removeEventListener("keydown",mdKeyDown);
|
||||
});
|
||||
editorInstance.cm.on("change", (cm) => {
|
||||
//调用父组件的onchange方法,将输入内容传入父级组件
|
||||
onChange && onChange(cm.getValue());
|
||||
if(atWhoVisibleRef.current){
|
||||
//搜索用户(弹框之后用户输入用户名信息)
|
||||
const cur = cm.doc.getCursor();
|
||||
const line = cur.line;
|
||||
const ch = cur.ch;
|
||||
let rangeCont = cmEl.getRange({line,ch:0},{line,ch});
|
||||
//处理已经弹出列表框,但用户删除@符号
|
||||
if(rangeCont.indexOf("@")===-1){
|
||||
setAtWhoVisible(false);
|
||||
atWhoVisibleRef.current = false;
|
||||
}else{
|
||||
rangeCont = rangeCont.substring(rangeCont.lastIndexOf("@")+1);
|
||||
rangeCont ? axios.get(`/${owner}/${projectsId}/members.json`,{
|
||||
params: {
|
||||
search: rangeCont,
|
||||
},
|
||||
}).then(response=>{
|
||||
if(response && response.data && response.data.total_count !== 0){
|
||||
setUsers(response.data.users);
|
||||
}else{
|
||||
setUsers(undefined);
|
||||
}
|
||||
}):setUsers(allUsers)
|
||||
}
|
||||
}
|
||||
|
||||
//当内容发生改变并且有已@列表时
|
||||
if(atWhoLoginList.current.length != 0){
|
||||
const codemirror = editorInstance.cm;
|
||||
|
@ -434,7 +415,7 @@ export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, cla
|
|||
//处理初始内容就自带@谁的情况
|
||||
if(initValue){
|
||||
const del = [];
|
||||
users.map(item=>{
|
||||
allUsers.map(item=>{
|
||||
if(initValue.indexOf(item.username)!=-1 && initValue.charAt(initValue.indexOf(item.username)-1) === "@" && initValue.indexOf(`@${item.username}`)===value.indexOf(`@${item.username}`)){
|
||||
//初始内容中有符合@+名字的格式并且当前内容未删除初始内容
|
||||
del[del.length] = `@${item.username}`;
|
||||
|
@ -447,7 +428,7 @@ export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, cla
|
|||
//以username为主键,login为value的map集合
|
||||
let atWhoMap = new Map();
|
||||
Array.from(atWhoLoginList.current).map(item=>{
|
||||
users.map(i=>{
|
||||
allUsers.map(i=>{
|
||||
if(i.login === item){
|
||||
atWhoMap.set(i.username,i.login);
|
||||
}
|
||||
|
@ -471,8 +452,6 @@ export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, cla
|
|||
return;
|
||||
}
|
||||
//处理有名字但是无@符号,有@但是名字对不上的情况
|
||||
const a = value.indexOf(username)===-1;
|
||||
const b = value.charAt(value.indexOf(username)-1) !="@";
|
||||
if(value.indexOf(username)===-1 || value.charAt(value.indexOf(username)-1) !="@"){
|
||||
//符合任意一种情况->踢掉这个人 不给他发消息
|
||||
const list = new Set(atWhoLoginList.current);
|
||||
|
@ -541,14 +520,14 @@ export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, cla
|
|||
}, [
|
||||
editorInstance, resizeBarEl
|
||||
])
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{atWhoVisible && atWhoList}
|
||||
<div ref={editorEl} className={`df ${className} ${imageExpand && 'editormd-image-click-expand'} `}>
|
||||
<div className={`edu-back-greyf5 radius4 editormd ${error ? 'error' : ''}`} id={containerId} >
|
||||
<textarea style={{ display: 'none' }} id={editorBodyId} name="content"></textarea>
|
||||
<div className="CodeMirror cm-s-defualt"></div>
|
||||
<input id ="blur_atWho" className="blur_atWho"/>
|
||||
{atWhoVisible && atWhoList}
|
||||
</div>
|
||||
</div>
|
||||
{showResizeBar ? <a ref={resizeBarEl} className='editor-resize'></a> : null}
|
||||
|
|
Loading…
Reference in New Issue