Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

增加清理附件按钮,对悬空无引用的图片/附件进行清理 #918

Merged
merged 4 commits into from
Dec 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ _testmain.go
mindoc
mindoc_linux_amd64
mindoc_linux_musl_amd64
database
database/mindoc.db
*.test
*.prof
.idea
Expand Down
56 changes: 56 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,3 +268,59 @@ docker run -p 8181:8181 --name mindoc -e DB_ADAPTER=mysql -e MYSQL_PORT_3306_TCP

一个不纯粹的PHPer,一个不自由的 gopher 。


# 部署补充
- 若内网部署,draw.io无法使用外网,则需要用tomcat运行war包,见(https://github.com/jgraph/drawio) 从release下载,之后修改markdown.js的TODO行对应的链接即可
- 为了护眼,简单增加了编辑界面的主题切换,见editormd.js和markdown_edit_template.tpl
- (需重新编译项)为了对已删除文档/文档引用图片删除文字后,对悬空无引用的图片/附件进行清理,增加了清理接口,需重新编译
- 编译后除二进制文件外还需更新三个文件: conf/lang/en-us.ini,zh-cn.ini; attach_list.tpl
- 若不想重新编译,也可通过database/clean.py,手动执行对无引用图片/附件的文件清理和数据库记录双向清理。
- 若采用nginx二级部署,以yourpath/为例,需修改
- conf/app.conf修改:`baseurl="/yourpath"`
- static/js/kancloud.js文件中`url: "/comment/xxxxx` => `url: "/yourpath" + "/comment/xxxxx`, 共两处

- nginx端口代理示例:
```
增加
location /yourpath/ {
rewrite ^/yourpath/(.*) /$1 break;
proxy_pass http://127.0.0.1:8181;
}
```
注意使用的是127.0.0.1,根据自身选择替换,如果nginx是docker部署,则还需要在docker中托管运行mindoc,具体参考如下配置:
- docker-compose代理示例(docker-nginx代理运行mindoc)
```
version: '3'
services:
mynginx:
image: nginx:latest
ports:
- "8880:80"
command:
- bash
- -c
- |
service nginx start
cd /src/mindoc/ && ./mindoc
volumes:
- ..:/src
- ./nginx:/etc/nginx/conf.d
```

目录结构
```
onefolder
|
- docker
|
- docker-compose.yml
- nginx
|
- mynginx.conf

- mindoc
|
- database/
- conf/
- ...
```
1 change: 1 addition & 0 deletions conf/lang/en-us.ini
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ yes = yes
no = no
read = Read
generate = Generate
clean = Clean

[init]
default_proj_name = MinDoc Demo Project
Expand Down
1 change: 1 addition & 0 deletions conf/lang/zh-cn.ini
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ yes = 是
no = 否
read = 阅读
generate = 生成
clean = 清理

[init]
default_proj_name = MinDoc演示项目
Expand Down
35 changes: 35 additions & 0 deletions controllers/ManagerController.go
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,41 @@ func (c *ManagerController) AttachList() {
c.Data["Lists"] = attachList
}

//附件清理.
func (c *ManagerController) AttachClean() {
c.Prepare()

attachList, _, err := models.NewAttachment().FindToPager(0, 0)

if err != nil {
c.Abort("500")
}

for _, item := range attachList {

p := filepath.Join(conf.WorkingDirectory, item.FilePath)

item.IsExist = filetil.FileExists(p)
if item.IsExist {
// 判断
searchList, err := models.NewDocumentSearchResult().SearchAllDocument(item.HttpPath)
if err != nil {
c.Abort("500")
} else if len(searchList) == 0 {
logs.Info("delete file:", item.FilePath)
item.FilePath = p
if err := item.Delete(); err != nil {
logs.Error("AttachDelete => ", err)
c.JsonResult(6002, err.Error())
break
}
}
}
}

c.JsonResult(0, "ok")
}

//附件详情.
func (c *ManagerController) AttachDetailed() {
c.Prepare()
Expand Down
34 changes: 34 additions & 0 deletions database/clean.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import sqlite3
import os, glob

conn = sqlite3.connect("mindoc.db")
cur = conn.cursor() #通过建立数据库游标对象,准备读写操作


cmd = """
SELECT
att.http_path
FROM
md_attachment AS att
WHERE (att.document_id != 0 OR (NOT EXISTS( SELECT 1 FROM md_documents WHERE markdown LIKE ("%" || att.http_path || "%"))))
AND (att.document_id = 0 OR (NOT EXISTS( SELECT 1 FROM md_documents WHERE att.document_id = document_id )))
"""
cur.execute(cmd)
file_list = cur.fetchall()
for file_item in file_list:
item_path = file_item[0]
# 1. 删除os文件
if os.path.exists(os.path.join("..", item_path[1:])):
os.remove(os.path.join("..", item_path[1:]))

# 2. 查询os是否删除成功,成功则删除附件记录
if not os.path.exists(os.path.join("..", item_path[1:])):
cmd = """
delete
from md_attachment
WHERE http_path = '{}'
""".format(item_path)
cur.execute(cmd)
conn.commit() #保存提交,确保数据保存成功

conn.close() #关闭与数据库的连接
8 changes: 6 additions & 2 deletions models/AttachmentModel.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,15 @@ func (m *Attachment) FindToPager(pageIndex, pageSize int) (attachList []*Attachm
return nil, 0, err
}
totalCount = int(total)
offset := (pageIndex - 1) * pageSize

var list []*Attachment

_, err = o.QueryTable(m.TableNameWithPrefix()).OrderBy("-attachment_id").Offset(offset).Limit(pageSize).All(&list)
offset := (pageIndex - 1) * pageSize
if pageSize == 0 {
_, err = o.QueryTable(m.TableNameWithPrefix()).OrderBy("-attachment_id").Offset(offset).Limit(pageSize).All(&list)
} else {
_, err = o.QueryTable(m.TableNameWithPrefix()).OrderBy("-attachment_id").All(&list)
}

if err != nil {
if err == orm.ErrNoRows {
Expand Down
20 changes: 20 additions & 0 deletions models/DocumentSearchResult.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,3 +309,23 @@ func (m *DocumentSearchResult) SearchDocument(keyword string, bookId int) (docs

return
}

// 所有项目搜索.
func (m *DocumentSearchResult) SearchAllDocument(keyword string) (docs []*DocumentSearchResult, err error) {
o := orm.NewOrm()

sql := "SELECT * FROM md_documents WHERE (document_name LIKE ? OR `release` LIKE ?) "
keyword = "%" + keyword + "%"

_need_escape := need_escape(keyword)
escape_sql := func(sql string) string {
if _need_escape {
return escape_re.ReplaceAllString(sql, escape_replace)
}
return sql
}

_, err = o.Raw(escape_sql(sql), keyword, keyword).QueryRows(&docs)

return
}
1 change: 1 addition & 0 deletions routers/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ func init() {
web.Router("/manager/books/open", &controllers.ManagerController{}, "post:PrivatelyOwned")

web.Router("/manager/attach/list", &controllers.ManagerController{}, "*:AttachList")
web.Router("/manager/attach/clean", &controllers.ManagerController{}, "post:AttachClean")
web.Router("/manager/attach/detailed/:id", &controllers.ManagerController{}, "*:AttachDetailed")
web.Router("/manager/attach/delete", &controllers.ManagerController{}, "post:AttachDelete")
web.Router("/manager/label/list", &controllers.ManagerController{}, "get:LabelList")
Expand Down
22 changes: 16 additions & 6 deletions static/editor.md/editormd.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,20 +71,20 @@
"list-ul", "list-ol", "hr", "|",
"link", "reference-link", "image", "code", "preformatted-text", "code-block", "table", "datetime", "emoji", "html-entities", "pagebreak", "|",
"goto-line", "watch", "preview", "fullscreen", "clear", "search", "|",
"help", "info"
"help", "changetheme", "info"
],
simple : [
"undo", "redo", "|",
"bold", "del", "italic", "quote", "uppercase", "lowercase", "|",
"h1", "h2", "h3", "h4", "h5", "h6", "|",
"list-ul", "list-ol", "hr", "|",
"watch", "preview", "fullscreen", "|",
"help", "info"
"help", "changetheme", "info"
],
mini : [
"undo", "redo", "|",
"watch", "preview", "|",
"help", "info"
"help", "changetheme", "info"
]
};

Expand All @@ -94,8 +94,8 @@
name : "", // Form element name
value : "", // value for CodeMirror, if mode not gfm/markdown
theme : "", // Editor.md self themes, before v1.5.0 is CodeMirror theme, default empty
editorTheme : "default", // Editor area, this is CodeMirror theme at v1.5.0
previewTheme : "", // Preview area theme, default empty
editorTheme : "pastel-on-dark", //"default", // Editor area, this is CodeMirror theme at v1.5.0
previewTheme : "dark", //"", // Preview area theme, default empty
markdown : "", // Markdown source code
appendMarkdown : "", // if in init textarea value not empty, append markdown to textarea
width : "100%",
Expand Down Expand Up @@ -225,6 +225,7 @@
fullscreen : "fa-arrows-alt",
clear : "fa-eraser",
help : "fa-question-circle",
changetheme : "fa-info-circle",
info : "fa-info-circle"
},
toolbarIconTexts : {},
Expand Down Expand Up @@ -271,6 +272,7 @@
clear : "清空",
search : "搜索",
help : "使用帮助",
changetheme : "切换编辑主题",
info : "关于" + editormd.title
},
buttons : {
Expand Down Expand Up @@ -322,7 +324,10 @@
},
help : {
title : "使用帮助"
}
},
changetheme : {
title : "切换编辑主题"
},
}
}
};
Expand Down Expand Up @@ -3385,6 +3390,11 @@
this.executePlugin("helpDialog", "help-dialog/help-dialog");
},

