1、优化导出文件的效果

2、修复更新用户时邮箱重复的提示文案
3、优化部分显示效果
pull/244/head
Minho 2018-03-22 14:27:23 +08:00
parent 52f5a44691
commit 359c5dfb10
13 changed files with 336 additions and 120 deletions

View File

@ -178,7 +178,6 @@ func (c *AccountController) Register() {
member.Email = email
member.Status = 0
if err := member.Add(); err != nil {
beego.Error(err)
c.JsonResult(6006, "注册失败,请联系系统管理员处理")
}

View File

@ -181,7 +181,6 @@ func (c *ManagerController) ChangeMemberRole() {
member.Role = role
if err := member.Update(); err != nil {
logs.Error("", err)
c.JsonResult(6003, "用户权限设置失败")
}
member.ResolveRoleName()
@ -233,8 +232,7 @@ func (c *ManagerController) EditMember() {
member.Password = password
}
if err := member.Update(); err != nil {
beego.Error(err)
c.JsonResult(6004, "保存失败")
c.JsonResult(6004, err.Error())
}
c.JsonResult(0, "ok")
}

View File

@ -21,6 +21,7 @@ import (
type Converter struct {
BasePath string
OutputPath string
Config Config
Debug bool
GeneratedCover string
@ -123,10 +124,9 @@ func (this *Converter) Convert() (err error) {
}
//将当前文件夹下的所有文件压缩成zip包然后直接改名成content.epub
f := filepath.Join(this.BasePath, "content.epub")
fmt.Println("epub目录 " + f)
f := filepath.Join(this.OutputPath, "content.epub")
os.Remove(f) //如果原文件存在了,则删除;
if err = ziptil.Zip(f, this.BasePath); err == nil {
if err = ziptil.Zip(this.BasePath,f); err == nil {
//创建导出文件夹
os.Mkdir(this.BasePath+"/"+output, os.ModePerm)
if len(this.Config.Format) > 0 {
@ -434,8 +434,8 @@ func (this *Converter) generateContentOpf() (err error) {
//转成epub
func (this *Converter) convertToEpub() (err error) {
args := []string{
filepath.Join(this.BasePath, "content.epub"),
filepath.Join(this.BasePath, output, "book.epub"),
filepath.Join(this.OutputPath, "content.epub"),
filepath.Join(this.OutputPath, output, "book.epub"),
}
cmd := exec.Command(ebookConvert, args...)
@ -443,13 +443,15 @@ func (this *Converter) convertToEpub() (err error) {
fmt.Println(cmd.Args)
}
return cmd.Run()
//return filetil.CopyFile(filepath.Join(this.OutputPath, "content.epub"),filepath.Join(this.OutputPath, output, "book.epub"))
}
//转成mobi
func (this *Converter) convertToMobi() (err error) {
args := []string{
filepath.Join(this.BasePath, "content.epub"),
filepath.Join(this.BasePath, output, "book.mobi"),
filepath.Join(this.OutputPath, "content.epub"),
filepath.Join(this.OutputPath, output, "book.mobi"),
}
cmd := exec.Command(ebookConvert, args...)
if this.Debug {
@ -462,8 +464,8 @@ func (this *Converter) convertToMobi() (err error) {
//转成pdf
func (this *Converter) convertToPdf() (err error) {
args := []string{
filepath.Join(this.BasePath, "content.epub"),
filepath.Join(this.BasePath, output, "book.pdf"),
filepath.Join(this.OutputPath, "content.epub"),
filepath.Join(this.OutputPath, output, "book.pdf"),
}
//页面大小
if len(this.Config.PaperSize) > 0 {
@ -484,16 +486,16 @@ func (this *Converter) convertToPdf() (err error) {
args = append(args, "--pdf-footer-template",this.Config.Footer)
}
if len(this.Config.MarginLeft) > 0 {
if strings.Count(this.Config.MarginLeft,"") > 0 {
args = append(args, "--pdf-page-margin-left", this.Config.MarginLeft)
}
if len(this.Config.MarginTop) > 0 {
if strings.Count(this.Config.MarginTop,"") > 0 {
args = append(args, "--pdf-page-margin-top", this.Config.MarginTop)
}
if len(this.Config.MarginRight) > 0 {
if strings.Count(this.Config.MarginRight,"") > 0 {
args = append(args, "--pdf-page-margin-right", this.Config.MarginRight)
}
if len(this.Config.MarginBottom) > 0 {
if strings.Count(this.Config.MarginBottom,"") > 0 {
args = append(args, "--pdf-page-margin-bottom", this.Config.MarginBottom)
}
@ -513,8 +515,8 @@ func (this *Converter) convertToPdf() (err error) {
// 转成word
func (this *Converter) convertToDocx() (err error) {
args := []string{
this.BasePath + "/content.epub",
this.BasePath + "/" + output + "/book.docx",
filepath.Join(this.OutputPath , "content.epub"),
filepath.Join(this.OutputPath , output , "book.docx"),
}
args = append(args, "--docx-no-toc")

View File

@ -19,6 +19,7 @@ import (
"github.com/lifei6671/mindoc/utils"
"gopkg.in/russross/blackfriday.v2"
"github.com/lifei6671/mindoc/utils/ziptil"
"github.com/lifei6671/mindoc/utils/filetil"
)
type BookResult struct {
@ -189,6 +190,7 @@ func (m *BookResult) ToBookResult(book Book) *BookResult {
return m
}
//导出PDF、word等格式
func (m *BookResult) Converter(sessionId string) (ConvertBookResult, error) {
convertBookResult := ConvertBookResult{}
@ -202,7 +204,7 @@ func (m *BookResult) Converter(sessionId string) (ConvertBookResult, error) {
docxpath := filepath.Join(outputPath, "book.docx")
//先将转换的文件储存到临时目录
tempOutputPath := filepath.Join(os.TempDir(),sessionId) //filepath.Abs(filepath.Join("cache", sessionId))
tempOutputPath := filepath.Join(os.TempDir(),sessionId,m.Identify) //filepath.Abs(filepath.Join("cache", sessionId))
os.MkdirAll(outputPath, 0766)
os.MkdirAll(tempOutputPath, 0766)
@ -332,18 +334,28 @@ func (m *BookResult) Converter(sessionId string) (ConvertBookResult, error) {
f.Close()
return convertBookResult, err
}
// html = strings.Replace(html, "<img src=\"/uploads", "<img src=\"" + c.BaseUrl() + "/uploads", -1)
f.WriteString(html)
f.Close()
}
filetil.CopyFile(filepath.Join(conf.WorkingDirectory,"static","css","kancloud.css"),filepath.Join(tempOutputPath,"styles","css","kancloud.css"))
filetil.CopyFile(filepath.Join(conf.WorkingDirectory,"static","css","export.css"),filepath.Join(tempOutputPath,"styles","css","export.css"))
filetil.CopyFile(filepath.Join(conf.WorkingDirectory,"static","editor.md","css","editormd.preview.css"),filepath.Join(tempOutputPath,"styles","editor.md","css","editormd.preview.css"))
filetil.CopyFile(filepath.Join(conf.WorkingDirectory,"static","prettify","themes","prettify.css"),filepath.Join(tempOutputPath,"styles","prettify","themes","prettify.css"))
filetil.CopyFile(filepath.Join(conf.WorkingDirectory,"static","css,","markdown.preview.css"),filepath.Join(tempOutputPath,"styles","css","markdown.preview.css"))
filetil.CopyFile(filepath.Join(conf.WorkingDirectory,"static","highlight","styles","vs.css"),filepath.Join(tempOutputPath,"styles","highlight","styles","vs.css"))
filetil.CopyFile(filepath.Join(conf.WorkingDirectory,"static","katex","katex.min.css"),filepath.Join(tempOutputPath,"styles","katex","katex.min.css"))
eBookConverter := &converter.Converter{
BasePath: tempOutputPath,
OutputPath: strings.TrimSuffix(tempOutputPath,"sources"),
Config: ebookConfig,
Debug: true,
}
if err := eBookConverter.Convert(); err != nil {
beego.Error("转换文件错误:" + m.BookName + " => " + err.Error())
return convertBookResult, err

View File

@ -169,7 +169,8 @@ func (m *Member) Add() error {
hash, err := utils.PasswordHash(m.Password)
if err != nil {
return err
beego.Error("加密用户密码失败 =>",err)
return errors.New("加密用户密码失败")
}
m.Password = hash
@ -179,7 +180,8 @@ func (m *Member) Add() error {
_, err = o.Insert(m)
if err != nil {
return err
beego.Error("保存用户数据到数据时失败 =>",err)
return errors.New("保存用户失败")
}
m.ResolveRoleName()
return nil
@ -192,8 +194,12 @@ func (m *Member) Update(cols ...string) error {
if m.Email == "" {
return errors.New("邮箱不能为空")
}
if c, err := o.QueryTable(m.TableNameWithPrefix()).Filter("email", m.Email).Exclude("member_id",m.MemberId).Count(); err == nil && c > 0 {
return errors.New("邮箱已被使用")
}
if _, err := o.Update(m, cols...); err != nil {
return err
beego.Error("保存用户信息失败=>",err)
return errors.New("保存用户信息失败")
}
return nil
}

View File

@ -0,0 +1,11 @@
body{
margin: 5px auto;
padding: 5px 30px;
}
.article-title{
margin: 15px auto;
line-height: 35px;
}
.editormd-preview-container{
padding: 0 !important;
}

View File

@ -16,6 +16,7 @@ body {
word-wrap: break-word;
line-height: 1em;
}
h1,h2,h3,h4,h5,h6,strong,input,select,textarea,button,body,code {
font-family: "Helvetica Neue",Helvetica,"Segoe UI",Arial,freesans,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Microsoft Yahei","Helvetica Neue",Helvetica;
}

View File

@ -0,0 +1,70 @@
/**
* @license
* Copyright (C) 2015 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Pretty printing styles. Used with prettify.js. */
/* SPAN elements with the classes below are added by prettyprint. */
.pln { color: #000 } /* plain text */
@media screen {
.str { color: #080 } /* string content */
.kwd { color: #008 } /* a keyword */
.com { color: #800 } /* a comment */
.typ { color: #606 } /* a type name */
.lit { color: #066 } /* a literal value */
/* punctuation, lisp open bracket, lisp close bracket */
.pun, .opn, .clo { color: #660 }
.tag { color: #008 } /* a markup tag name */
.atn { color: #606 } /* a markup attribute name */
.atv { color: #080 } /* a markup attribute value */
.dec, .var { color: #606 } /* a declaration; a variable name */
.fun { color: red } /* a function name */
}
/* Use higher contrast and text-weight for printable form. */
@media print, projection {
.str { color: #060 }
.kwd { color: #006; font-weight: bold }
.com { color: #600; font-style: italic }
.typ { color: #404; font-weight: bold }
.lit { color: #044 }
.pun, .opn, .clo { color: #440 }
.tag { color: #006; font-weight: bold }
.atn { color: #404 }
.atv { color: #060 }
}
/* Put a border around prettyprinted code snippets. */
pre.prettyprint { padding: 2px; border: 1px solid #888 }
/* Specify class=linenums on a pre to get line numbering */
ol.linenums { margin-top: 0; margin-bottom: 0 } /* IE indents via margin-left */
li.L0,
li.L1,
li.L2,
li.L3,
li.L5,
li.L6,
li.L7,
li.L8 { list-style-type: none }
/* Alternate shading for lines */
li.L1,
li.L3,
li.L5,
li.L7,
li.L9 { background: #eee }

View File

@ -4,6 +4,8 @@ import (
"os"
"path/filepath"
"strings"
"io"
"fmt"
)
//==================================
@ -41,3 +43,90 @@ func ScanFiles(dir string) (fl []FileList, err error) {
})
return
}
//拷贝文件
func CopyFile(source string, dst string) (err error) {
sourceFile, err := os.Open(source)
if err != nil {
return err
}
defer sourceFile.Close()
_,err = os.Stat(filepath.Dir(dst))
if err != nil {
if os.IsNotExist(err) {
os.MkdirAll(filepath.Dir(dst),0766)
}else{
return err
}
}
destFile, err := os.Create(dst)
if err != nil {
return err
}
defer destFile.Close()
_, err = io.Copy(destFile, sourceFile)
if err == nil {
sourceInfo, err := os.Stat(source)
if err != nil {
err = os.Chmod(dst, sourceInfo.Mode())
}
}
return
}
//拷贝目录
func CopyDir(source string, dest string) (err error) {
// get properties of source dir
sourceInfo, err := os.Stat(source)
if err != nil {
return err
}
// create dest dir
err = os.MkdirAll(dest, sourceInfo.Mode())
if err != nil {
return err
}
directory, _ := os.Open(source)
objects, err := directory.Readdir(-1)
for _, obj := range objects {
sourceFilePointer := filepath.Join(source , obj.Name())
destinationFilePointer := filepath.Join(dest, obj.Name())
if obj.IsDir() {
// create sub-directories - recursively
err = CopyDir(sourceFilePointer, destinationFilePointer)
if err != nil {
fmt.Println(err)
}
} else {
// perform copy
err = CopyFile(sourceFilePointer, destinationFilePointer)
if err != nil {
fmt.Println(err)
}
}
}
return
}
func RemoveDir(dir string) error {
return os.RemoveAll(dir)
}

View File

@ -2,14 +2,11 @@ package ziptil
import (
"archive/zip"
"errors"
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/lifei6671/mindoc/utils/filetil"
"fmt"
)
//解压zip文件
@ -47,66 +44,122 @@ func Unzip(zipFile, dest string) (err error) {
return nil
}
//压缩指定文件或文件夹
//@param dest 压缩后的zip文件目标如/usr/local/hello.zip
//@param filepath 需要压缩的文件或者文件夹
//@return err 错误。如果返回错误则会删除dest文件
func Zip(dest string, filepath ...string) (err error) {
if len(filepath) == 0 {
return errors.New("lack of file")
}
//创建文件
fzip, err := os.Create(dest)
//压缩文件
func Zip(source, target string) error {
zipFile, err := os.Create(target)
if err != nil {
return err
}
defer fzip.Close()
defer zipFile.Close()
var filelist []filetil.FileList
for _, file := range filepath {
if info, err := os.Stat(file); err == nil {
if info.IsDir() { //目录,则扫描文件
if f, _ := filetil.ScanFiles(file); len(f) > 0 {
filelist = append(filelist, f...)
}
} else { //文件
filelist = append(filelist, filetil.FileList{
IsDir: false,
Name: info.Name(),
Path: file,
})
}
} else {
archive := zip.NewWriter(zipFile)
defer archive.Close()
source = strings.Replace(source, "\\", "/", -1)
filepath.Walk(source, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
}
w := zip.NewWriter(fzip)
defer w.Close()
for _, file := range filelist {
if !file.IsDir {
if fw, err := w.Create(strings.TrimLeft(file.Path, "./")); err != nil {
return err
} else {
if fileContent, err := ioutil.ReadFile(file.Path); err != nil {
return err
} else {
if _, err = fw.Write(fileContent); err != nil {
return err
}
}
}
path = strings.Replace(path, "\\", "/", -1)
if path == source {
return nil
}
}
return
header, err := zip.FileInfoHeader(info)
if err != nil {
return err
}
header.Name = strings.TrimPrefix(strings.TrimPrefix(strings.Replace(path, "\\", "/", -1), source), "/")
fmt.Println(header.Name)
if info.IsDir() {
header.Name += "/"
} else {
header.Method = zip.Deflate
}
writer, err := archive.CreateHeader(header)
if err != nil {
return err
}
if info.IsDir() {
return nil
}
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
_, err = io.Copy(writer, file)
return err
})
return err
}
func Compress(dst string,src string) (err error) {
////压缩指定文件或文件夹
////@param dest 压缩后的zip文件目标如/usr/local/hello.zip
////@param filepath 需要压缩的文件或者文件夹
////@return err 错误。如果返回错误则会删除dest文件
//func Zip(dest string, filepath ...string) (err error) {
// if len(filepath) == 0 {
// return errors.New("lack of file")
// }
// //创建文件
// fzip, err := os.Create(dest)
// if err != nil {
// return err
// }
// defer fzip.Close()
//
// var filelist []filetil.FileList
// for _, file := range filepath {
// if info, err := os.Stat(file); err == nil {
// if info.IsDir() { //目录,则扫描文件
// if f, _ := filetil.ScanFiles(file); len(f) > 0 {
// filelist = append(filelist, f...)
// }
// } else { //文件
// filelist = append(filelist, filetil.FileList{
// IsDir: false,
// Name: info.Name(),
// Path: file,
// })
// }
// } else {
// return err
// }
// }
// w := zip.NewWriter(fzip)
// defer w.Close()
// for _, file := range filelist {
// if !file.IsDir {
// if fw, err := w.Create(strings.TrimLeft(file.Path, "./")); err != nil {
// return err
// } else {
// if fileContent, err := ioutil.ReadFile(file.Path); err != nil {
// return err
// } else {
// if _, err = fw.Write(fileContent); err != nil {
// return err
// }
// }
// }
// }
// }
// return
//}
func Compress(dst string, src string) (err error) {
d, _ := os.Create(dst)
defer d.Close()
w := zip.NewWriter(d)
defer w.Close()
src = strings.Replace(src,"\\","/",-1)
src = strings.Replace(src, "\\", "/", -1)
f, err := os.Open(src)
if err != nil {
@ -124,7 +177,6 @@ func Compress(dst string,src string) (err error) {
return nil
}
func compress(file *os.File, prefix string, zw *zip.Writer) error {
info, err := file.Stat()
if err != nil {
@ -133,7 +185,7 @@ func compress(file *os.File, prefix string, zw *zip.Writer) error {
if info.IsDir() {
if prefix != "" {
prefix = prefix + "/" + info.Name()
}else{
} else {
prefix = info.Name()
}
fileInfos, err := file.Readdir(-1)
@ -171,9 +223,3 @@ func compress(file *os.File, prefix string, zw *zip.Writer) error {
}
return nil
}

View File

@ -23,10 +23,10 @@
<link href="{{cdncss "/static/css/jstree.css"}}" rel="stylesheet">
{{if eq .Model.Editor "markdown"}}
<link href="{{cdncss "/static/editor.md/css/editormd.preview.css"}}" rel="stylesheet">
<link href="{{cdncss "/static/prettify/themes/atelier-estuary-dark.min.css"}}" rel="stylesheet">
<link href="{{cdncss "/static/prettify/themes/prettify.css"}}" rel="stylesheet">
<link href="{{cdncss "/static/css/markdown.preview.css"}}" rel="stylesheet">
{{else}}
<link href="{{cdncss "/static/highlight/styles/zenburn.css"}}" rel="stylesheet">
<link href="{{cdncss "/static/highlight/styles/vs.css"}}" rel="stylesheet">
{{end}}
<link href="{{cdncss "/static/katex/katex.min.css"}}" rel="stylesheet">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->

View File

@ -1,41 +1,23 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"/>
<title>{{.Model.BookName}} - Powered by MinDoc</title>
<!-- Bootstrap -->
<link href="{{.BaseUrl}}/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="{{.BaseUrl}}/static/font-awesome/css/font-awesome.min.css" rel="stylesheet">
<link href="{{.BaseUrl}}/static/jstree/3.3.4/themes/default/style.min.css" rel="stylesheet">
<link href="{{.BaseUrl}}/static/nprogress/nprogress.css" rel="stylesheet">
<link href="{{.BaseUrl}}/static/css/kancloud.css" rel="stylesheet">
<link href="{{.BaseUrl}}/static/css/jstree.css" rel="stylesheet">
{{if eq .Model.Editor "markdown"}}
<link href="{{.BaseUrl}}/static/editor.md/css/editormd.preview.css" rel="stylesheet">
<link href="{{.BaseUrl}}/static/prettify/themes/atelier-estuary-dark.min.css" rel="stylesheet">
<link href="{{.BaseUrl}}/static/css/markdown.preview.css" rel="stylesheet">
{{else}}
<link href="{{.BaseUrl}}/static/highlight/styles/zenburn.css" rel="stylesheet">
{{end}}
<link href="styles/css/kancloud.css" rel="stylesheet">
<link href="styles/editor.md/css/editormd.preview.css" rel="stylesheet"/>
<link href="styles/prettify/themes/prettify.css" rel="stylesheet"/>
<link href="styles/css/markdown.preview.css" rel="stylesheet"/>
<link href="styles/highlight/styles/vs.css" rel="stylesheet"/>
<link href="styles/katex/katex.min.css" rel="stylesheet"/>
<link href="styles/css/export.css" rel="stylesheet"/>
</head>
<body>
<div class="m-manual manual-reader">
<div class="container-fluid manual-body">
<div class="manual-article">
<div class="article-content">
<h1 id="article-title">{{.Lists.DocumentName}}</h1>
<div class="article-body {{if eq $.Model.Editor "markdown"}}markdown-body editormd-preview-container{{else}}editor-content{{end}}" id="page-content">
{{str2html .Lists.Release}}
</div>
</div>
<h1 class="article-title">{{.Lists.DocumentName}}</h1>
<div class="article-body markdown-body editormd-preview-container" id="page-content">
{{str2html .Lists.Release}}
</div>
</div>
</body>
</html>

View File

@ -27,10 +27,10 @@
<link href="{{cdncss "/static/editor.md/css/editormd.css"}}" rel="stylesheet">
<link href="{{cdncss "/static/css/jstree.css"}}" rel="stylesheet">
<link href="{{cdncss "/static/highlight/styles/zenburn.css"}}" rel="stylesheet">
<link href="{{cdncss "/static/highlight/styles/vs.css"}}" rel="stylesheet">
<link href="{{cdncss "/static/webuploader/webuploader.css"}}" rel="stylesheet">
<link href="{{cdncss "/static/css/markdown.css"}}" rel="stylesheet">
<link href="{{cdncss "/static/prettify/themes/atelier-estuary-dark.min.css"}}" rel="stylesheet">
<link href="{{cdncss "/static/prettify/themes/prettify.css"}}" rel="stylesheet">
<link href="{{cdncss "/static/css/markdown.preview.css"}}" rel="stylesheet">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->