Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
midjourney-proxy
Overview
Overview
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
徐少华
midjourney-proxy
Commits
1e777734
Commit
1e777734
authored
Mar 06, 2020
by
裴大威
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'feat-1002505' into 'master'
需求单延迟 See merge request rays/pcloud-book!514
parents
c4e9a581
9e67e954
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
394 additions
and
49 deletions
+394
-49
pom.xml
pcloud-service-book/pom.xml
+5
-0
FeedbackConsr.java
...java/com/pcloud/book/consumer/feedback/FeedbackConsr.java
+18
-2
BookGuideBizImpl.java
...a/com/pcloud/book/keywords/biz/impl/BookGuideBizImpl.java
+2
-0
DelayReceiver.java
...src/main/java/com/pcloud/book/mq/delay/DelayReceiver.java
+4
-0
PersonalStageBiz.java
...a/com/pcloud/book/personalstage/biz/PersonalStageBiz.java
+1
-1
PersonalStageJumpBiz.java
...m/pcloud/book/personalstage/biz/PersonalStageJumpBiz.java
+33
-0
PersonalStageBizImpl.java
...oud/book/personalstage/biz/impl/PersonalStageBizImpl.java
+22
-17
PersonalStageJumpBizImpl.java
...book/personalstage/biz/impl/PersonalStageJumpBizImpl.java
+174
-24
PersonalStageProgressMessageBizImpl.java
...alstage/biz/impl/PersonalStageProgressMessageBizImpl.java
+11
-0
PersonalStageConstant.java
...ud/book/personalstage/constant/PersonalStageConstant.java
+8
-1
PersonalStageProgressMessageDao.java
...ok/personalstage/dao/PersonalStageProgressMessageDao.java
+3
-0
PersonalStageProgressMessageDaoImpl.java
...alstage/dao/impl/PersonalStageProgressMessageDaoImpl.java
+6
-0
LinkClickRecordDTO.java
...com/pcloud/book/personalstage/dto/LinkClickRecordDTO.java
+20
-0
PaperDelayDTO.java
...java/com/pcloud/book/personalstage/dto/PaperDelayDTO.java
+24
-0
ProgressDelayDTO.java
...a/com/pcloud/book/personalstage/dto/ProgressDelayDTO.java
+22
-0
PersonalStageProgressMessage.java
...ok/personalstage/entity/PersonalStageProgressMessage.java
+3
-0
PersonalStageFacade.java
...pcloud/book/personalstage/facade/PersonalStageFacade.java
+14
-0
PersonalStageProgressMessage.Mapper.xml
...per/personalstage/PersonalStageProgressMessage.Mapper.xml
+24
-4
No files found.
pcloud-service-book/pom.xml
View file @
1e777734
...
...
@@ -191,6 +191,11 @@
<artifactId>
pcloud-facade-wechat
</artifactId>
<version>
${pcloud-facade.version}
</version>
</dependency>
<dependency>
<groupId>
com.pcloud.facade
</groupId>
<artifactId>
pcloud-facade-feedback
</artifactId>
<version>
${pcloud-facade.version}
</version>
</dependency>
<dependency>
<groupId>
com.pcloud.facade
</groupId>
...
...
pcloud-service-book/src/main/java/com/pcloud/book/consumer/feedback/FeedbackConsr.java
View file @
1e777734
package
com
.
pcloud
.
book
.
consumer
.
feedback
;
import
com.pcloud.book.base.exception.BookBizException
;
import
com.pcloud.common.core.aspect.ParamLog
;
import
com.pcloud.common.exceptions.BizException
;
import
com.pcloud.common.utils.ListUtils
;
import
com.pcloud.common.utils.ResponseHandleUtil
;
import
com.pcloud.
contentcenter.resource.dto.ResourceDTO
;
import
com.pcloud.
contentcenter.resource.service.ResourceService
;
import
com.pcloud.
feedback.feedback.service.FeedBackService
;
import
com.pcloud.
feedback.paper.dto.PaperAndQuestionDto
;
import
com.pcloud.feedback.paper.dto.PaperDto
;
import
com.pcloud.feedback.paper.service.PaperService
;
import
org.slf4j.Logger
;
...
...
@@ -27,6 +29,8 @@ public class FeedbackConsr {
@Autowired
private
PaperService
paperService
;
@Autowired
private
FeedBackService
feedBackService
;
/**
...
...
@@ -71,5 +75,17 @@ public class FeedbackConsr {
return
paperIds
;
}
@ParamLog
(
"根据问卷id获取问卷基本信息"
)
public
PaperAndQuestionDto
getPaperByPaperId
(
Long
paperId
){
PaperAndQuestionDto
questionDto
=
new
PaperAndQuestionDto
();
try
{
questionDto
=
ResponseHandleUtil
.
parseResponse
(
feedBackService
.
getPaperByPaperId
(
paperId
),
PaperAndQuestionDto
.
class
);
}
catch
(
Exception
e
){
LOGGER
.
error
(
"【feedBackService.getPaperByPaperId】调用失败"
+
e
.
getMessage
(),
e
);
}
return
questionDto
;
}
}
pcloud-service-book/src/main/java/com/pcloud/book/keywords/biz/impl/BookGuideBizImpl.java
View file @
1e777734
...
...
@@ -287,6 +287,8 @@ public class BookGuideBizImpl implements BookGuideBiz {
//清空缓存中该阶段的非关键词数量
//刪除发送非关键词次数緩存
JedisClusterUtils
.
del
(
PersonalStageConstant
.
USER_SEND_KEYWORD_COUNT_LOCK
+
personalStageId
+
"_"
+
agreeAddUserDTO
.
getUserWxId
());
//删除进度单点击记录缓存
JedisClusterUtils
.
del
(
"BOOK:LINK_PROGRESS:"
+
agreeAddUserDTO
.
getUserWxId
()
+
"-"
+
agreeAddUserDTO
.
getRobotWxId
());
}
return
;
}
...
...
pcloud-service-book/src/main/java/com/pcloud/book/mq/delay/DelayReceiver.java
View file @
1e777734
...
...
@@ -48,6 +48,10 @@ public class DelayReceiver {
personalStageBiz
.
dealDelayFusingFinish
(
dto
);
}
else
if
(
PersonalStageConstant
.
PERSONALSTAGE_DELAY_LINKUP
.
equals
(
dto
.
getType
()))
{
personalStageJumpBiz
.
dealDelayLinkup
(
dto
);
}
else
if
(
PersonalStageConstant
.
PERSONALSTAGE_DELAY_PROGRESS
.
equalsIgnoreCase
(
dto
.
getType
()))
{
personalStageJumpBiz
.
delayProgress
(
dto
);
}
else
if
(
PersonalStageConstant
.
PERSONALSTAGE_DELAY_PAPER
.
equalsIgnoreCase
(
dto
.
getType
()))
{
personalStageJumpBiz
.
delayPaper
(
dto
);
}
}
}
pcloud-service-book/src/main/java/com/pcloud/book/personalstage/biz/PersonalStageBiz.java
View file @
1e777734
...
...
@@ -55,7 +55,7 @@ public interface PersonalStageBiz {
void
sendNotKeywordFusingReply
(
String
robotId
,
String
userWxId
,
String
ip
,
Long
personalStageId
,
Long
personalStageUserId
,
Long
paperId
);
String
replaceProjectProgressUrl
(
String
content
,
String
robotId
,
String
userWxId
,
Long
personalStageUserId
);
String
replaceProjectProgressUrl
(
String
content
,
String
robotId
,
String
userWxId
,
Long
personalStageUserId
,
String
ip
);
void
dealDelayFusingFinish
(
DelayQueueDTO
dto
);
...
...
pcloud-service-book/src/main/java/com/pcloud/book/personalstage/biz/PersonalStageJumpBiz.java
View file @
1e777734
package
com
.
pcloud
.
book
.
personalstage
.
biz
;
import
com.pcloud.book.personalstage.dto.LinkClickRecordDTO
;
import
com.pcloud.book.personalstage.dto.PersonalStageJumpDto
;
import
com.pcloud.book.personalstage.enums.JumpTypeEnum
;
import
com.pcloud.book.personalstage.vo.request.CreateStageJumpRequestVO
;
...
...
@@ -59,4 +60,36 @@ public interface PersonalStageJumpBiz {
* @return
*/
Map
<
String
,
Object
>
getUserInputPaperInfo
(
String
robotWxId
,
String
userWxId
);
/**
* 进度单发送时添加未点链接回复延迟
*/
public
void
addProgressDelay
(
String
userWxId
,
String
robotWxId
,
String
ip
);
/**
* 添加点击记录
* @param linkClickRecordDTO
*/
public
void
addLinkClickRecord
(
LinkClickRecordDTO
linkClickRecordDTO
);
/**
* 处理进度单延迟
* @param dto
*/
void
delayProgress
(
DelayQueueDTO
dto
);
/**
* 添加需求定制单延迟
* @param userWxId
* @param robotWxId
* @param ip
* @param paperId
*/
public
void
addPaperDelay
(
String
userWxId
,
String
robotWxId
,
String
ip
,
Long
paperId
);
/**
* 处理需求单延迟
* @param dto
*/
void
delayPaper
(
DelayQueueDTO
dto
);
}
pcloud-service-book/src/main/java/com/pcloud/book/personalstage/biz/impl/PersonalStageBizImpl.java
View file @
1e777734
...
...
@@ -68,8 +68,6 @@ import java.util.Map;
import
java.util.Random
;
import
java.util.stream.Collectors
;
import
io.swagger.models.auth.In
;
@Component
(
"personalStageBiz"
)
public
class
PersonalStageBizImpl
implements
PersonalStageBiz
{
...
...
@@ -501,7 +499,7 @@ public class PersonalStageBizImpl implements PersonalStageBiz {
String
robotId
=
wakeupDelayDTO
.
getRobotId
();
String
userWxId
=
wakeupDelayDTO
.
getWxId
();
String
ip
=
wakeupDelayDTO
.
getIp
();
this
.
replacePaperUrl
(
replyItems
,
robotId
,
userWxId
,
personalStage
.
getPaperId
());
this
.
replacePaperUrl
(
replyItems
,
robotId
,
userWxId
,
personalStage
.
getPaperId
()
,
ip
);
sendReplyItems
(
replyItems
,
robotId
,
userWxId
,
ip
,
wakeupDelayDTO
.
getPersonalStageUserId
());
//下一个延时
List
<
PersonalStageWakeup
>
wakeups
=
personalStageWakeupDao
.
getListByPersonalStageId
(
personalStageId
);
...
...
@@ -614,7 +612,7 @@ public class PersonalStageBizImpl implements PersonalStageBiz {
return
;
}
//替换需求定制单链接
this
.
replacePaperUrl
(
items
,
robotId
,
userWxId
,
personalStageReply
.
getPaperId
());
this
.
replacePaperUrl
(
items
,
robotId
,
userWxId
,
personalStageReply
.
getPaperId
()
,
ip
);
sendReplyItems
(
items
,
robotId
,
userWxId
,
ip
,
personalStageUserId
);
}
...
...
@@ -687,11 +685,13 @@ public class PersonalStageBizImpl implements PersonalStageBiz {
@Override
@ParamLog
(
"替换进度链接"
)
public
String
replaceProjectProgressUrl
(
String
content
,
String
robotId
,
String
userWxId
,
Long
personalStageUserId
)
{
public
String
replaceProjectProgressUrl
(
String
content
,
String
robotId
,
String
userWxId
,
Long
personalStageUserId
,
String
ip
)
{
if
(
content
.
indexOf
(
PersonalStageConstant
.
PERSONAL_STAGE_PROJECT_PROGRESS_TEMPLATE
)
>
-
1
){
tryInsertNumber
(
personalStageUserId
);
String
longUrl
=
wechatLinkPrefix
.
concat
(
PersonalStageConstant
.
PERSONAL_STAGE_PROJECT_PROGRESS
).
concat
(
"?wxUserId="
+
userWxId
+
"&robotId="
+
robotId
+
"&personalStageUserId="
+
personalStageUserId
);
content
=
content
.
replace
(
PersonalStageConstant
.
PERSONAL_STAGE_PROJECT_PROGRESS_TEMPLATE
,
UrlUtils
.
getShortUrl4Own
(
longUrl
));
//添加进度单回复延迟队列
personalStageJumpBiz
.
addProgressDelay
(
userWxId
,
robotId
,
ip
);
}
content
=
replaceUserSendContent
(
content
,
robotId
,
userWxId
);
content
=
replaceReadingStyle
(
content
,
robotId
,
userWxId
);
...
...
@@ -734,20 +734,25 @@ public class PersonalStageBizImpl implements PersonalStageBiz {
}
@ParamLog
(
"替换需求定制单链接"
)
private
void
replacePaperUrl
(
List
<
PersonalStageReplyItem
>
items
,
String
robotId
,
String
userWxId
,
Long
paperId
){
private
void
replacePaperUrl
(
List
<
PersonalStageReplyItem
>
items
,
String
robotId
,
String
userWxId
,
Long
paperId
,
String
ip
){
for
(
PersonalStageReplyItem
item
:
items
){
if
(
ReplyTypeEnum
.
TEXT
.
value
.
equals
(
item
.
getReplyType
())){
if
(
null
==
paperId
){
item
.
setContent
(
item
.
getContent
().
replace
(
PERSONAL_STAGE_PAPER_TEMPLATE
,
""
));
item
.
setContent
(
item
.
getContent
().
replace
(
PERSONAL_STAGE_PAPER_TEMPLATE1
,
""
));
return
;
if
(
item
.
getContent
().
indexOf
(
PERSONAL_STAGE_PAPER_TEMPLATE
)
>
-
1
||
item
.
getContent
().
indexOf
(
PERSONAL_STAGE_PAPER_TEMPLATE1
)
>
-
1
)
{
//包含链接
if
(
null
==
paperId
)
{
item
.
setContent
(
item
.
getContent
().
replace
(
PERSONAL_STAGE_PAPER_TEMPLATE
,
""
));
item
.
setContent
(
item
.
getContent
().
replace
(
PERSONAL_STAGE_PAPER_TEMPLATE1
,
""
));
return
;
}
String
longUrl
=
wechatLinkPrefix
.
concat
(
PERSONAL_STAGE_PAPER
).
concat
(
paperId
.
toString
()).
concat
(
"&wxId="
+
userWxId
+
"&robotWxId="
+
robotId
);
//由于前端给的替换符中的“&”可能会是“&”,所以两种替换符都要换掉
String
shortLink
=
UrlUtils
.
getShortUrl4Own
(
longUrl
);
item
.
setContent
(
item
.
getContent
().
replace
(
PERSONAL_STAGE_PAPER_TEMPLATE
,
shortLink
));
item
.
setContent
(
item
.
getContent
().
replace
(
PERSONAL_STAGE_PAPER_TEMPLATE1
,
shortLink
));
//添加需求单延迟发送队列
personalStageJumpBiz
.
addPaperDelay
(
userWxId
,
robotId
,
ip
,
paperId
);
}
String
longUrl
=
wechatLinkPrefix
.
concat
(
PERSONAL_STAGE_PAPER
).
concat
(
paperId
.
toString
()).
concat
(
"&wxId="
+
userWxId
+
"&robotWxId="
+
robotId
);
//由于前端给的替换符中的“&”可能会是“&”,所以两种替换符都要换掉
String
shortLink
=
UrlUtils
.
getShortUrl4Own
(
longUrl
);
item
.
setContent
(
item
.
getContent
().
replace
(
PERSONAL_STAGE_PAPER_TEMPLATE
,
shortLink
));
item
.
setContent
(
item
.
getContent
().
replace
(
PERSONAL_STAGE_PAPER_TEMPLATE1
,
shortLink
));
}
}
}
...
...
@@ -765,7 +770,7 @@ public class PersonalStageBizImpl implements PersonalStageBiz {
if
(
ListUtils
.
isEmpty
(
items
)){
return
;
}
this
.
replacePaperUrl
(
items
,
robotId
,
userWxId
,
paperId
);
this
.
replacePaperUrl
(
items
,
robotId
,
userWxId
,
paperId
,
ip
);
sendReplyItems
(
items
,
robotId
,
userWxId
,
ip
,
personalStageUserId
);
}
...
...
@@ -775,7 +780,7 @@ public class PersonalStageBizImpl implements PersonalStageBiz {
Integer
type
=
item
.
getReplyType
();
if
(
ReplyTypeEnum
.
TEXT
.
value
.
equals
(
type
))
{
SendTextMessageVO
sendTextMessageVO
=
new
SendTextMessageVO
();
sendTextMessageVO
.
setContent
(
replaceProjectProgressUrl
(
item
.
getContent
(),
robotId
,
userWxId
,
personalStageUserId
));
sendTextMessageVO
.
setContent
(
replaceProjectProgressUrl
(
item
.
getContent
(),
robotId
,
userWxId
,
personalStageUserId
,
ip
));
sendTextMessageVO
.
setAltId
(
robotId
);
sendTextMessageVO
.
setWxGroupId
(
userWxId
);
sendTextMessageVO
.
setIp
(
ip
);
...
...
pcloud-service-book/src/main/java/com/pcloud/book/personalstage/biz/impl/PersonalStageJumpBizImpl.java
View file @
1e777734
...
...
@@ -4,6 +4,7 @@ import com.pcloud.book.base.exception.BookBizException;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Maps
;
import
com.pcloud.book.book.entity.Book
;
import
com.pcloud.book.consumer.feedback.FeedbackConsr
;
import
com.pcloud.book.consumer.wechatgroup.WechatGroupConsr
;
import
com.pcloud.book.group.biz.WeixinQrcodeBiz
;
import
com.pcloud.book.guide.biz.PcloudGuideBiz
;
...
...
@@ -17,15 +18,8 @@ import com.pcloud.book.personalstage.biz.PersonalStageBiz;
import
com.pcloud.book.personalstage.biz.PersonalStageJumpBiz
;
import
com.pcloud.book.personalstage.constant.PersonalStageConstant
;
import
com.pcloud.book.personalstage.dao.*
;
import
com.pcloud.book.personalstage.dto.LinkupDelayDTO
;
import
com.pcloud.book.personalstage.dto.PersonalStageJumpDto
;
import
com.pcloud.book.personalstage.dto.PersonalStageJumpKeywordDto
;
import
com.pcloud.book.personalstage.entity.PersonalStage
;
import
com.pcloud.book.personalstage.entity.PersonalStageJump
;
import
com.pcloud.book.personalstage.entity.PersonalStageJumpEmail
;
import
com.pcloud.book.personalstage.entity.PersonalStageJumpKeyword
;
import
com.pcloud.book.personalstage.entity.PersonalStageJumpLinkup
;
import
com.pcloud.book.personalstage.entity.PersonalStageUser
;
import
com.pcloud.book.personalstage.dto.*
;
import
com.pcloud.book.personalstage.entity.*
;
import
com.pcloud.book.personalstage.enums.JumpTypeEnum
;
import
com.pcloud.book.personalstage.enums.PersonalStageUserStateEnum
;
import
com.pcloud.book.personalstage.vo.request.BaseStageJumpRequestVO
;
...
...
@@ -45,12 +39,14 @@ import com.pcloud.common.utils.NumberUtil;
import
com.pcloud.common.utils.cache.redis.JedisClusterUtils
;
import
com.pcloud.common.utils.httpclient.UrlUtils
;
import
com.pcloud.common.utils.string.StringUtil
;
import
com.pcloud.feedback.paper.dto.PaperAndQuestionDto
;
import
com.pcloud.wechatgroup.group.dto.GroupRobotDTO
;
import
com.pcloud.wechatgroup.group.dto.GroupUserDTO
;
import
com.sdk.wxgroup.SendMessageTypeEnum
;
import
com.sdk.wxgroup.SendPicMessageVO
;
import
com.sdk.wxgroup.SendTextMessageVO
;
import
com.sdk.wxgroup.WxGroupSDK
;
import
lombok.extern.slf4j.Slf4j
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
...
...
@@ -63,6 +59,7 @@ import java.util.*;
import
java.util.stream.Collectors
;
@Component
(
"personalStageJumpBiz"
)
@Slf4j
public
class
PersonalStageJumpBizImpl
implements
PersonalStageJumpBiz
{
private
static
final
Logger
LOGGER
=
LoggerFactory
.
getLogger
(
PersonalStageJumpBizImpl
.
class
);
...
...
@@ -97,6 +94,10 @@ public class PersonalStageJumpBizImpl implements PersonalStageJumpBiz {
private
PersonalStageDao
personalStageDao
;
@Autowired
private
PersonalStageReplyDao
personalStageReplyDao
;
@Autowired
private
PersonalStageProgressMessageDao
personalStageProgressMessageDao
;
@Autowired
private
FeedbackConsr
feedbackConsr
;
@Value
(
"${system.env}"
)
private
String
envStr
;
...
...
@@ -390,11 +391,11 @@ public class PersonalStageJumpBizImpl implements PersonalStageJumpBiz {
}
List
<
PersonalStageJumpLinkup
>
list
=
new
ArrayList
<>();
list
.
add
(
jumpLinkup
);
this
.
replacePaperUrl
(
list
,
linkupDelayDTO
.
getRobotId
(),
linkupDelayDTO
.
getWxId
(),
jumpLinkup
.
getPersonalStageJumpId
());
this
.
replacePaperUrl
(
list
,
linkupDelayDTO
.
getRobotId
(),
linkupDelayDTO
.
getWxId
(),
jumpLinkup
.
getPersonalStageJumpId
()
,
linkupDelayDTO
.
getIp
()
);
jumpLinkup
=
list
.
get
(
0
);
if
(
ReplyTypeEnum
.
TEXT
.
value
.
equals
(
jumpLinkup
.
getReplyType
())){
SendTextMessageVO
sendTextMessageVO
=
new
SendTextMessageVO
();
sendTextMessageVO
.
setContent
(
personalStageBiz
.
replaceProjectProgressUrl
(
jumpLinkup
.
getLinkupContent
(),
linkupDelayDTO
.
getRobotId
(),
linkupDelayDTO
.
getWxId
(),
linkupDelayDTO
.
getPersonalStageUserId
()));
sendTextMessageVO
.
setContent
(
personalStageBiz
.
replaceProjectProgressUrl
(
jumpLinkup
.
getLinkupContent
(),
linkupDelayDTO
.
getRobotId
(),
linkupDelayDTO
.
getWxId
(),
linkupDelayDTO
.
getPersonalStageUserId
()
,
linkupDelayDTO
.
getIp
()
));
sendTextMessageVO
.
setAltId
(
linkupDelayDTO
.
getRobotId
());
sendTextMessageVO
.
setWxGroupId
(
dto
.
getKey
());
sendTextMessageVO
.
setIp
(
linkupDelayDTO
.
getIp
());
...
...
@@ -569,7 +570,7 @@ public class PersonalStageJumpBizImpl implements PersonalStageJumpBiz {
if
(
ListUtils
.
isEmpty
(
linkups
)){
return
;
}
this
.
replacePaperUrl
(
linkups
,
robotWxId
,
userWxId
,
jumpId
);
this
.
replacePaperUrl
(
linkups
,
robotWxId
,
userWxId
,
jumpId
,
ip
);
for
(
PersonalStageJumpLinkup
jumpLinkup
:
linkups
){
if
(
jumpLinkup
.
getToStageStartTime
()!=
null
&&
jumpLinkup
.
getToStageStartTime
()>
0
){
LinkupDelayDTO
linkupDelayDTO
=
new
LinkupDelayDTO
();
...
...
@@ -584,7 +585,7 @@ public class PersonalStageJumpBizImpl implements PersonalStageJumpBiz {
}
else
{
if
(
ReplyTypeEnum
.
TEXT
.
value
.
equals
(
jumpLinkup
.
getReplyType
())){
SendTextMessageVO
sendTextMessageVO
=
new
SendTextMessageVO
();
sendTextMessageVO
.
setContent
(
personalStageBiz
.
replaceProjectProgressUrl
(
jumpLinkup
.
getLinkupContent
(),
robotWxId
,
userWxId
,
personalStageUserId
));
sendTextMessageVO
.
setContent
(
personalStageBiz
.
replaceProjectProgressUrl
(
jumpLinkup
.
getLinkupContent
(),
robotWxId
,
userWxId
,
personalStageUserId
,
ip
));
sendTextMessageVO
.
setAltId
(
robotWxId
);
sendTextMessageVO
.
setWxGroupId
(
userWxId
);
sendTextMessageVO
.
setIp
(
ip
);
...
...
@@ -613,7 +614,7 @@ public class PersonalStageJumpBizImpl implements PersonalStageJumpBiz {
}
@ParamLog
(
"替换需求定制单链接"
)
private
void
replacePaperUrl
(
List
<
PersonalStageJumpLinkup
>
linkups
,
String
robotId
,
String
userWxId
,
Long
jumpId
){
private
void
replacePaperUrl
(
List
<
PersonalStageJumpLinkup
>
linkups
,
String
robotId
,
String
userWxId
,
Long
jumpId
,
String
ip
){
PersonalStageJumpDto
stageJump
=
personalStageJumpDao
.
getDtoById
(
jumpId
);
if
(
null
==
stageJump
){
return
;
...
...
@@ -623,22 +624,171 @@ public class PersonalStageJumpBizImpl implements PersonalStageJumpBiz {
return
;
}
for
(
PersonalStageJumpLinkup
linkup
:
linkups
){
if
(
ReplyTypeEnum
.
TEXT
.
value
.
equals
(
linkup
.
getReplyType
())){
if
(
null
==
personalStage
.
getPaperId
()){
linkup
.
setLinkupContent
(
linkup
.
getLinkupContent
().
replace
(
PERSONAL_STAGE_PAPER_TEMPLATE
,
""
));
linkup
.
setLinkupContent
(
linkup
.
getLinkupContent
().
replace
(
PERSONAL_STAGE_PAPER_TEMPLATE1
,
""
));
continue
;
if
(
ReplyTypeEnum
.
TEXT
.
value
.
equals
(
linkup
.
getReplyType
()))
{
if
(
linkup
.
getLinkupContent
().
indexOf
(
PERSONAL_STAGE_PAPER_TEMPLATE
)
>
-
1
||
linkup
.
getLinkupContent
().
indexOf
(
PERSONAL_STAGE_PAPER_TEMPLATE1
)
>
-
1
)
{
//包含链接
if
(
null
==
personalStage
.
getPaperId
())
{
linkup
.
setLinkupContent
(
linkup
.
getLinkupContent
().
replace
(
PERSONAL_STAGE_PAPER_TEMPLATE
,
""
));
linkup
.
setLinkupContent
(
linkup
.
getLinkupContent
().
replace
(
PERSONAL_STAGE_PAPER_TEMPLATE1
,
""
));
continue
;
}
String
longUrl
=
wechatLinkPrefix
.
concat
(
PERSONAL_STAGE_PAPER
).
concat
(
personalStage
.
getPaperId
().
toString
()).
concat
(
"&wxId="
+
userWxId
+
"&robotWxId="
+
robotId
);
//由于前端给的替换符中的“&”可能会是“&”,所以两种替换符都要换掉
String
shortLink
=
UrlUtils
.
getShortUrl4Own
(
longUrl
);
linkup
.
setLinkupContent
(
linkup
.
getLinkupContent
().
replace
(
PERSONAL_STAGE_PAPER_TEMPLATE
,
shortLink
));
linkup
.
setLinkupContent
(
linkup
.
getLinkupContent
().
replace
(
PERSONAL_STAGE_PAPER_TEMPLATE1
,
shortLink
));
//添加需求单延迟发送队列
addPaperDelay
(
userWxId
,
robotId
,
ip
,
personalStage
.
getPaperId
());
}
String
longUrl
=
wechatLinkPrefix
.
concat
(
PERSONAL_STAGE_PAPER
).
concat
(
personalStage
.
getPaperId
().
toString
()).
concat
(
"&wxId="
+
userWxId
+
"&robotWxId="
+
robotId
);
//由于前端给的替换符中的“&”可能会是“&”,所以两种替换符都要换掉
String
shortLink
=
UrlUtils
.
getShortUrl4Own
(
longUrl
);
linkup
.
setLinkupContent
(
linkup
.
getLinkupContent
().
replace
(
PERSONAL_STAGE_PAPER_TEMPLATE
,
shortLink
));
linkup
.
setLinkupContent
(
linkup
.
getLinkupContent
().
replace
(
PERSONAL_STAGE_PAPER_TEMPLATE1
,
shortLink
));
}
}
}
@Override
@ParamLog
(
"添加进度单延时"
)
public
void
addProgressDelay
(
String
userWxId
,
String
robotWxId
,
String
ip
){
PersonalStageProgressMessage
progressMessage
=
personalStageProgressMessageDao
.
getWaitClickProgress
();
if
(
null
==
progressMessage
||
null
==
progressMessage
.
getMinutes
()){
return
;
}
Integer
time
=
progressMessage
.
getMinutes
()*
1000
;
PersonalStageUser
currentStageUser
=
personalStageUserDao
.
getLast
(
userWxId
,
robotWxId
,
null
);
if
(
null
==
currentStageUser
){
return
;
}
Long
personalStageId
=
currentStageUser
.
getPersonalStageId
();
ProgressDelayDTO
progressDelayDTO
=
new
ProgressDelayDTO
();
progressDelayDTO
.
setIp
(
ip
);
progressDelayDTO
.
setRobotId
(
robotWxId
);
progressDelayDTO
.
setWxId
(
userWxId
);
progressDelayDTO
.
setPersonalStageId
(
personalStageId
);
DelayQueueDTO
delayQueueDTONew
=
DelayQueueDTO
.
builder
().
key
(
userWxId
).
type
(
PersonalStageConstant
.
PERSONALSTAGE_DELAY_PROGRESS
).
msg
(
progressDelayDTO
).
timeout
(
time
).
build
();
delayMessageSender
.
send
(
delayQueueDTONew
);
String
key
=
"BOOK:LINK_PROGRESS:"
+
userWxId
+
"-"
+
robotWxId
;
JedisClusterUtils
.
del
(
key
);
}
@Override
@ParamLog
(
"添加进度单/需求单点击记录"
)
public
void
addLinkClickRecord
(
LinkClickRecordDTO
linkClickRecordDTO
)
{
//链接类型(1进度单2需求单)
Integer
linkType
=
linkClickRecordDTO
.
getLinkType
();
String
userWxId
=
linkClickRecordDTO
.
getWxId
();
String
robotId
=
linkClickRecordDTO
.
getRobotId
();
if
(
linkType
==
1
){
String
key
=
"BOOK:LINK_PROGRESS:"
+
userWxId
+
"-"
+
robotId
;
JedisClusterUtils
.
setJson
(
key
,
userWxId
,
5
*
3600
);
}
else
if
(
linkType
==
2
){
String
key
=
"BOOK:LINK_PAPER:"
+
userWxId
+
"-"
+
robotId
+
"-"
+
linkClickRecordDTO
.
getPaperId
();
JedisClusterUtils
.
setJson
(
key
,
userWxId
,
5
*
3600
);
}
}
@Override
@ParamLog
(
"进度单延迟处理"
)
public
void
delayProgress
(
DelayQueueDTO
dto
)
{
PersonalStageProgressMessage
progressMessage
=
personalStageProgressMessageDao
.
getWaitClickProgress
();
if
(
null
==
progressMessage
||
StringUtil
.
isEmpty
(
progressMessage
.
getContent
())){
return
;
}
String
userWxId
=
dto
.
getKey
();
ProgressDelayDTO
progressDelayDTO
=(
ProgressDelayDTO
)
dto
.
getMsg
();
String
robotId
=
progressDelayDTO
.
getRobotId
();
Long
personalStageId
=
progressDelayDTO
.
getPersonalStageId
();
String
ip
=
progressDelayDTO
.
getIp
();
//是否点击过进度单链接
String
key
=
"BOOK:LINK_PROGRESS:"
+
userWxId
+
"-"
+
robotId
;
String
value
=
JedisClusterUtils
.
getJson
(
key
,
String
.
class
);
if
(!
StringUtil
.
isEmpty
(
value
)){
log
.
info
(
"用户已点击进度单链接"
);
JedisClusterUtils
.
del
(
key
);
return
;
}
// 查询用户是否在当前阶段
PersonalStageUser
currentStageUser
=
personalStageUserDao
.
getLast
(
userWxId
,
robotId
,
null
);
if
(
null
!=
currentStageUser
&&
!
personalStageId
.
equals
(
currentStageUser
.
getPersonalStageId
())){
log
.
info
(
"用户不在当前阶段"
);
return
;
}
SendTextMessageVO
sendTextMessageVO
=
new
SendTextMessageVO
();
sendTextMessageVO
.
setContent
(
progressMessage
.
getContent
());
sendTextMessageVO
.
setAltId
(
robotId
);
sendTextMessageVO
.
setWxGroupId
(
userWxId
);
sendTextMessageVO
.
setIp
(
ip
);
sendTextMessageVO
.
setCode
(
SendMessageTypeEnum
.
SELF
.
getCode
());
WxGroupSDK
.
sendTextMessage
(
sendTextMessageVO
);
}
@Override
@ParamLog
(
"添加需求单延迟"
)
public
void
addPaperDelay
(
String
userWxId
,
String
robotWxId
,
String
ip
,
Long
paperId
)
{
PaperAndQuestionDto
questionDto
=
feedbackConsr
.
getPaperByPaperId
(
paperId
);
if
(
null
==
questionDto
||
null
==
questionDto
.
getNotClickWaitTime
()){
return
;
}
Integer
time
=
questionDto
.
getNotClickWaitTime
()*
1000
;
PersonalStageUser
currentStageUser
=
personalStageUserDao
.
getLast
(
userWxId
,
robotWxId
,
null
);
if
(
null
==
currentStageUser
){
return
;
}
Long
personalStageId
=
currentStageUser
.
getPersonalStageId
();
PaperDelayDTO
paperDelayDTO
=
new
PaperDelayDTO
();
paperDelayDTO
.
setIp
(
ip
);
paperDelayDTO
.
setRobotId
(
robotWxId
);
paperDelayDTO
.
setWxId
(
userWxId
);
paperDelayDTO
.
setPersonalStageId
(
personalStageId
);
paperDelayDTO
.
setPaperId
(
paperId
);
DelayQueueDTO
delayQueueDTONew
=
DelayQueueDTO
.
builder
().
key
(
userWxId
).
type
(
PersonalStageConstant
.
PERSONALSTAGE_DELAY_PAPER
).
msg
(
paperDelayDTO
).
timeout
(
time
).
build
();
delayMessageSender
.
send
(
delayQueueDTONew
);
String
key
=
"BOOK:LINK_PAPER:"
+
userWxId
+
"-"
+
robotWxId
+
"-"
+
paperId
;
JedisClusterUtils
.
del
(
key
);
}
@Override
@ParamLog
(
"需求单延迟处理"
)
public
void
delayPaper
(
DelayQueueDTO
dto
)
{
String
userWxId
=
dto
.
getKey
();
PaperDelayDTO
paperDelayDTO
=(
PaperDelayDTO
)
dto
.
getMsg
();
String
robotId
=
paperDelayDTO
.
getRobotId
();
Long
personalStageId
=
paperDelayDTO
.
getPersonalStageId
();
String
ip
=
paperDelayDTO
.
getIp
();
Long
paperId
=
paperDelayDTO
.
getPaperId
();
PaperAndQuestionDto
questionDto
=
feedbackConsr
.
getPaperByPaperId
(
paperId
);
if
(
null
==
questionDto
||
StringUtil
.
isEmpty
(
questionDto
.
getNotClickReplyText
())){
return
;
}
//是否点击过需求单链接
String
key
=
"BOOK:LINK_PAPER:"
+
userWxId
+
"-"
+
robotId
+
"-"
+
paperId
;
String
value
=
JedisClusterUtils
.
getJson
(
key
,
String
.
class
);
//当前阶段是否发送
String
sendKey
=
"BOOK:LINK_PAPER_SEND:"
+
userWxId
+
"-"
+
robotId
+
"-"
+
paperId
+
"-"
+
personalStageId
;
String
send
=
JedisClusterUtils
.
getJson
(
sendKey
,
String
.
class
);
if
(!
StringUtil
.
isEmpty
(
value
)){
log
.
info
(
"用户已点击需求单链接"
+
paperId
);
// JedisClusterUtils.del(key);
return
;
}
if
(!
StringUtil
.
isEmpty
(
send
)){
log
.
info
(
"用户已发送需求单未点链接回复"
);
return
;
}
// 查询用户是否在当前阶段
PersonalStageUser
currentStageUser
=
personalStageUserDao
.
getLast
(
userWxId
,
robotId
,
null
);
if
(
null
!=
currentStageUser
&&
!
personalStageId
.
equals
(
currentStageUser
.
getPersonalStageId
())){
log
.
info
(
"用户不在当前阶段"
);
return
;
}
SendTextMessageVO
sendTextMessageVO
=
new
SendTextMessageVO
();
sendTextMessageVO
.
setContent
(
questionDto
.
getNotClickReplyText
());
sendTextMessageVO
.
setAltId
(
robotId
);
sendTextMessageVO
.
setWxGroupId
(
userWxId
);
sendTextMessageVO
.
setIp
(
ip
);
sendTextMessageVO
.
setCode
(
SendMessageTypeEnum
.
SELF
.
getCode
());
WxGroupSDK
.
sendTextMessage
(
sendTextMessageVO
);
JedisClusterUtils
.
setJson
(
sendKey
,
userWxId
,
30
);
}
@Override
public
Map
<
String
,
Object
>
getUserInputPaperInfo
(
String
robotWxId
,
String
userWxId
)
{
Map
<
String
,
Object
>
map
=
new
HashMap
<>();
//书名
...
...
pcloud-service-book/src/main/java/com/pcloud/book/personalstage/biz/impl/PersonalStageProgressMessageBizImpl.java
View file @
1e777734
...
...
@@ -56,11 +56,22 @@ public class PersonalStageProgressMessageBizImpl implements PersonalStageProgres
if
(
ListUtils
.
isEmpty
(
personalStageProgressMessage
)){
throw
BizException
.
PARAM_IS_NULL
;
}
for
(
int
i
=
personalStageProgressMessage
.
size
()-
1
;
i
>=
0
;
i
--){
if
(
personalStageProgressMessage
.
get
(
i
).
getType
()
==
2
&&
StringUtil
.
isEmpty
(
personalStageProgressMessage
.
get
(
i
).
getContent
())){
personalStageProgressMessage
.
remove
(
i
);
}
}
if
(
personalStageProgressMessage
.
stream
().
filter
(
x
->
StringUtil
.
isEmpty
(
x
.
getContent
())).
count
()
>
0
){
throw
BizException
.
PARAM_IS_NULL
;
}
// 删除所有旧数据
personalStageProgressMessageDao
.
deleteAll
();
personalStageProgressMessage
.
stream
().
forEach
(
x
->{
if
(
x
.
getType
()
==
null
||
x
.
getType
()
==
0
){
x
.
setType
(
1
);
}
});
// 重新插入
return
personalStageProgressMessageDao
.
insert
(
personalStageProgressMessage
);
}
...
...
pcloud-service-book/src/main/java/com/pcloud/book/personalstage/constant/PersonalStageConstant.java
View file @
1e777734
...
...
@@ -17,6 +17,13 @@ public class PersonalStageConstant {
public
static
final
String
PERSONAL_STAGE_SEND_TIME
=
"PERSONAL_STAGE_SEND_TIME"
;
/**
* 进度单未点链接延迟
*/
public
static
final
String
PERSONALSTAGE_DELAY_PROGRESS
=
"PERSONALSTAGE_DELAY_PROGRESS"
;
/**
* 需求定制单延迟
*/
public
static
final
String
PERSONALSTAGE_DELAY_PAPER
=
"PERSONALSTAGE_DELAY_PAPER"
;
}
pcloud-service-book/src/main/java/com/pcloud/book/personalstage/dao/PersonalStageProgressMessageDao.java
View file @
1e777734
...
...
@@ -27,4 +27,6 @@ public interface PersonalStageProgressMessageDao extends BaseDao<PersonalStagePr
* @return
*/
Integer
countProgressMessage
();
PersonalStageProgressMessage
getWaitClickProgress
();
}
\ No newline at end of file
pcloud-service-book/src/main/java/com/pcloud/book/personalstage/dao/impl/PersonalStageProgressMessageDaoImpl.java
View file @
1e777734
...
...
@@ -41,4 +41,9 @@ public class PersonalStageProgressMessageDaoImpl extends BaseDaoImpl<PersonalSta
public
Integer
countProgressMessage
()
{
return
super
.
sqlSessionTemplate
.
selectOne
(
getStatement
(
"countProgressMessage"
));
}
@Override
public
PersonalStageProgressMessage
getWaitClickProgress
()
{
return
getSessionTemplate
().
selectOne
(
getStatement
(
"getWaitClickProgress"
));
}
}
\ No newline at end of file
pcloud-service-book/src/main/java/com/pcloud/book/personalstage/dto/LinkClickRecordDTO.java
0 → 100644
View file @
1e777734
package
com
.
pcloud
.
book
.
personalstage
.
dto
;
import
com.pcloud.common.dto.BaseDto
;
import
io.swagger.annotations.ApiModel
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.Data
;
@Data
@ApiModel
(
"点链接dto"
)
public
class
LinkClickRecordDTO
extends
BaseDto
{
@ApiModelProperty
(
"链接类型(1进度单2需求单)"
)
private
Integer
linkType
;
@ApiModelProperty
(
"机器人id"
)
private
String
robotId
;
@ApiModelProperty
(
"用户wxId"
)
private
String
wxId
;
@ApiModelProperty
(
"需求定制单id"
)
private
Long
paperId
;
}
pcloud-service-book/src/main/java/com/pcloud/book/personalstage/dto/PaperDelayDTO.java
0 → 100644
View file @
1e777734
package
com
.
pcloud
.
book
.
personalstage
.
dto
;
import
io.swagger.annotations.ApiModel
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.Data
;
import
java.io.Serializable
;
@Data
@ApiModel
(
"需求定制单未点链接延时dto"
)
public
class
PaperDelayDTO
implements
Serializable
{
@ApiModelProperty
(
"定制化阶段id"
)
private
Long
personalStageId
;
@ApiModelProperty
(
"机器人id"
)
private
String
robotId
;
@ApiModelProperty
(
"用户wxId"
)
private
String
wxId
;
@ApiModelProperty
(
"ip地址"
)
private
String
ip
;
@ApiModelProperty
(
"需求单id"
)
private
Long
paperId
;
}
pcloud-service-book/src/main/java/com/pcloud/book/personalstage/dto/ProgressDelayDTO.java
0 → 100644
View file @
1e777734
package
com
.
pcloud
.
book
.
personalstage
.
dto
;
import
io.swagger.annotations.ApiModel
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.Data
;
import
java.io.Serializable
;
@Data
@ApiModel
(
"进度单未点链接延时dto"
)
public
class
ProgressDelayDTO
implements
Serializable
{
@ApiModelProperty
(
"定制化阶段id"
)
private
Long
personalStageId
;
@ApiModelProperty
(
"机器人id"
)
private
String
robotId
;
@ApiModelProperty
(
"用户wxId"
)
private
String
wxId
;
@ApiModelProperty
(
"ip地址"
)
private
String
ip
;
}
pcloud-service-book/src/main/java/com/pcloud/book/personalstage/entity/PersonalStageProgressMessage.java
View file @
1e777734
...
...
@@ -32,4 +32,6 @@ public class PersonalStageProgressMessage extends BaseEntity {
* 状态(0-未完成,1-已完成)
*/
private
Integer
state
;
private
Integer
type
;
}
\ No newline at end of file
pcloud-service-book/src/main/java/com/pcloud/book/personalstage/facade/PersonalStageFacade.java
View file @
1e777734
...
...
@@ -2,6 +2,7 @@ package com.pcloud.book.personalstage.facade;
import
com.pcloud.book.personalstage.biz.PersonalStageBiz
;
import
com.pcloud.book.personalstage.biz.PersonalStageProgressMessageBiz
;
import
com.pcloud.book.personalstage.dto.LinkClickRecordDTO
;
import
com.pcloud.book.personalstage.dto.PersonalStageProgressDTO
;
import
com.pcloud.book.personalstage.entity.PersonalStage
;
import
com.pcloud.book.personalstage.entity.PersonalStageProgressMessage
;
...
...
@@ -253,4 +254,17 @@ public class PersonalStageFacade {
return
new
ResponseDto
<>(
map
);
}
@ApiOperation
(
"保存进度单/需求单链接点击记录"
)
@PostMapping
(
"addLinkClickRecord"
)
public
ResponseDto
<?>
addLinkClickRecord
(
@RequestBody
@ApiParam
(
"链接点击记录"
)
LinkClickRecordDTO
linkClickRecordDTO
){
if
(
null
==
linkClickRecordDTO
||
StringUtil
.
isEmpty
(
linkClickRecordDTO
.
getRobotId
())
||
StringUtil
.
isEmpty
(
linkClickRecordDTO
.
getWxId
())
||
null
==
linkClickRecordDTO
.
getLinkType
()){
throw
new
BookBizException
(
BookBizException
.
PARAM_IS_NULL
,
"参数缺失"
);
}
if
(
linkClickRecordDTO
.
getLinkType
()==
2
&&
null
==
linkClickRecordDTO
.
getPaperId
()){
throw
new
BookBizException
(
BookBizException
.
PARAM_IS_NULL
,
"缺失需求单id"
);
}
personalStageJumpBiz
.
addLinkClickRecord
(
linkClickRecordDTO
);
return
new
ResponseDto
<>();
}
}
pcloud-service-book/src/main/resources/mapper/personalstage/PersonalStageProgressMessage.Mapper.xml
View file @
1e777734
...
...
@@ -6,12 +6,13 @@
<id
column=
"id"
property=
"id"
jdbcType=
"BIGINT"
/>
<result
column=
"content"
property=
"content"
jdbcType=
"VARCHAR"
/>
<result
column=
"minutes"
property=
"minutes"
jdbcType=
"INTEGER"
/>
<result
column=
"type"
property=
"type"
jdbcType=
"INTEGER"
/>
<result
column=
"create_time"
property=
"createTime"
jdbcType=
"TIMESTAMP"
/>
<result
column=
"update_time"
property=
"updateTime"
jdbcType=
"TIMESTAMP"
/>
</resultMap>
<sql
id=
"Base_Column_List"
>
id, content, minutes,
create_time, update_time
id, content, minutes,
type, create_time, update_time
</sql>
<select
id=
"getById"
resultMap=
"BaseResultMap"
>
...
...
@@ -25,17 +26,20 @@
SELECT
<include
refid=
"Base_Column_List"
/>
FROM personal_stage_progress_message
ORDER BY type
</select>
<insert
id=
"insert"
keyProperty=
"id"
useGeneratedKeys=
"true"
>
INSERT INTO personal_stage_progress_message(
content,
minutes,
minutes,
type,
create_time,
update_time
) VALUES (
#{content, jdbcType=VARCHAR},
#{minutes, jdbcType=INTEGER},
#{type, jdbcType=INTEGER},
NOW(),
NOW()
)
...
...
@@ -44,7 +48,8 @@
<insert
id=
"batchInsert"
keyProperty=
"id"
useGeneratedKeys=
"true"
>
INSERT INTO personal_stage_progress_message (
content,
minutes,
minutes,
type,
create_time,
update_time
) VALUES
...
...
@@ -52,6 +57,7 @@
(
#{item.content, jdbcType=VARCHAR},
#{item.minutes, jdbcType=INTEGER},
#{item.type, jdbcType=INTEGER},
NOW(),
NOW()
)
...
...
@@ -68,6 +74,9 @@
<if
test=
"minutes != null"
>
minutes = #{minutes},
</if>
<if
test=
"type != null"
>
type = #{type},
</if>
<if
test=
"createTime != null"
>
create_time = #{createTime},
</if>
...
...
@@ -91,14 +100,25 @@
select
id,
content,
minutes
minutes,
type
from
personal_stage_progress_message
where
TIMESTAMPDIFF(MINUTE,#{startTime}, now())
>
= minutes
and type = 1
order by id asc
</select>
<select
id=
"getWaitClickProgress"
resultMap=
"BaseResultMap"
>
select
<include
refid=
"Base_Column_List"
/>
from
personal_stage_progress_message
where type = 2
limit 1
</select>
<select
id=
"selectAllProgressMessage"
resultType=
"com.pcloud.book.personalstage.entity.PersonalStageProgressMessage"
>
select
id,
...
...
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