Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 41d1d63

Browse files
committed
主题增加附言功能
1 parent ad0d02e commit 41d1d63

File tree

11 files changed

+357
-25
lines changed

11 files changed

+357
-25
lines changed

config/db.sql

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,15 @@ CREATE TABLE IF NOT EXISTS `topics_ex` (
5151
PRIMARY KEY (`tid`)
5252
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT '主题扩展表(计数)';
5353

54+
CREATE TABLE IF NOT EXISTS `topic_append` (
55+
`id` int unsigned NOT NULL AUTO_INCREMENT,
56+
`tid` int unsigned NOT NULL DEFAULT 0 COMMENT '主题 TID',
57+
`content` text NOT NULL COMMENT '附言内容',
58+
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
59+
PRIMARY KEY (`id`),
60+
KEY `tid` (`tid`)
61+
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT '主题附言表';
62+
5463
CREATE TABLE IF NOT EXISTS `topics_node` (
5564
`nid` int unsigned NOT NULL AUTO_INCREMENT,
5665
`parent` int unsigned NOT NULL DEFAULT 0 COMMENT '父节点id,无父节点为0',

src/http/controller/topic.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"logic"
1313
"model"
1414
"net/http"
15+
"strconv"
1516

1617
. "http"
1718

@@ -39,6 +40,8 @@ func (self TopicController) RegisterRoute(g *echo.Group) {
3940

4041
g.Match([]string{"GET", "POST"}, "/topics/new", self.Create, middleware.NeedLogin(), middleware.Sensivite(), middleware.BalanceCheck(), middleware.PublishNotice())
4142
g.Match([]string{"GET", "POST"}, "/topics/modify", self.Modify, middleware.NeedLogin(), middleware.Sensivite())
43+
44+
g.Match([]string{"GET", "POST"}, "/append/topic/:tid", self.Append, middleware.NeedLogin(), middleware.Sensivite(), middleware.BalanceCheck())
4245
}
4346

4447
func (self TopicController) TopicList(ctx echo.Context) error {
@@ -166,6 +169,8 @@ func (TopicController) Detail(ctx echo.Context) error {
166169
logic.Views.Incr(Request(ctx), model.TypeTopic, tid)
167170
}
168171

172+
data["appends"] = logic.DefaultTopic.FindAppend(ctx, tid)
173+
169174
return render(ctx, "topics/detail.html,common/comment.html", data)
170175
}
171176

@@ -256,3 +261,39 @@ func (TopicController) Modify(ctx echo.Context) error {
256261
}
257262
return success(ctx, map[string]interface{}{"tid": tid})
258263
}
264+
265+
func (TopicController) Append(ctx echo.Context) error {
266+
tid := goutils.MustInt(ctx.Param("tid"))
267+
if tid == 0 {
268+
return ctx.Redirect(http.StatusSeeOther, "/topics")
269+
}
270+
271+
topics := logic.DefaultTopic.FindByTids([]int{tid})
272+
if len(topics) == 0 {
273+
return ctx.Redirect(http.StatusSeeOther, "/topics")
274+
}
275+
276+
topic := topics[0]
277+
me := ctx.Get("user").(*model.Me)
278+
if topic.Uid != me.Uid {
279+
return ctx.Redirect(http.StatusSeeOther, "/topics/"+strconv.Itoa(tid))
280+
}
281+
282+
// 请求新建主题页面
283+
if ctx.Request().Method() != http.MethodPost {
284+
data := map[string]interface{}{
285+
"topic": topic,
286+
"activeTopics": "active",
287+
}
288+
289+
return render(ctx, "topics/append.html", data)
290+
}
291+
292+
content := ctx.FormValue("content")
293+
err := logic.DefaultTopic.Append(ctx, me.Uid, tid, content)
294+
if err != nil {
295+
return fail(ctx, 1, "出错了:"+err.Error())
296+
}
297+
298+
return success(ctx, nil)
299+
}

src/logic/observer.go

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ var (
1717
modifyObservable Observable
1818
commentObservable Observable
1919
ViewObservable Observable
20+
appendObservable Observable
2021
)
2122

2223
func init() {
@@ -38,6 +39,11 @@ func init() {
3839
ViewObservable = NewConcreteObservable(actionView)
3940
ViewObservable.AddObserver(&UserWeightObserver{})
4041
ViewObservable.AddObserver(&TodayActiveObserver{})
42+
43+
appendObservable = NewConcreteObservable(actionAppend)
44+
appendObservable.AddObserver(&UserWeightObserver{})
45+
appendObservable.AddObserver(&TodayActiveObserver{})
46+
appendObservable.AddObserver(&UserRichObserver{})
4147
}
4248

4349
type Observer interface {
@@ -58,6 +64,7 @@ const (
5864
actionModify = "modify"
5965
actionComment = "comment"
6066
actionView = "view"
67+
actionAppend = "append"
6168
)
6269

6370
type ConcreteObservable struct {
@@ -104,29 +111,42 @@ func (this *ConcreteObservable) NotifyObservers(uid, objtype, objid int) {
104111
type UserWeightObserver struct{}
105112

106113
func (this *UserWeightObserver) Update(action string, uid, objtype, objid int) {
107-
if action == actionPublish {
108-
DefaultUser.IncrUserWeight("uid", uid, 20)
109-
} else if action == actionModify {
110-
DefaultUser.IncrUserWeight("uid", uid, 2)
111-
} else if action == actionComment {
112-
DefaultUser.IncrUserWeight("uid", uid, 5)
113-
} else if action == actionView {
114-
DefaultUser.IncrUserWeight("uid", uid, 1)
114+
var weight int
115+
switch action {
116+
case actionPublish:
117+
weight = 20
118+
case actionModify:
119+
weight = 2
120+
case actionComment:
121+
weight = 5
122+
case actionView:
123+
weight = 1
124+
case actionAppend:
125+
weight = 15
115126
}
127+
128+
DefaultUser.IncrUserWeight("uid", uid, weight)
116129
}
117130

118131
type TodayActiveObserver struct{}
119132

120133
func (*TodayActiveObserver) Update(action string, uid, objtype, objid int) {
121-
if action == actionPublish {
122-
DefaultRank.GenDAURank(uid, 20)
123-
} else if action == actionModify {
124-
DefaultRank.GenDAURank(uid, 2)
125-
} else if action == actionComment {
126-
DefaultRank.GenDAURank(uid, 5)
127-
} else if action == actionView {
128-
DefaultRank.GenDAURank(uid, 1)
134+
var weight int
135+
136+
switch action {
137+
case actionPublish:
138+
weight = 20
139+
case actionModify:
140+
weight = 2
141+
case actionComment:
142+
weight = 5
143+
case actionView:
144+
weight = 1
145+
case actionAppend:
146+
weight = 15
129147
}
148+
149+
DefaultRank.GenDAURank(uid, weight)
130150
}
131151

132152
type UserRichObserver struct{}
@@ -324,6 +344,13 @@ func (UserRichObserver) Update(action string, uid, objtype, objid int) {
324344
return
325345
} else if action == actionView {
326346
return
347+
} else if action == actionAppend {
348+
typ = model.MissionTypeAppend
349+
award = -15
350+
topic := DefaultTopic.findByTid(objid)
351+
desc = fmt.Sprintf(`为主题 › <a href="/topics/%d">%s</a> 增加附言`,
352+
topic.Tid,
353+
topic.Title)
327354
}
328355

329356
DefaultUserRich.IncrUserRich(user, typ, award, desc)

src/logic/topic.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,37 @@ func (TopicLogic) Modify(ctx context.Context, user *model.Me, form url.Values) (
178178
return
179179
}
180180

181+
// Append 主题附言
182+
func (self TopicLogic) Append(ctx context.Context, uid, tid int, content string) error {
183+
objLog := GetLogger(ctx)
184+
185+
// 当前已经附言了几条,最多 3 条
186+
num, err := MasterDB.Where("tid=?", tid).Count(new(model.TopicAppend))
187+
if err != nil {
188+
objLog.Errorln("TopicLogic Append error:", err)
189+
return err
190+
}
191+
192+
if num >= model.AppendMaxNum {
193+
return errors.New("不允许再发附言!")
194+
}
195+
196+
topicAppend := &model.TopicAppend{
197+
Tid: tid,
198+
Content: content,
199+
}
200+
_, err = MasterDB.Insert(topicAppend)
201+
202+
if err != nil {
203+
objLog.Errorln("TopicLogic Append insert error:", err)
204+
return err
205+
}
206+
207+
go appendObservable.NotifyObservers(uid, model.TypeTopic, tid)
208+
209+
return nil
210+
}
211+
181212
// FindAll 支持多页翻看
182213
func (self TopicLogic) FindAll(ctx context.Context, paginator *Paginator, orderBy string, querystring string, args ...interface{}) []map[string]interface{} {
183214
objLog := GetLogger(ctx)
@@ -343,6 +374,18 @@ func (TopicLogic) FindByPage(ctx context.Context, conds map[string]string, curPa
343374
return topicList, int(total)
344375
}
345376

377+
func (TopicLogic) FindAppend(ctx context.Context, tid int) []*model.TopicAppend {
378+
objLog := GetLogger(ctx)
379+
380+
topicAppends := make([]*model.TopicAppend, 0)
381+
err := MasterDB.Where("tid=?", tid).Find(&topicAppends)
382+
if err != nil {
383+
objLog.Errorln("TopicLogic FindAppend error:", err)
384+
}
385+
386+
return topicAppends
387+
}
388+
346389
func (TopicLogic) findByTid(tid int) *model.Topic {
347390
topic := &model.Topic{}
348391
_, err := MasterDB.Where("tid=?", tid).Get(topic)

src/model/mission.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ const (
2424
MissionTypeProject = 56
2525
MissionTypeBook = 57
2626

27+
MissionTypeAppend = 60
28+
2729
MissionTypeModify = 65
2830
// 被回复
2931
MissionTypeReplied = 70

src/model/topic.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ const (
1515
FlagUserDelete
1616
)
1717

18+
const (
19+
// 最多附言条数
20+
AppendMaxNum = 3
21+
)
22+
1823
// 社区主题信息
1924
type Topic struct {
2025
Tid int `xorm:"pk autoincr" json:"tid"`
@@ -82,6 +87,13 @@ func (*TopicInfo) TableName() string {
8287
return "topics"
8388
}
8489

90+
type TopicAppend struct {
91+
Id int `xorm:"pk autoincr"`
92+
Tid int
93+
Content string
94+
CreatedAt OftenTime `xorm:"<-"`
95+
}
96+
8597
// 社区主题节点信息
8698
type TopicNode struct {
8799
Nid int `json:"nid" xorm:"pk autoincr"`

src/model/user_rich.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ var BalanceTypeMap = map[int]string{
2424
MissionTypeWiki: "创建WIKI",
2525
MissionTypeProject: "发布项目",
2626
MissionTypeBook: "分享图书",
27+
MissionTypeAppend: "增加附言",
2728
MissionTypeModify: "修改",
2829
MissionTypeReplied: "回复收益",
2930
MissionTypeActive: "活跃奖励",

static/js/topic_append.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// 主题附言相关js功能
2+
(function(){
3+
emojify.setConfig({
4+
// emojify_tag_type : 'span',
5+
only_crawl_id : null,
6+
img_dir : SG.EMOJI_DOMAIN,
7+
ignored_tags : { //忽略以下几种标签内的emoji识别
8+
'SCRIPT' : 1,
9+
'TEXTAREA': 1,
10+
'A' : 1,
11+
'PRE' : 1,
12+
'CODE' : 1
13+
}
14+
});
15+
16+
SG.TopicAppend = function(){}
17+
SG.TopicAppend.prototype = new SG.Publisher();
18+
19+
jQuery(document).ready(function($) {
20+
// 文本框自动伸缩
21+
$('.need-autogrow').autoGrow();
22+
23+
$('#content').on('keydown', function(e) {
24+
if (e.keyCode == 9) {
25+
e.preventDefault();
26+
var indent = "\t";
27+
var start = this.selectionStart;
28+
var end = this.selectionEnd;
29+
var selected = window.getSelection().toString();
30+
selected = indent + selected.replace(/\n/g, '\n' + indent);
31+
this.value = this.value.substring(0, start) + selected
32+
+ this.value.substring(end);
33+
this.setSelectionRange(start + indent.length, start
34+
+ selected.length);
35+
}
36+
});
37+
38+
$('#content').on('input propertychange', function() {
39+
var markdownString = $(this).val();
40+
41+
// 配置 marked 语法高亮
42+
marked = SG.markSetting();
43+
44+
var contentHtml = marked(markdownString);
45+
contentHtml = SG.replaceCodeChar(contentHtml);
46+
47+
$('#content-preview').html(contentHtml);
48+
49+
// emoji 表情解析
50+
emojify.run($('#content-preview').get(0));
51+
});
52+
53+
// 提交附言
54+
$('#submit').on('click', function(evt){
55+
evt.preventDefault();
56+
var validator = $('.validate-form').validate();
57+
if (!validator.form()) {
58+
return false;
59+
}
60+
61+
// if ($('.usernames').length != 0) {
62+
// var usernames = SG.analyzeAt($('#content').val());
63+
// $('.usernames').val(usernames);
64+
// }
65+
66+
var topicAppend = new SG.TopicAppend();
67+
topicAppend.publish(this);
68+
});
69+
70+
$(document).keypress(function(evt){
71+
if (evt.ctrlKey && (evt.which == 10 || evt.which == 13)) {
72+
$('#submit').click();
73+
}
74+
});
75+
76+
SG.registerAtEvent();
77+
});
78+
}).call(this)

static/js/topics.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,20 @@
1616
SG.Topics = function(){}
1717
SG.Topics.prototype = new SG.Publisher();
1818
SG.Topics.prototype.parseContent = function(selector) {
19-
var markdownString = selector.text();
2019
// 配置 marked 语法高亮
2120
marked = SG.markSetting();
2221

23-
var contentHtml = marked(markdownString);
24-
contentHtml = SG.replaceCodeChar(contentHtml);
25-
26-
selector.html(contentHtml);
22+
selector.each(function() {
23+
var markdownString = $(this).text();
2724

28-
// emoji 表情解析
29-
emojify.run(selector.get(0));
25+
var contentHtml = marked(markdownString);
26+
contentHtml = SG.replaceCodeChar(contentHtml);
27+
28+
$(this).html(contentHtml);
29+
30+
// emoji 表情解析
31+
emojify.run(this);
32+
});
3033
}
3134

3235
jQuery(document).ready(function($) {

0 commit comments

Comments
 (0)