Compare commits

..
9 Commits
15 changed files with 181 additions and 25 deletions
+2 -1
View File
@@ -1,6 +1,6 @@
{
"name": "picgo",
"version": "1.4.0",
"version": "1.4.2",
"author": "Molunerfinn <marksz@teamsz.xyz>",
"description": "Easy to upload your pic & copy to write",
"license": "MIT",
@@ -73,6 +73,7 @@
"dependencies": {
"axios": "^0.16.1",
"element-ui": "^2.0.5",
"fecha": "^2.3.3",
"fs-extra": "^4.0.2",
"image-size": "^0.6.1",
"keycode": "^2.1.9",
+11 -2
View File
@@ -309,7 +309,8 @@ const uploadClipboardFiles = async () => {
imgUrl
}
}
img = await uploader(uploadImg, 'imgFromClipboard', settingWindow.webContents)
const win = settingWindow || window
img = await uploader(uploadImg, 'imgFromClipboard', win.webContents)
if (img !== false) {
if (img.length > 0) {
const pasteStyle = db.read().get('picBed.pasteStyle').value() || 'markdown'
@@ -394,7 +395,15 @@ ipcMain.on('updateShortKey', (evt, oldKey) => {
notification.show()
})
ipcMain.on('updateDefaultPicBed', (evt) => {
ipcMain.on('updateCustomLink', (evt, oldLink) => {
const notification = new Notification({
title: '操作成功',
body: '你的自定义链接格式已经修改成功'
})
notification.show()
})
ipcMain.on('updteDefaultPicBed', (evt) => {
const types = ['weibo', 'qiniu', 'tcyun', 'upyun']
let submenuItem = contextMenu.items[2].submenu.items
submenuItem.forEach((item, index) => {
+8 -4
View File
@@ -1,6 +1,7 @@
import fs from 'fs-extra'
import path from 'path'
import sizeOf from 'image-size'
import fecha from 'fecha'
const imgFromPath = async (imgPath) => {
let results = []
@@ -13,7 +14,8 @@ const imgFromPath = async (imgPath) => {
base64Image,
fileName,
width: imgSize.width,
height: imgSize.height
height: imgSize.height,
extname: path.extname(item.name)
})
}))
return results
@@ -22,12 +24,13 @@ const imgFromPath = async (imgPath) => {
const imgFromClipboard = (file) => {
let result = []
if (file !== null) {
const today = new Date().toLocaleString().replace(/[ ]+/g, '-').replace(/\/+/g, '-')
const today = fecha.format(new Date(), 'YYYYMMDDHHmmss')
result.push({
base64Image: file.imgUrl.replace(/^data\S+,/, ''),
fileName: `${today}.png`,
width: file.width,
height: file.height
height: file.height,
extname: '.png'
})
}
return result
@@ -44,7 +47,8 @@ const imgFromUploader = async (files) => {
base64Image,
fileName,
width: imgSize.width,
height: imgSize.height
height: imgSize.height,
extname: path.extname(item.name)
})
}))
return results
+5 -1
View File
@@ -1,9 +1,13 @@
import db from '../../datastore'
export default (style, url) => {
const customLink = db.read().get('customLink').value() || '$url'
const tpl = {
'markdown': `![](${url})`,
'HTML': `<img src="${url}"/>`,
'URL': url,
'UBB': `[IMG]${url}[/IMG]`
'UBB': `[IMG]${url}[/IMG]`,
'Custom': customLink.replace(/\$url/, url)
}
return tpl[style]
}
+2 -1
View File
@@ -6,7 +6,8 @@ import { Notification } from 'electron'
function postOptions (fileName, token, imgBase64) {
const area = selectArea(db.read().get('picBed.qiniu.area').value() || 'z0')
const base64FileName = Buffer.from(fileName, 'utf-8').toString('base64').replace(/\+/g, '-').replace(/\//g, '_')
const path = db.read().get('picBed.qiniu.path') || ''
const base64FileName = Buffer.from(path + fileName, 'utf-8').toString('base64').replace(/\+/g, '-').replace(/\//g, '_')
return {
method: 'POST',
url: `http://upload${area}.qiniu.com/putb64/-1/key/${base64FileName}`,
+8 -1
View File
@@ -52,13 +52,20 @@ const tcYunUpload = async (img, type, webContents) => {
webContents.send('uploadProgress', 30)
const singature = generateSignature()
const length = imgList.length
const tcYunOptions = db.read().get('picBed.tcyun').value()
const customUrl = tcYunOptions.customUrl
const path = tcYunOptions.path
for (let i in imgList) {
const options = postOptions(imgList[i].fileName, singature, imgList[i].base64Image)
const res = await request(options)
const body = JSON.parse(res)
if (body.message === 'SUCCESS') {
delete imgList[i].base64Image
imgList[i]['imgUrl'] = body.data.source_url
if (customUrl) {
imgList[i]['imgUrl'] = `${customUrl}/${path}${imgList[i].fileName}`
} else {
imgList[i]['imgUrl'] = body.data.source_url
}
imgList[i]['type'] = 'tcyun'
if (i - length === -1) {
webContents.send('uploadProgress', 60)
+7 -9
View File
@@ -8,12 +8,12 @@ import MD5 from 'md5'
// generate COS signature string
const generateSignature = (fileName) => {
const options = db.read().get('picBed.upyun').value()
// const apiKey = options.apiKey
const path = options.path || ''
const operator = options.operator
const password = options.password
const md5Password = MD5(password)
const date = new Date().toGMTString()
const uri = `/${options.bucket}/${encodeURI(fileName)}`
const uri = `/${options.bucket}/${path}${encodeURI(fileName)}`
const value = `PUT&${uri}&${date}`
const sign = crypto.createHmac('sha1', md5Password).update(value).digest('base64')
return `UPYUN ${operator}:${sign}`
@@ -22,9 +22,10 @@ const generateSignature = (fileName) => {
const postOptions = (fileName, signature, imgBase64) => {
const options = db.read().get('picBed.upyun').value()
const bucket = options.bucket
const path = options.path || ''
return {
method: 'PUT',
url: `https://v0.api.upyun.com/${bucket}/${encodeURI(fileName)}`,
url: `https://v0.api.upyun.com/${bucket}/${path}${encodeURI(fileName)}`,
headers: {
Authorization: signature,
Date: new Date().toGMTString()
@@ -41,24 +42,21 @@ const upYunUpload = async (img, type, webContents) => {
webContents.send('uploadProgress', 30)
const length = imgList.length
const upyunOptions = db.read().get('picBed.upyun').value()
const path = upyunOptions.path || ''
for (let i in imgList) {
const singature = generateSignature(imgList[i].fileName)
const options = postOptions(imgList[i].fileName, singature, imgList[i].base64Image)
const body = await request(options)
if (body.statusCode === 200) {
delete imgList[i].base64Image
imgList[i]['imgUrl'] = `${upyunOptions.url}/${imgList[i].fileName}${upyunOptions.options}`
imgList[i]['imgUrl'] = `${upyunOptions.url}/${path}${imgList[i].fileName}${upyunOptions.options}`
imgList[i]['type'] = 'upyun'
if (i - length === -1) {
webContents.send('uploadProgress', 60)
}
} else {
webContents.send('uploadProgress', -1)
const notification = new Notification({
title: '上传失败!',
body: '服务端出错,请稍后再试'
})
notification.show()
return new Error()
}
}
webContents.send('uploadProgress', 100)
+5 -1
View File
@@ -66,10 +66,13 @@ const weiboUpload = async function (img, type, webContents) {
body: '微博Cookie失效,请在网页版重新登录一遍'
})
notification.show()
return new Error()
} else {
imgList[i]['imgUrl'] = `https://ws1.sinaimg.cn/${quality}/${resTextJson.data.pics.pic_1.pid}`
const extname = imgList[i].extname === '.gif' ? '.gif' : '.jpg'
imgList[i]['imgUrl'] = `https://ws1.sinaimg.cn/${quality}/${resTextJson.data.pics.pic_1.pid}${extname}`
imgList[i]['type'] = 'weibo'
}
delete imgList[i].extname
}
webContents.send('uploadProgress', 100)
return imgList
@@ -80,6 +83,7 @@ const weiboUpload = async function (img, type, webContents) {
body: res.body.msg
})
notification.show()
return new Error()
}
} catch (err) {
webContents.send('uploadProgress', -1)
+8
View File
@@ -24,4 +24,12 @@
width 100%
.el-button
width 50%
*::-webkit-scrollbar
width 8px
height 8px
*::-webkit-scrollbar-thumb
border-radius 4px
background #6f6f6f
*::-webkit-scrollbar-track
background-color transparent
</style>
+90 -1
View File
@@ -86,6 +86,58 @@
<el-button type="primary" @click="confirmKeyBinding">确定</el-button>
</span>
</el-dialog>
<el-dialog
title="修改快捷键"
:visible.sync="keyBindingVisible"
>
<el-form
label-width="80px"
>
<el-form-item
label="快捷上传"
>
<el-input
class="align-center"
@keydown.native.prevent="keyDetect('upload', $event)"
v-model="shortKey.upload"
:autofocus="true"
></el-input>
</el-form-item>
</el-form>
<span slot="footer">
<el-button @click="cancelKeyBinding">取消</el-button>
<el-button type="primary" @click="confirmKeyBinding">确定</el-button>
</span>
</el-dialog>
<el-dialog
title="自定义链接格式"
:visible.sync="customLinkVisible"
>
<el-form
label-position="top"
:model="customLink"
ref="customLink"
:rules="rules"
>
<el-form-item
label="用占位符$url来表示url的位置"
prop="value"
>
<el-input
class="align-center"
v-model="customLink.value"
:autofocus="true"
></el-input>
</el-form-item>
</el-form>
<div>
[]($url)
</div>
<span slot="footer">
<el-button @click="cancelCustomLink">取消</el-button>
<el-button type="primary" @click="confirmCustomLink">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
@@ -97,12 +149,28 @@ const { Menu, dialog, BrowserWindow } = remote
export default {
name: 'setting-page',
data () {
const customLinkRule = (rule, value, callback) => {
if (!/\$url/.test(value)) {
return callback(new Error('必须含有$url'))
} else {
return callback()
}
}
return {
version: pkg.version,
version: process.env.NODE_ENV === 'production' ? pkg.version : 'Dev',
defaultActive: 'upload',
menu: null,
visible: false,
keyBindingVisible: false,
customLinkVisible: false,
customLink: {
value: db.read().get('customLink').value() || '$url'
},
rules: {
value: [
{ validator: customLinkRule, trigger: 'blur' }
]
},
os: '',
shortKey: {
upload: db.read().get('shortKey.upload').value()
@@ -152,6 +220,12 @@ export default {
_this.keyBindingVisible = true
}
},
{
label: '自定义链接格式',
click () {
_this.customLinkVisible = true
}
},
{
label: '打开更新助手',
type: 'checkbox',
@@ -179,6 +253,21 @@ export default {
db.read().set('shortKey', this.shortKey).write()
this.keyBindingVisible = false
this.$electron.ipcRenderer.send('updateShortKey', oldKey)
},
cancelCustomLink () {
this.customLinkVisible = false
this.customLink.value = db.read().get('customLink').value() || '$url'
},
confirmCustomLink () {
this.$refs.customLink.validate((valid) => {
if (valid) {
db.read().set('customLink', this.customLink.value).write()
this.customLinkVisible = false
this.$electron.ipcRenderer.send('updateCustomLink')
} else {
return false
}
})
}
},
beforeRouteEnter: (to, from, next) => {
@@ -58,6 +58,11 @@
>
<el-input v-model="form.options" @keyup.native.enter="confirm" placeholder="例如?imageslim"></el-input>
</el-form-item>
<el-form-item
label="指定存储路径"
>
<el-input v-model="form.path" @keyup.native.enter="confirm" placeholder="例如img/"></el-input>
</el-form-item>
<el-form-item>
<el-button-group>
<el-button type="primary" @click="confirm" round>确定</el-button>
@@ -82,7 +87,8 @@ export default {
bucket: '',
url: '',
area: 'z0',
options: ''
options: '',
path: ''
}
}
},
@@ -127,6 +133,8 @@ export default {
color #eee
.el-input__inner
border-radius 19px
&-item
margin-bottom 10.5px
.el-radio-group
width 100%
label
@@ -56,6 +56,11 @@
>
<el-input v-model="form.path" @keyup.native.enter="confirm" placeholder="例如img/"></el-input>
</el-form-item>
<el-form-item
label="设定自定义域名"
>
<el-input v-model="form.customUrl" @keyup.native.enter="confirm" placeholder="例如https://xxxx.com"></el-input>
</el-form-item>
<el-form-item>
<el-button-group>
<el-button type="primary" @click="confirm" round>确定</el-button>
@@ -80,7 +85,8 @@ export default {
bucket: '',
appId: '',
area: '',
path: ''
path: '',
customUrl: ''
}
}
},
@@ -125,6 +131,8 @@ export default {
color #eee
.el-input__inner
border-radius 19px
&-item
margin-bottom 10.5px
.el-radio-group
width 100%
label
@@ -48,6 +48,11 @@
>
<el-input v-model="form.options" @keyup.native.enter="confirm" placeholder="例如!imgslim"></el-input>
</el-form-item>
<el-form-item
label="指定存储路径"
>
<el-input v-model="form.path" @keyup.native.enter="confirm" placeholder="例如img/"></el-input>
</el-form-item>
<el-form-item>
<el-button-group>
<el-button type="primary" @click="confirm" round>确定</el-button>
@@ -70,7 +75,8 @@ export default {
bucket: '',
operator: '',
password: '',
options: ''
options: '',
path: ''
}
}
},
@@ -1,7 +1,7 @@
<template>
<div id="upload-view">
<el-row :gutter="16">
<el-col :span="16" :offset="4">
<el-col :span="20" :offset="2">
<div class="view-title">
图片上传
</div>
@@ -38,6 +38,7 @@
<el-radio-button label="HTML"></el-radio-button>
<el-radio-button label="URL"></el-radio-button>
<el-radio-button label="UBB"></el-radio-button>
<el-radio-button label="Custom" title="自定义"></el-radio-button>
</el-radio-group>
</div>
<div class="el-col-8">
@@ -141,6 +142,8 @@ export default {
border 2px dashed #dddddd
border-radius 8px
text-align center
width 450px
margin-left 25px
color #dddddd
cursor pointer
transition all .2s ease-in-out
@@ -163,6 +166,8 @@ export default {
margin-top 20px
opacity 0
transition all .2s ease-in-out
width 450px
margin-left 25px
&.show
opacity 1
.el-progress-bar__inner
+4
View File
@@ -3556,6 +3556,10 @@ fd-slicer@~1.0.1:
dependencies:
pend "~1.2.0"
fecha@^2.3.3:
version "2.3.3"
resolved "http://registry.npm.taobao.org/fecha/download/fecha-2.3.3.tgz#948e74157df1a32fd1b12c3a3c3cdcb6ec9d96cd"
figures@^1.4.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e"