Skip to content

Commit

Permalink
添加功能:云存储支持直接创建文本文件#698
Browse files Browse the repository at this point in the history
  • Loading branch information
admpub committed Mar 21, 2024
1 parent 63043a7 commit 8bd4faf
Show file tree
Hide file tree
Showing 11 changed files with 183 additions and 30 deletions.
18 changes: 18 additions & 0 deletions application/handler/cloud/storage_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (

"github.com/webx-top/com"
"github.com/webx-top/echo"
"github.com/webx-top/echo/code"

"github.com/admpub/nging/v5/application/handler"
"github.com/admpub/nging/v5/application/library/config"
Expand Down Expand Up @@ -99,6 +100,23 @@ func StorageFile(ctx echo.Context) error {
}
}
return ctx.JSON(data)
case `createFile`:
data := ctx.Data()
if ctx.IsPost() {
fileName := ctx.Formx(`name`).String()
if len(fileName) == 0 {
return ctx.JSON(data.SetError(ctx.NewError(code.InvalidParameter, `请输入文件名`).SetZone(`name`)))
}
content := ctx.Form(`content`)
encoding := ctx.Form(`encoding`)
err := mgr.CreateFile(ctx, path.Join(ppath, fileName), content, encoding)
if err != nil {
data.SetInfo(err.Error(), 0)
} else {
data.SetInfo(ctx.T(`保存成功`), 1)
}
}
return ctx.JSON(data)
case `mkdir`:
data := ctx.Data()
newName := ctx.Form(`name`)
Expand Down
22 changes: 22 additions & 0 deletions application/library/filemanager/filemanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
uploadClient "github.com/webx-top/client/upload"
"github.com/webx-top/com"
"github.com/webx-top/echo"
"github.com/webx-top/echo/code"
)