changetheme : function() {
this.setEditorTheme((this.settings.editorTheme=="default")?"pastel-on-dark":"default");
this.setPreviewTheme((this.settings.previewTheme=="")?"dark":"");
},

info : function() {
this.showInfoDialog();
}
Expand Down
2 changes: 1 addition & 1 deletion static/js/markdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ $(function () {

drawio.show = function () {

const drawUrl = 'https://embed.diagrams.net/?embed=1&libraries=1&proto=json&spin=1&saveAndExit=1&noSaveBtn=1&noExitBtn=0';
const drawUrl = 'https://embed.diagrams.net/?embed=1&libraries=1&proto=json&spin=1&saveAndExit=1&noSaveBtn=1&noExitBtn=0'; // TODO: with Tomcat & https://github.com/jgraph/drawio
this.div = document.createElement('div');
this.div.id = 'diagram';
this.gXml = '';
Expand Down
10 changes: 3 additions & 7 deletions views/document/markdown_edit_template.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,6 @@
<div class="editormd-group">
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.h1"}}"><i class="fa editormd-bold first" name="h1" unselectable="on">H1</i></a>
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.h2"}}"><i class="fa editormd-bold item" name="h2" unselectable="on">H2</i></a>
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.h3"}}"><i class="fa editormd-bold item" name="h3" unselectable="on">H3</i></a>
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.h4"}}"><i class="fa editormd-bold item" name="h4" unselectable="on">H4</i></a>
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.h5"}}"><i class="fa editormd-bold item" name="h5" unselectable="on">H5</i></a>
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.h6"}}"><i class="fa editormd-bold last" name="h6" unselectable="on">H6</i></a>
</div>
<div class="editormd-group">
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.unorder_list"}}"><i class="fa fa-list-ul first" name="list-ul" unselectable="on"></i></a>
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.order_list"}}"><i class="fa fa-list-ol item" name="list-ol" unselectable="on"></i></a>
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.hline"}}"><i class="fa fa-minus last" name="hr" unselectable="on"></i></a>
Expand All @@ -111,10 +105,12 @@
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.modify_history"}}"><i class="fa fa-history item" name="history" aria-hidden="true"></i></a>
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.sidebar"}}"><i class="fa fa-columns item" aria-hidden="true" name="sidebar"></i></a>
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.help"}}"><i class="fa fa-question-circle-o last" aria-hidden="true" name="help"></i></a>
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.changetheme"}}"><i class="fa fa-paint-brush item" aria-hidden="true" name="changetheme"></i></a>
</div>

<div class="editormd-group pull-right">
<a target="_blank" href="{{urlfor "DocumentController.Read" ":key" .Model.Identify ":id" ""}}" data-toggle="tooltip" data-title="{{i18n .Lang "blog.preview"}}"><i class="fa fa-external-link" name="preview-open" aria-hidden="true"></i></a>
<!--<a target="_blank" href="{{urlfor "DocumentController.Read" ":key" .Model.Identify ":id" ""}}" data-toggle="tooltip" data-title="{{i18n .Lang "blog.preview"}}"><i class="fa fa-external-link" name="preview-open" aria-hidden="true"></i></a>-->
<a href="{{urlfor "DocumentController.Read" ":key" .Model.Identify ":id" ""}}" data-toggle="tooltip" data-title="{{i18n .Lang "blog.preview"}}"><i class="fa fa-external-link" name="preview-open" aria-hidden="true"></i></a>
<a href="javascript:;" data-toggle="tooltip" data-title="{{i18n .Lang "doc.publish"}}"><i class="fa fa-cloud-upload" name="release" aria-hidden="true"></i></a>
</div>

Expand Down
26 changes: 25 additions & 1 deletion views/manager/attach_list.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@
{{template "manager/widgets.tpl" .}}
<div class="page-right">
<div class="m-box">
<div class="box-head">
<div class="box-head" id="attachAll">
<strong class="box-title">{{i18n .Lang "mgr.attachment_mgr"}}</strong>
<button type="button" data-method="clean" class="btn btn-danger btn-sm" data-loading-text="{{i18n $.Lang "message.processing"}}">{{i18n $.Lang "common.clean"}}</button>
</div>
</div>
<div class="box-body">
Expand Down Expand Up @@ -104,6 +105,29 @@
}
});
});

$("#attachAll").on("click","button[data-method='clean']",function () {
var $this = $(this);
$(this).button("loading");
$.ajax({
url : "{{urlfor "ManagerController.AttachClean"}}",
type : "post",
dataType : "json",
success : function (res) {
if(res.errcode === 0){
alert("done");
}else {
layer.msg(res.message);
}
},
error : function () {
layer.msg({{i18n .Lang "message.system_error"}});
},
complete : function () {
$this.button("reset");
}
});
});
});
</script>
</body>
Expand Down