Skip to content

Commit

Permalink
编辑帖子
Browse files Browse the repository at this point in the history
  • Loading branch information
bbbbbbbbbbbbba committed Jun 28, 2019
1 parent b84c69b commit e7edb78
Show file tree
Hide file tree
Showing 13 changed files with 314 additions and 11 deletions.
53 changes: 53 additions & 0 deletions controllers/topic_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,59 @@ func (this *TopicController) PostCreate() *simple.JsonResult {
return simple.NewEmptyRspBuilder().Put("topicId", topic.Id).JsonResult()
}

func (this *TopicController) GetEditBy(topicId int64) {
user := session.GetCurrentUser(this.Ctx)
if user == nil {
this.Ctx.StatusCode(403)
return
}

topic := this.TopicService.Get(topicId)
if topic == nil || topic.Status != model.TopicStatusOk || topic.UserId != user.Id {
this.Ctx.StatusCode(404)
return
}

tags := this.TopicService.GetTopicTags(topicId)
var tagNames []string
if len(tags) > 0 {
for _, tag := range tags {
tagNames = append(tagNames, tag.Name)
}
}

render.View(this.Ctx, "topic/edit.html", iris.Map{
"Topic": iris.Map{
"TopicId": topic.Id,
"Title": topic.Title,
"Content": topic.Content,
"Tags": tagNames,
},
})
}

func (this *TopicController) PostEditBy(topicId int64) *simple.JsonResult {
user := session.GetCurrentUser(this.Ctx)
if user == nil {
return simple.Error(simple.ErrorNotLogin)
}

topic := this.TopicService.Get(topicId)
if topic == nil || topic.Status != model.TopicStatusOk || topic.UserId != user.Id {
return simple.ErrorMsg("话题不存在或已被删除")
}

title := strings.TrimSpace(simple.FormValue(this.Ctx, "title"))
content := strings.TrimSpace(simple.FormValue(this.Ctx, "content"))
tags := simple.FormValueStringArray(this.Ctx, "tags")

err := this.TopicService.Edit(topicId, tags, title, content)
if err != nil {
return simple.Error(err)
}
return simple.NewEmptyRspBuilder().Put("topicId", topic.Id).JsonResult()
}

// 收藏
func (this *TopicController) PostFavoriteBy(topicId int64) *simple.JsonResult {
user := session.GetCurrentUser(this.Ctx)
Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"github.com/sirupsen/logrus"
)

var configFile = flag.String("config", "./mlog.json", "配置文件路径")
var configFile = flag.String("config", "./mlog.yaml", "配置文件路径")

func init() {
flag.Parse()
Expand Down
8 changes: 8 additions & 0 deletions repositories/topic_tag_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,11 @@ func (this *TopicTagRepository) AddTopicTags(db *gorm.DB, topicId int64, tagIds
})
}
}

func (this *TopicTagRepository) RemoveTopicTags(db *gorm.DB, topicId int64) {
if topicId <= 0 {
return
}

db.Where("topic_id = ?", topicId).Delete(model.TopicTag{})
}
26 changes: 26 additions & 0 deletions services/topic_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,32 @@ func (this *TopicService) Publish(userId int64, tags []string, title, content st
return topic, simple.NewError2(err)
}

// 更新
func (this *TopicService) Edit(topicId int64, tags []string, title, content string) *simple.CodeError {
if len(title) == 0 {
return simple.NewErrorMsg("标题不能为空")
}

if simple.RuneLen(title) > 128 {
return simple.NewErrorMsg("标题长度不能超过128")
}

err := simple.Tx(simple.GetDB(), func(tx *gorm.DB) error {
tagIds := this.TagRepository.GetOrCreates(tx, tags)
err := this.TopicRepository.Updates(simple.GetDB(), topicId, map[string]interface{}{
"title": title,
"content": content,
})
if err != nil {
return err
}
this.TopicTagRepository.RemoveTopicTags(tx, topicId) // 先删掉所有的标签
this.TopicTagRepository.AddTopicTags(tx, topicId, tagIds) // 然后重新添加标签
return nil
})
return simple.NewError2(err)
}

// 帖子标签
func (this *TopicService) GetTopicTags(topicId int64) []model.Tag {
topicTags, err := this.TopicTagRepository.QueryCnd(simple.GetDB(), simple.NewQueryCnd("topic_id = ?", topicId))
Expand Down
8 changes: 4 additions & 4 deletions utils/session/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
)

const (
SessionCurrentUser = "CurrentUser"
CurrentUser = "CurrentUser"
)