var (
Expand Down Expand Up @@ -93,6 +94,27 @@ func (f *fileManager) Edit(absPath string, content string, encoding string) (int
return string(b), err
}

func (f *fileManager) CreateFile(absPath string, content string, encoding string) error {
_, err := os.Stat(absPath)
if err == nil {
return f.NewError(code.DataAlreadyExists, `新建文件失败,文件已经存在`)
}
if !os.IsNotExist(err) {
return err
}
encoding = strings.ToLower(encoding)
isUTF8 := encoding == `` || encoding == `utf-8`
b := []byte(content)
if !isUTF8 {
b, err = charset.Convert(`utf-8`, encoding, b)
if err != nil {
return err
}
}
err = os.WriteFile(absPath, b, 0664)
return err
}

func (f *fileManager) Remove(absPath string) error {
fi, err := os.Stat(absPath)
if err != nil {
Expand Down
30 changes: 19 additions & 11 deletions application/library/modal/modal.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,26 @@ type Button struct {
Text string //按钮文本
}

type ButtonDefault struct {
DisableClose bool
Disabled bool
Button
}

type Modal struct {
Id string //元素id
Custom bool //是否自定义整个内容区域
Full bool // 是否铺满整个页面
HeadTitle string //头部标题
Title string //内容标题
Content string //内容
HelpText string //帮助提示
Animate string //动画样式class名
Type string //类型:warning/primary/success/danger
ContentType string //内容类型:form/blackform/""
ExtButtons []Button //附加按钮 [{Text:"🔃重载",Attributes:[{Attr:"class",Value:"btn btn-warning btn-reload"}]}]
Id string //元素id
Custom bool //是否自定义整个内容区域
Full bool // 是否铺满整个页面
HeadTitle string //头部标题
Title string //内容标题
Content string //内容
HelpText string //帮助提示
Animate string //动画样式class名
Type string //类型:warning/primary/success/danger
ContentType string //内容类型:form/blackform/""
ExtButtons []Button //附加按钮 [{Text:"🔃重载",Attributes:[{Attr:"class",Value:"btn btn-warning btn-reload"}]}]
ButtonCancel ButtonDefault
ButtonSubmit ButtonDefault
}

func UnmarshalFile(ctx echo.Context, confile string) (Modal, error) {
Expand Down
27 changes: 27 additions & 0 deletions application/library/s3manager/s3manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import (
minio "github.com/minio/minio-go/v7"
"github.com/webx-top/com"
"github.com/webx-top/echo"
"github.com/webx-top/echo/code"

uploadClient "github.com/webx-top/client/upload"
)
Expand Down Expand Up @@ -140,6 +141,32 @@ func (s *S3Manager) Edit(ctx echo.Context, ppath string, content string, encodin
return string(dat), err
}

func (s *S3Manager) CreateFile(ctx echo.Context, ppath string, content string, encoding string) (err error) {
var exists bool
exists, err = s.Exists(ctx, ppath)
if err != nil {
return
}
if exists {
return ctx.NewError(code.DataAlreadyExists, `新建文件失败,文件已经存在`)
}
encoding = strings.ToLower(encoding)
isUTF8 := len(encoding) == 0 || encoding == `utf-8`
b := []byte(content)
if !isUTF8 {
b, err = charset.Convert(`utf-8`, encoding, b)
if err != nil {
return
}
}
r := bytes.NewReader(b)
err = s.Put(ctx, r, ppath, int64(len(b)))
if err != nil {
err = ctx.E(ppath + `:` + err.Error())
}
return
}

func (s *S3Manager) Mkbucket(ctx context.Context, bucketName string, regions ...string) error {
var region string
if len(regions) > 0 {
Expand Down
7 changes: 7 additions & 0 deletions config/config.yaml.sample
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ sys {
htm : "html"
js : "javascript"
go : "golang"
asp : "asp"
php : "php"
jsp : "jsp"
cs : "csharp"
java : "java"
css : "css"
txt : "txt"
xml : "xml"
Expand All @@ -30,6 +34,9 @@ sys {
yaml : "yaml"
yml : "yaml"
log : "log"
json : "json"
toml : "toml"
conf : "conf"
}
editableFileMaxSize : "1M" #允许在线编辑的最大文件尺寸
errorPages : { #指定错误页面模板
Expand Down
73 changes: 59 additions & 14 deletions public/assets/backend/js/behaviour/page/file.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var editor;
var editor,creator;
function resetCheckedbox() {
$('#checkedAll:checked').prop('checked', false);
$('#tbody-content input[type=checkbox][name="path[]"]:checked').prop('checked', false);
Expand All @@ -19,20 +19,24 @@ function refreshList() {
},'html');
}
function initCodeMirrorEditor() {
editor = CodeMirror.fromTextArea($("#file-edit-content")[0], {
lineNumbers: true,
theme: 'ambiance',
extraKeys: {
"F11": function(cm) {
cm.setOption("fullScreen", !cm.getOption("fullScreen"));
},
"Esc": function(cm) {
if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false);
var cfg = {
lineNumbers: true,
theme: 'ambiance',
extraKeys: {
"F11": function(cm) {
cm.setOption("fullScreen", !cm.getOption("fullScreen"));
},
"Esc": function(cm) {
if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false);
}
}
}
});
editor.setOption('lineWrapping', true);
editor.setSize('auto', '100%');
}, newInstance=function(obj){
var editor = CodeMirror.fromTextArea(obj, cfg);
editor.setOption('lineWrapping', true);
editor.setSize('auto', '100%');
return editor
};
editor = newInstance($("#file-edit-content")[0]);
$('#file-edit-modal .modal-footer .btn-success').on('click',function(){
var url=$(this).data('url');
var enc=$('#use-encoding-open').val();
Expand All @@ -42,6 +46,27 @@ function initCodeMirrorEditor() {
return App.message({title: App.i18n.SYS_INFO, text: App.i18n.SAVE_SUCCEED},false);
},'json');
});
if($("#file-create-content").length>0){
creator = newInstance($("#file-create-content")[0]);
$('#file-create-name').on('change',function(){
var file=$(this).val();
codeMirrorChangeMode(creator,file);
});
}
$('#file-create-modal .modal-footer .btn-primary:last').on('click',function(ev){
var url=$(this).data('url'),enc=$('#use-encoding-save').val(),fileName=$.trim($('#file-create-name').val());
if(!fileName){
App.message({text: App.t('请输入文件名'), type: 'error'});
$('#file-create-name').focus();
return;
}
if(!enc)enc='';
$.post(url,{content:creator.getValue(),encoding:enc,name:fileName},function(r){
if(r.Code!=1)return App.message({title: App.i18n.SYS_INFO, text: r.Info},false);
App.message({title: App.i18n.SYS_INFO, text: App.i18n.SAVE_SUCCEED},false);
$('#file-create-modal').niftyModal('hide');refreshList();
},'json');
});
$('#file-edit-modal .modal-body').css('padding',0);
$('#use-encoding-open').on('change',function(){
var enc=$(this).val();
Expand Down Expand Up @@ -82,6 +107,25 @@ function fileEdit(obj,file) {
},'json');
}

function fileCreate(obj) {
var url=$(obj).data('url');
$('#file-create-modal .modal-footer .btn-primary:last').data('url',url);
$('#file-create-modal .modal-header h3').html(App.i18n.CREATE_FILE);
$('#file-create-modal').niftyModal('show',{
afterOpen: function(modal) {
$('#file-create-name').val('');
creator.setValue('');
creator.refresh();
setTimeout(function(){
$('#file-create-name').focus();
},500)
},
afterClose: function(modal) {
$('#use-encoding-save').find('option:selected').prop('selected',false);
}
});
}

function fileRename(obj,file,isDir) {
var url=$(obj).data('url');
$('#file-rename-modal .modal-footer .btn-primary:last').data('url',url);
Expand Down Expand Up @@ -214,6 +258,7 @@ $(function(){
initCodeMirrorEditor();
$(window).off().on('resize',function(){
$('#file-edit-form,#file-play-video').css({height:$(window).height()-150,width:'100%','max-width':'100%',overflow:'auto'});
$('#file-create-form').css({height:$(window).height()-180,width:'100%','max-width':'100%',overflow:'auto'});
$('#file-play-video > video').css({height:'100%'});
});
$(window).trigger('resize');
Expand Down
2 changes: 1 addition & 1 deletion public/assets/backend/js/behaviour/page/file.min.js

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions template/backend/cloud/storage_file.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@
<button type="button" id="mkdirBtn" class="btn btn-success" data-content="{{`在当前目录下新建文件夹`|$.T}}" data-popover="popover" data-container="body" data-trigger="hover" data-placement="top" data-url="{{BackendURL}}/cloud/storage_file?id={{$id}}&do=mkdir&path={{$pathPrefix}}" onclick="fileMkdir(this)">
<i class="fa fa-plus"></i>
{{"新建文件夹"|$.T}}
</button>
<button type="button" id="createFileBtn" class="btn btn-warning" data-content="{{`在当前目录下新建文件`|$.T}}" data-popover="popover" data-container="body" data-trigger="hover" data-placement="top" data-url="{{BackendURL}}/cloud/storage_file?id={{$id}}&do=createFile&path={{$pathPrefix}}" onclick="fileCreate(this)">
<i class="fa fa-plus"></i>
{{"新建文件"|$.T}}
</button>
<span class="input-group" style="padding-left:10px">
<input type="text" id="query-current-path" name="query" class="form-control typeahead" required="required" value="{{$.Form `query`}}" data-provide="typeahead">
Expand Down
2 changes: 2 additions & 0 deletions template/backend/filemanager/file.script.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
{{call $.Func.Modal "__TMPL__/filemanager/file.yaml"}}
{{call $.Func.Modal "__TMPL__/filemanager/file_zip.yaml"}}
{{call $.Func.Modal "__TMPL__/filemanager/file_edit.yaml"}}
{{call $.Func.Modal "__TMPL__/filemanager/file_create.yaml"}}
{{call $.Func.Modal "__TMPL__/filemanager/file_rename.yaml"}}
{{call $.Func.Modal "__TMPL__/filemanager/file_mkdir.yaml"}}
{{call $.Func.Modal "__TMPL__/filemanager/file_play.yaml"}}
Expand All @@ -18,6 +19,7 @@
App.i18n.MODIFY_DIRNAME='{{"修改文件夹名"|$.T}}';
App.i18n.MODIFY_FILENAME='{{"修改文件名"|$.T}}';
App.i18n.EDIT_FILE='{{"编辑文件"|$.T}}';
App.i18n.CREATE_FILE='{{"创建文件"|$.T}}';
App.i18n.PLAY='{{"播放"|$.T}}';
App.i18n.SELECTED_ITEMS='{{"您已经选择了%d条数据"|$.T}}';
</script>
Expand Down
12 changes: 12 additions & 0 deletions template/backend/filemanager/file_create.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Id : "file-create-modal"
Custom : true
Full : true
HeadTitle : "新建文件"
Title : ""
HelpText : "文件编码:<select id='use-encoding-save'><option value='utf-8'>UTF-8</option><option value='gbk'>GBK</option></select>"
Content : "<form action='' id='file-create-form'><span class='input-group'><span class='input-group-addon'><i class='fa fa-file'></i></span><input name='name' class='form-control' id='file-create-name' value='' placeholder='请输入文件名'></span><textarea name='content' class='form-control' id='file-create-content'></textarea></form>"
Type : "primary"
ExtButtons : []
ButtonSubmit : {
DisableClose : true
}
16 changes: 12 additions & 4 deletions template/backend/modal.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,12 @@
{{- range $k, $v := .ExtButtons -}}
<button type="button" data-dismiss="modal"{{range $bk, $bv := $v.Attributes}} {{$bv.Attr|ToHTMLAttr}}="{{$bv.Value}}"{{else}} class="btn btn-default"{{end}}>{{$v.Text}}</button>
{{- end -}}
<button type="button" class="btn btn-default" data-dismiss="modal">{{"取消"|$.T}}</button>
<button type="button" class="btn btn-{{if .Type}}{{.Type}}{{else}}primary{{end}}" data-dismiss="modal">{{"确定"|$.T}}</button>
{{- if not .ButtonCancel.Disabled -}}
<button type="button"{{range $bk, $bv := .ButtonCancel.Attributes}} {{$bv.Attr|ToHTMLAttr}}="{{$bv.Value}}"{{else}} class="btn btn-default"{{end}}{{if not .ButtonCancel.DisableClose}} data-dismiss="modal"{{end}}>{{if .ButtonCancel.Text}}{{.ButtonCancel.Text|$.T}}{{else}}{{"取消"|$.T}}{{end}}</button>
{{- end -}}
{{- if not .ButtonSubmit.Disabled -}}
<button type="button"{{range $bk, $bv := .ButtonSubmit.Attributes}} {{$bv.Attr|ToHTMLAttr}}="{{$bv.Value}}"{{else}} class="btn btn-{{if .Type}}{{.Type}}{{else}}primary{{end}}"{{end}}{{if not .ButtonSubmit.DisableClose}} data-dismiss="modal"{{end}}>{{if .ButtonSubmit.Text}}{{.ButtonSubmit.Text|$.T}}{{else}}{{"确定"|$.T}}{{end}}</button>
{{- end -}}
</div>
</div><!-- /.modal-content -->

Expand Down Expand Up @@ -60,8 +64,12 @@ <h3>{{.HeadTitle|$.T|ToHTML}}<span class="modal-subtitle"></span></h3>
{{- range $k, $v := .ExtButtons -}}
<button type="button" data-dismiss="modal"{{range $bk, $bv := $v.Attributes}} {{$bv.Attr|ToHTMLAttr}}="{{$bv.Value}}"{{else}} class="btn btn-default"{{end}}>{{$v.Text}}</button>
{{- end -}}
<button type="button" class="btn btn-default btn-flat md-close" data-dismiss="modal">{{"取消"|$.T}}</button>
<button type="button" class="btn btn-{{if .Type}}{{.Type}}{{else}}primary{{end}} btn-flat md-close" data-dismiss="modal">{{"确定"|$.T}}</button>
{{- if not .ButtonCancel.Disabled -}}
<button type="button"{{range $bk, $bv := .ButtonCancel.Attributes}} {{$bv.Attr|ToHTMLAttr}}="{{$bv.Value}}"{{else}} class="btn btn-default btn-flat{{if not .ButtonCancel.DisableClose}} md-close{{end}}"{{end}}{{if not .ButtonCancel.DisableClose}} data-dismiss="modal"{{end}}>{{if .ButtonCancel.Text}}{{.ButtonCancel.Text|$.T}}{{else}}{{"取消"|$.T}}{{end}}</button>
{{- end -}}
{{- if not .ButtonSubmit.Disabled -}}
<button type="button"{{range $bk, $bv := .ButtonSubmit.Attributes}} {{$bv.Attr|ToHTMLAttr}}="{{$bv.Value}}"{{else}} class="btn btn-{{if .Type}}{{.Type}}{{else}}primary{{end}} btn-flat{{if not .ButtonSubmit.DisableClose}} md-close{{end}}"{{end}}{{if not .ButtonSubmit.DisableClose}} data-dismiss="modal"{{end}}>{{if .ButtonSubmit.Text}}{{.ButtonSubmit.Text|$.T}}{{else}}{{"确定"|$.T}}{{end}}</button>
{{- end -}}
</div>
</div>
</div>
Expand Down

0 comments on commit 8bd4faf

Please sign in to comment.