Browse Source

temp Update

zhuzhuyule 7 years ago
parent
commit
03d0c6c6c8

+ 1 - 0
app/moe-config-default.js

@@ -50,5 +50,6 @@ module.exports = {
     'image-qiniu-accessKey':'',
     'image-qiniu-secretKey':'',
     'image-qiniu-bucket':'',
+    'image-qiniu-url-protocol': 'https://',
     'image-qiniu-url':'',
 };

+ 20 - 2
app/moe-l10n.js

@@ -177,7 +177,6 @@ const strings = {
         "Hexo Config": "Hexo Config",
         "Hexo tags": "Tag Templates",
 
-        "HEXOOpenPath": "Open Work Path",
         "HEXOQuickPublish": "Quick Deploy",
         "HEXOServer": "Start Server",
         "HEXOClean": "Clean Cache",
@@ -230,6 +229,16 @@ const strings = {
         "Delete": "Delete",
         "Select All": "Select All",
 
+        "Quick Open":"Quick Open",
+        "OpenPathPost":"Open Post Path",
+        "OpenPathPostSrc":"Open Post Src Path",
+        "OpenPathSrcCenter":"Open Src Center Path",
+        "OpenPathHEXO":"Open Work Path",
+        "WebIndex":"Open Your Index",
+        "WebLocalIndex":"Open Server Index",
+        "WebQiNiuSource":"Open QiNiu Source Index",
+        "WebSMMS":"Open SM.MS",
+
         "Services": "Services",
         "Hide": "Hide",
         "Hide Others": "Hide Others",
@@ -336,7 +345,6 @@ const strings = {
         "Hexo Config": "Hexo配置文件",
         "Hexo tags": "Tag模板目录",
 
-        "HEXOOpenPath": "打开项目",
         "HEXOQuickPublish": "一键部署",
         "HEXOServer": "启动服务器",
         "HEXOClean": "清除缓存文件",
@@ -389,6 +397,16 @@ const strings = {
         "Delete": "删除",
         "Select All": "全选",
 
+        "Quick Open":"快速打开",
+        "OpenPathPost":"编辑文件",
+        "OpenPathPostSrc":"文件引用资源",
+        "OpenPathSrcCenter":"资源中心",
+        "OpenPathHEXO":"Hexo项目",
+        "WebIndex":"主页",
+        "WebLocalIndex":"本地主页",
+        "WebQiNiuSource":"七牛存储空间",
+        "WebSMMS":"SM.MS主页",
+
         "Services": "服务",
         "Hide": "隐藏",
         "Hide Others": "隐藏其他",

+ 78 - 64
views/main/hexo-image.js

@@ -17,26 +17,6 @@
  *  along with Moeditor. If not, see <http://www.gnu.org/licenses/>.
  */
 
-window.mkdirsSync = (dirpath, mode) => {
-    if (!fs.existsSync(dirpath)) {
-        var pathtmp;
-        dirpath.split(path.sep).forEach(function (dirname) {
-            if (pathtmp) {
-                pathtmp = path.join(pathtmp, dirname);
-            }
-            else {
-                pathtmp = dirname;
-            }
-            if (!fs.existsSync(pathtmp)) {
-                if (!fs.mkdirSync(pathtmp, mode)) {
-                    return false;
-                }
-            }
-        });
-    }
-    return true;
-}
-
 window.md5 = (text) => {
     return require('crypto').createHash('md5').update(text).digest('hex');
 };
@@ -48,7 +28,8 @@ class ImgManager {
         this.imgPathToDel = {};
         this.imgMD5IDList = {};
         this.imgPathIDList = {};
-        this.imgBasePath = '';
+        this.imgBaseDir = '';
+        this.imgPathDir = '';
         this.type = {
             png: '.png',
             jpg: '.jpg',
@@ -68,24 +49,45 @@ class ImgManager {
             rootPaht = hexoWindow.directory;
         }
         rootPaht = rootPaht.replace(/\\/g, '/');
-        if (this.imgBasePath && this.imgBasePath !== rootPaht) {
-            const oldPath = path.join(this.imgBasePath, this.fileName);
+        this.imgPathDir = path.join(rootPaht, this.fileName);
+        if (this.imgBaseDir && this.imgBaseDir !== rootPaht) {
+            const oldPath = path.join(this.imgBaseDir, this.fileName);
             if (fs.existsSync(oldPath)) {
                 try {
-                    fs.renameSync(oldPath, path.join(rootPaht, this.fileName));
+                    fs.renameSync(oldPath, this.imgPathDir);
                 } catch (e) {
-                    fs.renameSync(oldPath, path.join(rootPaht, this.fileName));
+                    fs.renameSync(oldPath, this.imgPathDir);
                 }
-                this.updateDictionary(this.imgBasePath, rootPaht)
+                this.updateDictionary(this.imgBaseDir, rootPaht)
             }
         }
-        this.imgBasePath = rootPaht;
+        this.imgBaseDir = rootPaht;
+    }
+
+    mkdirsSync(dirpath, mode) {
+        if (!fs.existsSync(dirpath)) {
+            var pathtmp;
+            dirpath.split(path.sep).forEach(function (dirname) {
+                if (pathtmp) {
+                    pathtmp = path.join(pathtmp, dirname);
+                }
+                else {
+                    pathtmp = dirname;
+                }
+                if (!fs.existsSync(pathtmp)) {
+                    if (!fs.mkdirSync(pathtmp, mode)) {
+                        return false;
+                    }
+                }
+            });
+        }
+        return true;
     }
 
     relativePath(p) {
         if (hexoWindow.useHexo)
-            return '/images/' + path.relative(this.imgBasePath, p).replace(/\\/g, '/');
-        return '/' + path.relative(this.imgBasePath, p).replace(/\\/g, '/');
+            return '/images/' + path.relative(this.imgBaseDir, p).replace(/\\/g, '/');
+        return '/' + path.relative(this.imgBaseDir, p).replace(/\\/g, '/');
     }
 
     resolvePath(p) {
@@ -93,30 +95,24 @@ class ImgManager {
             p = '.' + p;
         if (hexoWindow.useHexo) {
             if ([0, 1].includes(p.indexOf('images/')))
-                return path.resolve(this.imgBasePath, '..', p).replace(/\\/g, '/');
+                return path.resolve(this.imgBaseDir, '..', p).replace(/\\/g, '/');
         }
-        return path.resolve(this.imgBasePath, p).replace(/\\/g, '/');
+        return path.resolve(this.imgBaseDir, p).replace(/\\/g, '/');
     }
-    getQiNiuServer(){
-        if(!this.qiniuServer){
+
+    getQiNiuServer() {
+        if (!this.qiniuServer) {
             this.qiniuServer = new (require('./hexo-qiniu'))();
             this.qiniuServer.update(
                 moeApp.config.get('image-qiniu-accessKey'),
                 moeApp.config.get('image-qiniu-secretKey'),
                 moeApp.config.get('image-qiniu-bucket'),
-                moeApp.config.get('image-qiniu-url')
+                moeApp.config.get('image-qiniu-url-protocol') + moeApp.config.get('image-qiniu-url') + '/'
             );
         }
         return this.qiniuServer;
     }
 
-    getImage(img) {
-        if (typeof img === "string") {
-            return this.getImageOfPath(img)
-        }
-        return this.getImageOfObj(img)
-    }
-
     getImageOfPath(imgPath, md5ID) {
         if (fs.existsSync(imgPath)) {
             imgPath = imgPath.replace(/\\/g, '/');
@@ -124,7 +120,7 @@ class ImgManager {
             if (this.imgPathIDList[imgPath]) {
                 relativePath = this.imgPathIDList[imgPath];
             } else {
-                relativePath = '/' + path.relative(this.imgBasePath, imgPath).replace(/\\/g, '/');
+                relativePath = '/' + path.relative(this.imgBaseDir, imgPath).replace(/\\/g, '/');
                 this.imgPathIDList[imgPath] = relativePath;
                 if (md5ID) {
                     this.imgMD5IDList[md5ID] = imgPath;
@@ -136,20 +132,32 @@ class ImgManager {
 
     getImageOfFile(file) {
         let imgPath = file.path;
-
         if (fs.existsSync(imgPath)) {
-            imgPath = imgPath.replace(/\\/g, '/');
             let relativePath = '';
-            if (this.imgPathIDList[imgPath]) {
-                relativePath = this.imgPathIDList[imgPath];
-            } else {
-                relativePath = '/' + path.relative(this.imgBasePath, imgPath).replace(/\\/g, '/');
-                this.imgPathIDList[imgPath] = relativePath;
-                if (md5ID) {
-                    this.imgMD5IDList[md5ID] = imgPath;
+            try {
+                if (imgPath.indexOf(this.imgPathDir) != 0) {
+                    let imageAbsolutePath = path.join(this.imgPathDir, path.basename(imgPath));
+                    if (!fs.existsSync(imageAbsolutePath))
+                        if (!fs.existsSync(this.imgPathDir))
+                            this.mkdirsSync(this.imgPathDir);
+                    fs.writeFileSync(imageAbsolutePath, fs.readFileSync(imgPath));
+                    imgPath = imageAbsolutePath;
+                }
+
+                imgPath = imgPath.replace(/\\/g, '/');
+                if (this.imgPathIDList[imgPath]) {
+                    relativePath = this.imgPathIDList[imgPath];
+                } else {
+                    relativePath = '/' + path.relative(this.imgBaseDir, imgPath).replace(/\\/g, '/');
+                    this.imgPathIDList[imgPath] = relativePath;
+                    if (md5ID) {
+                        this.imgMD5IDList[md5ID] = imgPath;
+                    }
                 }
+            } catch (e) {
+            } finally {
+                return relativePath
             }
-            return relativePath
         }
     }
 
@@ -172,17 +180,17 @@ class ImgManager {
         ext = (ext && this.type[ext.toLowerCase().replace(/^\./, '')]) || '.png';
 
         let count = 0;
-        let imageAbsolutePath = path.join(this.imgBasePath, this.fileName, imageName + ext);
+        let imageAbsolutePath = path.join(this.imgPathDir, imageName + ext);
         do {
             if (count > 0)
-                imageAbsolutePath = path.join(this.imgBasePath, this.fileName, imageName + count + ext);
+                imageAbsolutePath = path.join(this.imgPathDir, imageName + count + ext);
             count += 1;
             if (count > 50) {
-                imageAbsolutePath = path.join(this.imgBasePath, this.fileName, imageName + require('moment')().format('YYYYMMDDhhmmssSSS') + ext);
+                imageAbsolutePath = path.join(this.imgPathDir, imageName + require('moment')().format('YYYYMMDDhhmmssSSS') + ext);
                 break;
             }
         } while (fs.existsSync(imageAbsolutePath));
-        mkdirsSync(path.dirname(imageAbsolutePath));
+        this.mkdirsSync(path.dirname(imageAbsolutePath));
         fs.writeFileSync(imageAbsolutePath, imgObject);
         return this.getImageOfPath(imageAbsolutePath, md5ID)
     }
@@ -204,16 +212,16 @@ class ImgManager {
         }
     }
 
-    uploadDelAll(){
-        Object.keys(this.imgPathToDel).forEach(k=>{
+    uploadDelAll() {
+        Object.keys(this.imgPathToDel).forEach(k => {
             imgManager.uploadDel(imgManager.imgPathToDel[k])
             delete imgManager.imgPathToDel[k];
         })
     }
 
-    uploadDel(fileHash){
+    uploadDel(fileHash) {
         let xhr = new XMLHttpRequest();
-        xhr.open('post', 'https://sm.ms/delete/'+fileHash);
+        xhr.open('post', 'https://sm.ms/delete/' + fileHash);
         xhr.send();
     }
 
@@ -284,10 +292,14 @@ class ImgManager {
             }
         })
 
-        checktime();
-        uploadList.forEach((filepath) => {
-            imgManager.asyncUploadFile(filepath, uploadRequest)
-        })
+        if (uploadList.size > 0) {
+            checktime();
+            uploadList.forEach((filepath) => {
+                imgManager.asyncUploadFile(filepath, uploadRequest)
+            })
+        } else {
+            uploadEnd();
+        }
 
         function uploadRequest(fileID, response) {
             finishedCount++;
@@ -304,6 +316,7 @@ class ImgManager {
             }
             checktime();
         }
+
         function updateSrc() {
             let value = editor.getValue();
             successList.forEach((v, k) => {
@@ -316,6 +329,7 @@ class ImgManager {
             hexoWindow.content = value;
             hexoWindow.changed = true;
         }
+
         function uploadEnd(isTimeout) {
             try {
                 updateSrc();

+ 12 - 15
views/main/hexo-qiniu.js

@@ -1,6 +1,6 @@
 class qiniuServer {
     constructor(acessKey, secretKey) {
-        this.qiniu = require('qiniu');
+        this.qiniu = require('./qiniu/index');
         this.bucket = '';
         this.qiniu.conf.ACCESS_KEY = acessKey;
         this.qiniu.conf.SECRET_KEY = secretKey;
@@ -103,7 +103,7 @@ class qiniuServer {
     getBucketsFiles(buketName, prefix, callback) {
         if (!buketName) return;
         const url_api_bukets = require('util').format(
-            'https://rsf.qbox.me/list?bucket=%s&marker=&limit=1000&prefix=%s&delimiter=/', buketName, prefix || '')
+            'https://rsf.qbox.me/list?bucket=%s&marker=&limit=1&prefix=%s&delimiter=/', buketName, prefix || '')
         let xhr = new XMLHttpRequest();
         xhr.open('get', url_api_bukets);
         xhr.setRequestHeader('Authorization', this.getAccessToken(url_api_bukets));
@@ -136,25 +136,22 @@ class qiniuServer {
         var extra = new this.qiniu.form_up.PutExtra();
         let qiniuServer = this;
         formUploader.putFile(token, serverFileName, localFile, extra,
-            function (respErr, respBody, respInfo) {
-                console.log( respBody);
-                if (respErr) {
-                    throw respErr;
-                }
-                if (respInfo.statusCode == 200 || respInfo.statusCode == 579) {
-                    let response = {
+            function (statusCode,response, responseText) {
+                console.log( response);
+                if (statusCode == 200 || statusCode == 579) {
+                    let result = {
                         code: 'success',
                         data: {
-                            url: qiniuServer.url + respBody.key
+                            url: qiniuServer.url + response.key
                         }
                     }
-                    callback(localFile, response);
+                    callback(localFile, result);
                 } else {
-                    console.log(respInfo.statusCode);
-                    let response = {
-                        error: respInfo.statusCode + respBody,
+                    console.log(statusCode);
+                    let result = {
+                        error: statusCode + responseText,
                     }
-                    callback(localFile, response);
+                    callback(localFile, result);
                 }
             });
     }

+ 89 - 12
views/main/moe-contextmenu.js

@@ -54,9 +54,9 @@ document.addEventListener('DOMContentLoaded', () => {
                 },
                 {
                     label: __('Paste'),
-                    enabled: inEditor && (require('electron').clipboard.readText().length !== 0||
+                    enabled: inEditor && (require('electron').clipboard.readText().length !== 0 ||
                         !clipboard.readImage().isEmpty()),
-                    click(item, hexoWindow){
+                    click(item, hexoWindow) {
                         pasteData();
                     }
                 },
@@ -64,8 +64,8 @@ document.addEventListener('DOMContentLoaded', () => {
                     label: __('Delete'),
                     enabled: inEditor && window.editor.doc.somethingSelected(),
                     click(item, hexoWindow) {
-                        hexoWindow.webContents.sendInputEvent({ type: 'keyDown', modifiers: [], keyCode: 'Delete' });
-                        hexoWindow.webContents.sendInputEvent({ type: 'keyUp', modifiers: [], keyCode: 'Delete' });
+                        hexoWindow.webContents.sendInputEvent({type: 'keyDown', modifiers: [], keyCode: 'Delete'});
+                        hexoWindow.webContents.sendInputEvent({type: 'keyUp', modifiers: [], keyCode: 'Delete'});
                     }
                 },
                 {
@@ -111,6 +111,9 @@ document.addEventListener('DOMContentLoaded', () => {
                         window.scrollTogether = !window.scrollTogether;
                     }
                 },
+                {
+                    type: 'separator',
+                },
                 {
                     label: '一键上传',
                     enabled: !imgManager.isUploading,
@@ -119,7 +122,88 @@ document.addEventListener('DOMContentLoaded', () => {
                     }
                 },
                 {
-                    type: moeApp.useHexo ?  'separator' :'normal',
+                    label: __('Quick Open'),
+                    submenu: [
+                        {
+                            label: __('OpenPathPost'),
+                            enabled: !!hexoWindow.fileName ,
+                            click(item, hexoWindow) {
+                                const shell = require('electron').shell
+                                shell.showItemInFolder(hexoWindow.fileName)
+                            }
+                        },
+                        {
+                            label: __('OpenPathPostSrc'),
+                            enabled: !!(imgManager && imgManager.imgBaseDir),
+                            click(item, hexoWindow) {
+                                const shell = require('electron').shell;
+                                let dir = path.join(imgManager.imgPathDir);
+                                if (fs.existsSync(dir))
+                                    shell.showItemInFolder(path.join(dir, '*'));
+                                else
+                                    shell.showItemInFolder(dir);
+                            }
+                        },
+                        {
+                            label: __('OpenPathSrcCenter'),
+                            enabled: !!(imgManager && imgManager.imgBaseDir),
+                            click(item, hexoWindow) {
+                                const shell = require('electron').shell;
+                                shell.showItemInFolder(path.join(imgManager.imgBaseDir, '*'))
+                            }
+                        },
+                        {
+                            label: __('OpenPathHEXO'),
+                            enabled: moeApp.useHexo,
+                            click(item, hexoWindow) {
+                                const shell = require('electron').shell
+                                shell.showItemInFolder(path.join(hexo.config.__basedir, '*'))
+                            }
+                        },
+                        {
+                            type: 'separator',
+                        },
+                        {
+                            label: __('WebIndex'),
+                            enabled: moeApp.useHexo && (!!hexo.config.url),
+                            click(item, hexoWindow) {
+                                const shell = require('electron').shell;
+                                let weburl = hexo.config.url;
+                                weburl = (weburl.startsWith('http://') || weburl.startsWith('https://') ? weburl : 'http://' + weburl);
+                                weburl = url.parse(weburl);
+                                weburl.path = hexo.config.root || '/';
+                                shell.openExternal(weburl.href);
+                            }
+                        },
+                        {
+                            label: __('WebLocalIndex'),
+                            enabled: moeApp.useHexo && (shellServer.shellProcess != null),
+                            click(item, hexoWindow) {
+                                const shell = require('electron').shell;
+                                let weburl = url.parse('http://localhost:4000');
+                                weburl.hostname = moeApp.hexo.config.server.ip || 'localhost';
+                                weburl.port = moeApp.hexo.config.server.port || 4000;
+                                shell.openExternal(weburl.href);
+                            }
+                        },
+                        {
+                            label: __('WebQiNiuSource'),
+                            click(item, hexoWindow) {
+                                const shell = require('electron').shell;
+                                shell.openExternal(`https://portal.qiniu.com/bucket/${moeApp.config.get('image-qiniu-bucket')}/resource`)
+                            }
+                        },
+                        {
+                            label: __('WebSMMS'),
+                            click(item, hexoWindow) {
+                                const shell = require('electron').shell;
+                                shell.openExternal(`https://sm.ms/`)
+                            }
+                        }
+                    ]
+                },
+                {
+                    type: moeApp.useHexo ? 'separator' : 'normal',
                     visible: moeApp.useHexo,
                 },
                 {
@@ -137,13 +221,6 @@ document.addEventListener('DOMContentLoaded', () => {
                                 window.changeFileName(true);
                             }
                         },
-                        {
-                            label: __('HEXOOpenPath'),
-                            click(item, hexoWindow) {
-                                const shell = require('electron').shell
-                                shell.showItemInFolder(path.join(hexo.config.__basedir, '*'))
-                            }
-                        },
                         {
                             label: __('HEXOQuickPublish'),
                             click(item, hexoWindow) {

+ 22 - 19
views/main/moe-document.js

@@ -26,6 +26,7 @@ window.hexoWindow = moeApp.hexoWindow;
 window.clipboard = require('electron').clipboard;
 window.fs = require('fs');
 window.path = require('path');
+window.url = require('url');
 
 $(() => {
     const dialog = require('electron').remote.dialog;
@@ -225,23 +226,7 @@ $(() => {
     var prastDataKey = (process.platform === 'darwin' ? "Cmd" : "Ctrl") + "-V";
     editor.options.extraKeys[prastDataKey] = pasteData;
 
-    const holder = document
-    holder.ondragover = () => {
-        return false;
-    }
-    holder.ondragleave = holder.ondragend = () => {
-        return false;
-    }
-    holder.ondrop = (e) => {
-        e.stopPropagation()
-        e.preventDefault()
-        for (let f of e.dataTransfer.files) {
-            replaceImgSelection(editor, (editor.getSelection() || ''),imgManager.getImageOfFile(f));
-        }
-        return false;
-    }
-
-    window.changeFileName = (force) => {
+     window.changeFileName = (force) => {
         if (!force && hexoWindow.defName !== hexoWindow.fileName)
             return;
 
@@ -275,9 +260,9 @@ $(() => {
                 document.getElementsByTagName('title')[0].innerText = 'HexoEditor - ' + nameNew + ext;
 
                 //修改文章中的Image链接
-                let imgPathOld = path.join(imgManager.imgBasePath,nameOld).replace(/\\/g,'/');
+                let imgPathOld = path.join(imgManager.imgBaseDir,nameOld).replace(/\\/g,'/');
                 if (fs.existsSync(imgPathOld)) {
-                    let imgPathNew = path.join(imgManager.imgBasePath,nameNew).replace(/\\/g,'/');
+                    let imgPathNew = path.join(imgManager.imgBaseDir,nameNew).replace(/\\/g,'/');
                     fs.rename(imgPathOld, imgPathNew, err => {
                         if (err) console.error(err);
                         fs.stat(imgFilePathNew, (err, stats) => {
@@ -433,6 +418,24 @@ $(() => {
             editordiv.classList.remove('ctrl')
         }
     })
+    function bindDrag(element) {
+        element.ondragover = () => {
+            return false;
+        }
+        element.ondragleave = element.ondragend = () => {
+            return false;
+        }
+        element.ondrop = (e) => {
+            e.stopPropagation()
+            e.preventDefault()
+            for (let f of e.dataTransfer.files) {
+                replaceImgSelection(editor, (editor.getSelection() || ''),imgManager.getImageOfFile(f));
+            }
+            return false;
+        }
+    }
+    bindDrag(document);
+    bindDrag(editordiv);
 
     window.onfocus = (e) => {
         if (hexoWindow.fileName === '' || !fs.existsSync(hexoWindow.fileName))

+ 8 - 1
views/main/moe-settings.js

@@ -220,8 +220,15 @@ function SetQiNiuBucket(val) {
 }
 
 function SetQiNiuWeb(val) {
+    if (val && val.oldURL && val.newURL){
+        let content = editor.getValue();
+        content = content.replace(new RegExp(val.oldURL,'g'),val.newURL);
+        editor.setValue(content);
+        hexoWindow.changed = true;
+        hexoWindow.content = content;
+    }
     if(imgManager && imgManager.qiniuServer){
-        imgManager.qiniuServer.update('','','',val)
+        imgManager.qiniuServer.update('','','',val.newURL)
     }
 }
 

+ 48 - 0
views/main/qiniu/qiniu/rpc.js

@@ -0,0 +1,48 @@
+var urllib = require('urllib');
+var util = require('./util');
+var conf = require('./conf');
+
+exports.post = post;
+exports.postMultipart = postMultipart;
+exports.postWithForm = postWithForm;
+exports.postWithoutForm = postWithoutForm;
+
+function postMultipart(requestURI, requestForm, callbackFunc) {
+  return post(requestURI, requestForm, callbackFunc);
+}
+
+function postWithForm(requestURI, requestForm, token, callbackFunc) {
+  var headers = {
+    'Content-Type': 'application/x-www-form-urlencoded'
+  };
+  if (token) {
+    headers['Authorization'] = token;
+  }
+  return post(requestURI, requestForm, headers, callbackFunc);
+}
+
+function postWithoutForm(requestURI, token, callbackFunc) {
+  var headers = {
+    'Content-Type': 'application/x-www-form-urlencoded',
+  };
+  if (token) {
+    headers['Authorization'] = token;
+  }
+  return post(requestURI, null, headers, callbackFunc);
+}
+
+function post(requestURI, data, callbackFunc) {
+    let xhr = new XMLHttpRequest();
+    xhr.open('post', requestURI);
+    xhr.onreadystatechange = () => {
+        if (xhr.readyState === 4) {
+            if (typeof callbackFunc === "function") {
+                callbackFunc(xhr.status, xhr.response, xhr.responseText);
+            }
+        }
+    }
+    // xhr.upload.onprogress = (e) => {
+    //     console.log(Math.floor(100 * e.loaded / e.total) + '%');
+    // }
+    xhr.send(data)
+}

+ 230 - 0
views/main/qiniu/qiniu/storage/form.js

@@ -0,0 +1,230 @@
+const conf = require('../conf');
+const util = require('../util');
+const rpc = require('../rpc');
+const fs = require('fs');
+const getCrc32 = require('crc32');
+const path = require('path');
+const mime = require('mime');
+const Readable = require('stream').Readable;
+const formstream = require('formstream');
+const zone = require('../zone');
+const digest = require('../auth/digest');
+
+exports.FormUploader = FormUploader;
+exports.PutExtra = PutExtra;
+
+function FormUploader(config) {
+  this.config = config || new conf.Config();
+}
+
+// 上传可选参数
+// @params fname   请求体中的文件的名称
+// @params params  额外参数设置,参数名称必须以x:开头
+// @param mimeType 指定文件的mimeType
+// @param crc32    指定文件的crc32值
+// @param checkCrc 指定是否检测文件的crc32值
+function PutExtra(fname, params, mimeType, crc32, checkCrc) {
+  this.fname = fname || '';
+  this.params = params || {};
+  this.mimeType = mimeType || null;
+  this.crc32 = crc32 || null;
+  this.checkCrc = checkCrc || 1;
+}
+
+FormUploader.prototype.putStream = function(uploadToken, key, fsStream,
+  putExtra, callbackFunc) {
+  putExtra = putExtra || new PutExtra();
+  if (!putExtra.mimeType) {
+    putExtra.mimeType = 'application/octet-stream';
+  }
+
+  if (!putExtra.fname) {
+    putExtra.fname = key ? key : 'fname';
+  }
+
+  fsStream.on("error", function(err) {
+    //callbackFunc
+    callbackFunc(err, null, null);
+    return;
+  });
+
+  var useCache = false;
+  var that = this;
+  if (this.config.zone) {
+    if (this.config.zoneExpire == -1) {
+      useCache = true;
+    } else {
+      if (!util.isTimestampExpired(this.config.zoneExpire)) {
+        useCache = true;
+      }
+    }
+  }
+
+  var accessKey = util.getAKFromUptoken(uploadToken);
+  var bucket = util.getBucketFromUptoken(uploadToken);
+  if (useCache) {
+    createMultipartForm(uploadToken, key, fsStream, putExtra, function(
+      postForm) {
+      putReq(that.config, postForm, callbackFunc);
+    });
+  } else {
+    zone.getZoneInfo(accessKey, bucket, function(err, cZoneInfo,
+      cZoneExpire) {
+      if (err) {
+        callbackFunc(err, null, null);
+        return;
+      }
+
+      //update object
+      that.config.zone = cZoneInfo;
+      that.config.zoneExpire = cZoneExpire;
+
+      //req
+      createMultipartForm(uploadToken, key, fsStream,
+        putExtra,
+        function(postForm) {
+          putReq(that.config, postForm, callbackFunc);
+        });
+    });
+  }
+}
+
+function putReq(config, postForm, callbackFunc) {
+  //set up hosts order
+  var upHosts = [];
+
+  if (config.useCdnDomain) {
+    if (config.zone.cdnUpHosts) {
+      config.zone.cdnUpHosts.forEach(function(host) {
+        upHosts.push(host);
+      });
+    }
+    config.zone.srcUpHosts.forEach(function(host) {
+      upHosts.push(host);
+    });
+  } else {
+    config.zone.srcUpHosts.forEach(function(host) {
+      upHosts.push(host);
+    });
+    config.zone.cdnUpHosts.forEach(function(host) {
+      upHosts.push(host);
+    });
+  }
+
+  var scheme = config.useHttpsDomain ? "https://" : "http://";
+  var upDomain = scheme + upHosts[0];
+  rpc.postMultipart(upDomain, postForm, callbackFunc);
+}
+
+// 上传字节
+//
+FormUploader.prototype.put = function(uploadToken, key, body, putExtra,
+  callbackFunc) {
+  var fsStream = new Readable();
+  fsStream.push(body);
+  fsStream.push(null);
+
+  putExtra = putExtra || new PutExtra();
+  return this.putStream(uploadToken, key, fsStream, putExtra, callbackFunc)
+}
+
+FormUploader.prototype.putWithoutKey = function(uploadToken, body, putExtra,
+  callbackFunc) {
+  return this.put(uploadToken, null, body, putExtra, callbackFunc);
+}
+
+function createMultipartForm(uploadToken, key, fsStream, putExtra, callbackFunc) {
+    var formdata = new FormData();
+    formdata.append('token', uploadToken);
+    formdata.append('key', key);
+    formdata.append('file', fsStream);
+    for (var k in putExtra.params) {
+        if (k.startsWith("x:")) {
+            formdata.append(k, putExtra.params[k].toString());
+        }
+    }
+
+    callbackFunc(formdata);
+
+    return;
+
+    let xhr = new XMLHttpRequest();
+    xhr.open('post', 'https://sm.ms/api/upload');
+    xhr.onreadystatechange = () => {
+        if (xhr.readyState === 4) { // 成功完成
+            // 判断响应结果:
+            if (xhr.status === 200) {
+                // 成功,通过responseText拿到响应的文本:
+                if (typeof callback === "function") {
+                    callback(imgPath, JSON.parse(xhr.responseText))
+                }
+            } else {
+                // 失败,根据响应码判断失败原因:
+                if (typeof callback === "function") {
+                    callback(imgPath, {code: xhr.status})
+                }
+            }
+            console.log(xhr.responseText)
+        }
+    }
+    // xhr.upload.onprogress = (e) => {
+    //     console.log(Math.floor(100 * e.loaded / e.total) + '%');
+    // }
+    xhr.send(formdata);
+
+    return;
+
+    var postForm = formstream();
+  postForm.field('token', uploadToken);
+  if (key) {
+    postForm.field('key', key);
+  }
+
+  postForm.stream('file', fsStream, putExtra.fname, putExtra.mimeType);
+
+  //putExtra params
+  for (var k in putExtra.params) {
+    if (k.startsWith("x:")) {
+      postForm.field(k, putExtra.params[k].toString());
+    }
+  }
+  var fileBody = [];
+  fsStream.on('data', function(data) {
+    fileBody.push(data);
+  });
+
+  fsStream.on('end', function() {
+    fileBody = Buffer.concat(fileBody);
+    var bodyCrc32 = parseInt("0x" + getCrc32(fileBody));
+    postForm.field('crc32', bodyCrc32);
+  });
+  callbackFunc(postForm);
+}
+
+
+// 上传本地文件
+// @params uploadToken 上传凭证
+// @param key 目标文件名
+// @param localFile 本地文件路径
+// @param putExtra 额外选项
+// @param callbackFunc 回调函数
+FormUploader.prototype.putFile = function(uploadToken, key, localFile, putExtra,
+  callbackFunc) {
+  putExtra = putExtra || new PutExtra();
+  var fsStream = fs.createReadStream(localFile);
+
+  if (!putExtra.mimeType) {
+    putExtra.mimeType = mime.lookup(localFile);
+  }
+
+  if (!putExtra.fname) {
+    putExtra.fname = path.basename(localFile);
+  }
+
+  return this.putStream(uploadToken, key, fsStream, putExtra, callbackFunc);
+}
+
+FormUploader.prototype.putFileWithoutKey = function(uploadToken, localFile,
+  putExtra, callbackFunc) {
+  return this.putFile(uploadToken, null, localFile, putExtra, callbackFunc);
+}

+ 29 - 2
views/settings/moe-settings.js

@@ -484,6 +484,7 @@ document.addEventListener('DOMContentLoaded', () => {
     let imageAccessKey = imageTabContents.querySelector('#image-qiniu-accessKey');
     let imageSecretKey = imageTabContents.querySelector('#image-qiniu-secretKey');
     let imageBucket = imageTabContents.querySelector('#image-qiniu-bucket');
+    let imageBaseWebProtocol = imageTabContents.querySelector('#image-qiniu-url-protocol');
     let imageBaseWeb = imageTabContents.querySelector('#image-qiniu-url');
 
     function hasQiNiuServer() {
@@ -528,7 +529,7 @@ document.addEventListener('DOMContentLoaded', () => {
                     imageBaseWeb.innerHTML = '';
                     response.data.forEach((url) => {
                         let option = document.createElement('option');
-                        option.value = `https://${url}/`;
+                        option.value = url;
                         option.innerText = url;
                         imageBaseWeb.appendChild(option);
                         if ((option.value == oldurl)) {
@@ -603,9 +604,35 @@ document.addEventListener('DOMContentLoaded', () => {
         ipcRenderer.send('setting-changed', {key: imageBucket.id, val: imageBucket.value});
     })
 
+
+    function protocolChange(){
+        if (imageBaseWebProtocol.value == 'http://'){
+            imageBaseWebProtocol.style.width = '53px';
+            imageBaseWeb.style.width = 'calc(100% - 57px)';
+            imageBaseWebProtocol.value = 'https://';
+        } else {
+            imageBaseWebProtocol.style.width = '47px';
+            imageBaseWeb.style.width = 'calc(100% - 51px)';
+            imageBaseWebProtocol.value = 'http://';
+        }
+    }
+    imageBaseWebProtocol.value = moeApp.config.get('image-qiniu-url-protocol');
+    protocolChange();
+    imageBaseWebProtocol.addEventListener('click',()=>{
+        protocolChange();
+        imageBaseWeb.dispatchEvent(new Event('change'));
+    })
+
     imageBaseWeb.addEventListener('change', function (e) {
+        let protocol = moeApp.config.get(imageBaseWebProtocol.id)
+        let oldURL =  moeApp.config.get(imageBaseWeb.id);
+        let value = {
+            oldURL: (oldURL ? protocol + oldURL: ''),
+            newURL: (imageBaseWeb.value ? imageBaseWebProtocol.value + imageBaseWeb.value: '')
+        };
+        moeApp.config.set(imageBaseWebProtocol.id, imageBaseWebProtocol.value);
         moeApp.config.set(imageBaseWeb.id, imageBaseWeb.value);
-        ipcRenderer.send('setting-changed', {key: imageBaseWeb.id, val: imageBaseWeb.value});
+        ipcRenderer.send('setting-changed', {key: imageBaseWeb.id, val: value});
     })
 
     let type =  moeApp.config.get(imageType.id);

+ 4 - 3
views/settings/settings.html

@@ -182,7 +182,7 @@
                             <tr>
                                 <td width="30%" class="l10n">Hexo Config</td>
                                 <td width="70%">
-                                    <input type="text" class="settings-item" disabled="disabled"  data-key="hexo-config" style="width: calc(100% - 25px);">
+                                    <input type="text" class="settings-item" readonly  data-key="hexo-config" style="width: calc(100% - 25px);">
                                     <div style="display: inline-block; margin-left: -1px; position: absolute; " id="hexo-config-btn">
                                         <button class="button-add-remove button-add" ><i class="fa fa-folder-o" aria-hidden="true"></i></button>
                                     </div>
@@ -291,7 +291,7 @@
                             <tr>
                                 <td width="40%" class="l10n">Source Center</td>
                                 <td width="60%">
-                                    <input class="settings-item-image" disabled="disabled" id="image-source-center" type="url" style="width: calc(100% - 25px);"/>
+                                    <input class="settings-item-image" readonly id="image-source-center" type="url" style="width: calc(100% - 25px);"/>
                                     <div style="display: inline-block; margin-left: -1px; position: absolute; " id="image-source-center-btn">
                                     <button class="button-add-remove button-add" ><i class="fa fa-folder-o" aria-hidden="true"></i></button>
 
@@ -329,7 +329,8 @@
                             <tr data-type="image-qiniu" style="display:none">
                                 <td width="40%" class="l10n">BaseWeb</td>
                                 <td width="60%">
-                                    <select class="settings-item-image" id="image-qiniu-url">
+                                    <input class="settings-item-image" id="image-qiniu-url-protocol" readonly style="transition: width .5s;  width:53px" />
+                                    <select class="settings-item-image" id="image-qiniu-url" style="transition: width .5s;width: calc(100% - 54px);">
                                     </select>
                                 </td>
                             </tr>