func InitSessionManager() {
Expand Down Expand Up @@ -43,7 +43,7 @@ func StartByRequest(w http.ResponseWriter, r *http.Request) session.Store {

func SetCurrentUser(ctx context.Context, user *model.User) {
store := Start(ctx)
store.Set(SessionCurrentUser, user)
store.Set(CurrentUser, user)
err := store.Save()
if err != nil {
logrus.Error(err)
Expand All @@ -55,7 +55,7 @@ func GetCurrentUser(ctx context.Context) *model.User {
}

func GetCurrentUserByRequest(w http.ResponseWriter, r *http.Request) *model.User {
val, exists := StartByRequest(w, r).Get(SessionCurrentUser)
val, exists := StartByRequest(w, r).Get(CurrentUser)
if exists {
json, err := simple.FormatJson(val)
if err != nil {
Expand All @@ -74,7 +74,7 @@ func GetCurrentUserByRequest(w http.ResponseWriter, r *http.Request) *model.User

func DelCurrentUser(ctx context.Context) {
store := Start(ctx)
store.Delete(SessionCurrentUser)
store.Delete(CurrentUser)
err := store.Save()
if err != nil {
logrus.Error(err)
Expand Down
4 changes: 4 additions & 0 deletions web/static/styles/topic.scss
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@
&.tag {
height: auto !important;
}

&.btn a {
color: #3273dc;
}
}

a {
Expand Down
2 changes: 1 addition & 1 deletion web/views/article/create.html
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
toolbar: ['emoji', 'headings', 'bold', 'italic', 'strike', '|', 'line', 'quote', 'list', 'ordered-list', 'check', 'code',
'inline-code', 'undo', 'redo', 'upload', 'link', 'table', 'preview', 'fullscreen'],
upload: {
accept: 'image/*,.pdf',
accept: 'image/*',
token: 'test',
url: '{{baseUrl}}/upload/editor',
linkToImgUrl: '{{baseUrl}}/upload/fetch',
Expand Down
2 changes: 1 addition & 1 deletion web/views/article/edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
toolbar: ['emoji', 'headings', 'bold', 'italic', 'strike', '|', 'line', 'quote', 'list', 'ordered-list', 'check', 'code',
'inline-code', 'undo', 'redo', 'upload', 'link', 'table', 'preview', 'fullscreen'],
upload: {
accept: 'image/*,.pdf',
accept: 'image/*',
token: 'test',
url: '{{baseUrl}}/upload/editor',
linkToImgUrl: '{{baseUrl}}/upload/fetch',
Expand Down
16 changes: 14 additions & 2 deletions web/views/topic/create.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@
<div class="tags-selected">
<span class="tag-item" v-for="tag in tags" :key="tag">
<span class="text">{{html "{{tag}}"}}<i
class="iconfont icon-close"></i></span>
class="iconfont icon-close"
@click="clickRemoveTag"
:data-name="tag"></i></span>
</span>
</div>
<input ref="tagInput" class="input" type="text" v-model="inputTag"
Expand Down Expand Up @@ -90,7 +92,7 @@
'inline-code', 'undo', 'redo', 'upload', 'link', 'table', 'preview', 'fullscreen'],
placeholder: '讨论内容(可为空)',
upload: {
accept: 'image/*,.pdf',
accept: 'image/*',
token: 'test',
url: '{{baseUrl}}/upload/editor',
linkToImgUrl: '{{baseUrl}}/upload/fetch',
Expand Down Expand Up @@ -131,6 +133,16 @@
}
},

clickRemoveTag(event) {
var tag = event.target.dataset.name
if (tag) {
var index = this.tags.indexOf(tag)
if (index !== -1) {
this.tags.splice(index, 1);
}
}
},

addTag(event) {
event.stopPropagation()
event.preventDefault()
Expand Down
172 changes: 172 additions & 0 deletions web/views/topic/edit.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
{{template "common/header.html" .}}
{{template "common/nav.html" .}}

<section class="main">
<div class="container">

<div class="columns">
<div class="column is-21">
<div class="widget">
<div class="header">
<nav class="breadcrumb" aria-label="breadcrumbs">
<ul>
<li><a href="{{baseUrl}}">首页</a></li>
<li><a href="{{baseUrl}}/user/{{.CurrentUser.Id}}?tab=topics">{{.CurrentUser.Nickname}}</a></li>
<li class="is-active"><a href="#" aria-current="page">讨论</a></li>
</ul>
</nav>
</div>
<div class="content">
<div class="field">
<div class="control">
<input name="title" id="title" class="input" type="text" value="{{.Topic.Title}}"
placeholder="请输入标题,如果标题能够表达完整内容,则正文可以为空">
</div>
</div>

<div class="field">
<div class="control">
<div id="editor" style="border: 1px solid #d1d5da;"></div>
</div>
</div>


<div class="field">
<label class="label">标签</label>
<div class="control">
<div id="select-tags" class="select-tags">
<input id="tags" name="tags" type="hidden" v-model="tags"/>
<div class="tags-selected">
<span class="tag-item" v-for="tag in tags" :key="tag">
<span class="text">{{html "{{tag}}"}}<i
class="iconfont icon-close"
@click="clickRemoveTag"
:data-name="tag"></i></span>
</span>
</div>
<input ref="tagInput" class="input" type="text" v-model="inputTag"
@keydown.delete="removeTag" @keydown.enter="addTag"
@keydown.32="addTag" @keydown.186="addTag" @keydown.188="addTag"
placeholder="标签(请用逗号分隔每个标签,最多4个,每个最长15字符)">
</div>
</div>
</div>

<div class="field is-grouped">
<div class="control">
<a class="button is-success" id="topicEditSubmit">发表讨论</a>
</div>
</div>
</div>
</div>
</div>
<div class="column is-3">
<div class="widget">
<div class="header">Markdown 语法参考</div>
<div class="content">
<ol>
<li><tt>### 单行的标题</tt></li>
<li><tt>**粗体**</tt></li>
<li><tt>`console.log('行内代码')`</tt></li>
<li><tt>```js\n code \n```</tt> 标记代码块</li>
<li><tt>[内容](链接)</tt></li>
<li><tt>![文字说明](图片链接)</tt></li>
</ol>
<span><a href="https://www.mlog.club/article/5522" target="_blank">Markdown 文档</a></span>
</div>
</div>
</div>
</div>

</div>
</section>

<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/vditor/dist/index.classic.css"/>
<script src="//cdn.jsdelivr.net/npm/vditor/dist/index.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
const vditor = new Vditor('editor', {
cache: false,
height: 400,
toolbar: ['emoji', 'headings', 'bold', 'italic', 'strike', '|', 'line', 'quote', 'list', 'ordered-list', 'check', 'code',
'inline-code', 'undo', 'redo', 'upload', 'link', 'table', 'preview', 'fullscreen'],
placeholder: '讨论内容(可为空)',
upload: {
accept: 'image/*',
token: 'test',
url: '{{baseUrl}}/upload/editor',
linkToImgUrl: '{{baseUrl}}/upload/fetch',
filename(name) {
return name.replace(/\?|\\|\/|:|\||<|>|\*|\[|\]|\s+/g, '-')
}
},
})
vditor.setValue('{{.Topic.Content}}')
vditor.focus()

$('#topicEditSubmit').click(function () {
var params = {
title: $('#title').val(),
content: vditor.getValue(),
tags: $('#tags').val(),
}
httpPost('{{baseUrl}}/topic/edit/{{.Topic.TopicId}}', params).then(function (data) {
window.location = '{{baseUrl}}/topic/' + data.topicId
}, function (response) {
alert(response.message)
})
})
})

var app = new Vue({
el: '#select-tags',
data: {
inputTag: '',
tags: [
{{if .Topic.Tags}} {{range .Topic.Tags}} '{{.}}', {{end}} {{end}}
]
},
mounted() {
},
methods: {
removeTag(event, tag) {
var selectionStart = this.$refs.tagInput.selectionStart
if (!this.inputTag || selectionStart === 0) { // input框没内容,或者光标在首位的时候就删除最后一个标签
this.tags.splice(this.tags.length - 1, 1);
}
},

clickRemoveTag(event) {
var tag = event.target.dataset.name
if (tag) {
var index = this.tags.indexOf(tag)
if (index !== -1) {
this.tags.splice(index, 1);
}
}
},

addTag(event) {
event.stopPropagation()
event.preventDefault()

if (!this.inputTag) {
return;
}
if (this.tags.indexOf(this.inputTag) !== -1) {
return;
}
if (this.tags.length >= 4) { // 最多四个标签
return;
}
if (this.inputTag.length > 15) { // 每个标签最多15个字符
return;
}
this.tags.push(this.inputTag);
this.inputTag = ''
}
}
})
</script>

{{template "common/footer.html" .}}
Loading

0 comments on commit e7edb78

Please sign in to comment.