Compare commits

...
99 Commits
Author SHA1 Message Date
Molunerfinn 4ab782e8dc 1.6.1 2018-07-25 15:07:46 +08:00
Molunerfinn a9ba87dc8e Updated: readme & FAQ 2018-07-25 00:04:14 +08:00
Molunerfinn 396faa2c60 Fixed: multi copy bug 2018-07-24 23:15:19 +08:00
Molunerfinn 930e4e663b Fixed: #84 && add multi copy 2018-07-23 22:24:18 +08:00
alanandPiEgg ce9c2aed71 Fixed: #82 2018-07-22 10:42:54 +08:00
Molunerfinn bba250b0d9 Fixed: #80 || mime-type in ali-oss 2018-07-18 15:34:35 +08:00
Molunerfinn b74fe8676b Updated: readme 2018-07-11 16:15:27 +08:00
Molunerfinn 8ad28f7fe5 Fixed: linux icon path 2018-07-11 16:04:07 +08:00
Molunerfinn 1d91730eb9 Fixed: word error 2018-07-11 15:38:15 +08:00
Molunerfinn 5a25aa0b52 Fuck: remove ali-oss 2018-07-11 15:28:56 +08:00
Molunerfinn 671c011feb Fixed: linux build bug 2018-07-11 11:42:39 +08:00
Molunerfinn 62b616bfc7 Added: linux build 2018-07-11 11:26:41 +08:00
Molunerfinn 2a801e6c19 1.6.0 2018-07-11 11:20:00 +08:00
Molunerfinn 313002cf9e Updated: readme & doc 2018-07-11 11:19:47 +08:00
Molunerfinn bcb1859eaa Fixed: choosed pic-bed bug 2018-07-11 10:52:02 +08:00
Molunerfinn 8bc0aef482 Fixed: linux version quit bug 2018-07-11 10:04:42 +08:00
Molunerfinn 353f553988 Fixed: linux mini-window tranparent bug 2018-07-11 09:39:23 +08:00
Molunerfinn f48021d928 Fixed: sync picbed status 2018-07-10 22:37:29 +08:00
Molunerfinn c9ecef60e3 Added: clipboard upload menu for mini page 2018-07-07 15:06:36 +08:00
Molunerfinn 0f4901bdbf Fixed: mini window & setting window toggle show or hide status 2018-07-07 14:45:14 +08:00
Molunerfinn f494e1486c Modified: error text for OSS 2018-07-07 00:31:53 +08:00
Molunerfinn 1faf29732c Fixed: tcyun error notice 2018-07-07 00:28:37 +08:00
Molunerfinn 5207326017 Added: icon for miniwindow 2018-07-07 00:01:06 +08:00
Molunerfinn 4d5b3fbdf6 Finished: miniwindow 2018-07-06 23:54:36 +08:00
Molunerfinn abcd7b848d Added: mini window upload progress 2018-07-06 00:43:53 +08:00
Molunerfinn 8785218b0d Added: transition for gallery handle-bar 2018-07-05 20:21:43 +08:00
Molunerfinn 61a2a047c7 Added: imgur support 2018-06-27 22:57:15 +08:00
Molunerfinn 6aed2d2a97 Added: aliYun OSS support 2018-06-26 23:50:16 +08:00
Molunerfinn 46189d2f34 Added: gallery lazy-load 2018-06-26 21:11:04 +08:00
Molunerfinn 4d55ac941f Fixed: updateDefaultPicBed bug 2018-06-26 17:12:21 +08:00
Molunerfinn 62b0c2113c Fixed: tray bug on ubuntu & hide tray icon on linux 2018-06-26 17:03:46 +08:00
Molunerfinn ed187f4438 Fixed: scrollbar bug in ubuntu 2018-06-26 00:19:40 +08:00
Molunerfinn 372f71bcd9 Fixed: not darwin platform setting window bug 2018-06-25 19:27:41 +08:00
Molunerfinn 415bdd31f3 Added: gallery edit functions 2018-06-20 20:45:12 +08:00
Molunerfinn 5d9e0a311d Updated: gallery functions 2018-06-19 13:45:07 +08:00
Molunerfinn 1781a8902c Fixed: scroll-bar style 2018-06-12 13:36:44 +08:00
Molunerfinn 1f95ef0ee2 Updated: docs 2018-06-05 21:10:36 +08:00
Molunerfinn a63e1717c7 Fixed: tray menu submenu item 2018-06-05 20:29:16 +08:00
Molunerfinn 1e5fa28789 1.5.1 2018-06-05 20:05:11 +08:00
Molunerfinn 3455512c47 Added: upload notification swtich 2018-06-05 20:03:58 +08:00
Molunerfinn 947e49ab4a Modified: pic-bed constructure for future 2018-06-05 19:49:01 +08:00
Molunerfinn a20299edaa Fixed: SMMS upload problem 2018-06-05 09:47:43 +08:00
Molunerfinn ffbbc74734 Added: smms picbed 2018-06-04 21:30:36 +08:00
Molunerfinn 1b8400a458 Added: manual check update button 2018-06-04 20:41:40 +08:00
Molunerfinn 9e2834c0f9 Added: support for upload notice & auto rename before upload 2018-06-04 20:13:17 +08:00
Molunerfinn 0b5981a27d Fixed: #61 || custom url can have more than one place 2018-05-28 18:39:43 +08:00
Molunerfinn d78de75c18 Fixed: #60 2018-05-26 23:23:36 +08:00
Molunerfinn f8eceae8e4 Finished: github custom url 2018-05-26 10:34:04 +08:00
Molunerfinn a0c1e95b15 Updated: readme 2018-05-23 20:33:02 +08:00
Molunerfinn 94f70cb8c6 Updated: readme 2018-05-09 15:17:03 +08:00
Molunerfinn f33df32312 Fixed: auto hide menu-bar in windows 2018-05-09 09:30:05 +08:00
Molunerfinn c1604fa3cb Updated: readme 2018-05-09 09:18:49 +08:00
Molunerfinn 0e5eee7876 1.5.0 2018-05-09 09:13:16 +08:00
Molunerfinn 00689a9931 Fixed: placeholder 2018-05-09 09:12:27 +08:00
Molunerfinn 06539d1513 Fixed: keyup enter for el-input & version check 2018-05-08 23:56:02 +08:00
Molunerfinn 74b94feb74 Finished: rename file before upload 2018-05-08 14:04:43 +08:00
Molunerfinn 757a7d1260 Finished: Tencent COS v5 version 2018-05-07 21:04:27 +08:00
Molunerfinn 2496c0b467 Added: v5 options 2018-05-07 19:55:33 +08:00
Molunerfinn 4a685e0474 Fixed: auto start setting 2018-05-02 19:34:24 +08:00
Molunerfinn 9fdd54ca16 Fixed: memeory out bug 2018-05-02 19:06:10 +08:00
Molunerfinn eaa348ad56 Added: autoStart 2018-05-02 17:17:55 +08:00
Molunerfinn 282b0dc25c Finished: custom picbed setting for displaying visible or none 2018-05-02 16:04:55 +08:00
Molunerfinn d99e45a021 Fixed: some styles 2018-05-02 14:24:59 +08:00
Molunerfinn ef8bf5476c Finished: picgo-setting page FE part 2018-04-28 16:22:35 +08:00
Molunerfinn d042c93bec Added: picgo-setting page 2018-04-28 00:16:17 +08:00
Molunerfinn ad71117876 Updated: sidebar 2018-04-14 11:02:02 +08:00
Molunerfinn fe7f688488 Finished: edit img-url in gallery page 2018-04-08 23:43:34 +08:00
Molunerfinn 65a15724a3 Fixed: #34 | macOS menubar drag file error 2018-04-08 10:27:41 +08:00
Molunerfinn 422aa52763 Added: display default picbed 2018-04-06 22:18:57 +08:00
Molunerfinn eecf98e452 Added: GitHub picbed support 2018-04-06 22:01:30 +08:00
Molunerfinn 975927ac68 Added: issue template 2018-03-12 21:26:03 +08:00
Molunerfinn 9ef615cab4 1.4.3 2018-03-12 11:03:27 +08:00
Molunerfinn fb236c3186 Fixed: qiniu uploader path undefined 2018-03-12 11:01:14 +08:00
Molunerfinn 458087a94e 1.4.2 2018-03-09 23:26:34 +08:00
Molunerfinn 4e8dfef6cb Added: qiniu upload custom path 2018-03-09 23:24:48 +08:00
Molunerfinn e1c151e310 Added: tcyun cos custom url 2018-03-09 21:08:10 +08:00
Molunerfinn 25068a8949 Added: upYun path option 2018-03-09 17:20:08 +08:00
Molunerfinn 4010a09fe4 Added: custom url rules 2018-03-09 16:18:17 +08:00
Molunerfinn f6536b1dc2 Updated: support custom paste link template 2018-03-09 14:35:41 +08:00
Molunerfinn df39511cdf Updated: filename & file extname with qiniu & weibo 2018-03-08 16:50:56 +08:00
Molunerfinn 504690b729 1.4.1 2018-01-30 19:08:00 +08:00
Molunerfinn 937979ae3d Fixed: can not use shortcut when settingWindow is closed 2018-01-30 19:05:13 +08:00
Molunerfinn 1f373fb325 1.4.0 2018-01-30 15:35:26 +08:00
Molunerfinn 92b9fbcee8 Added: quick set default picBed & quick upload clipboard files button 2018-01-30 15:35:05 +08:00
Molunerfinn 37a784225e Fixed: #17 2018-01-30 15:20:19 +08:00
Molunerfinn 16fe016c70 Fixed: readme 2018-01-29 10:55:50 +08:00
Molunerfinn 406cfffbc9 1.3.2 2018-01-18 09:31:52 +08:00
Molunerfinn e5d5bad115 Fixed: cookie error 2018-01-18 09:31:15 +08:00
Molunerfinn 7364ea6ddf Fixed: imgList error 2018-01-16 17:05:33 +08:00
Molunerfinn f657026820 Removed: some console & modified readme 2018-01-16 14:51:53 +08:00
Molunerfinn e8e78303a3 Added: weibo cookie uploader support 2018-01-16 13:55:16 +08:00
Molunerfinn 29fb9c742e Added: debug options for vscode debug 2018-01-12 17:24:56 +08:00
Molunerfinn 16f518b2ad Fixed: CI download speed 2018-01-10 20:39:08 +08:00
Molunerfinn 790367efd6 Updated: readme 2018-01-10 18:57:01 +08:00
Molunerfinn 7e9fd9d14e 1.3.1 2018-01-10 17:18:43 +08:00
Molunerfinn 9df9b547d1 Fixed: appveyor yml 2018-01-10 17:18:07 +08:00
Molunerfinn 26f6627b44 1.3.0 2018-01-10 17:14:01 +08:00
Molunerfinn dc9d5d6dfb Added: options for update helper 2018-01-10 17:12:24 +08:00
Molunerfinn b4c760c8cd Added: windows support 2018-01-10 16:51:09 +08:00
57 changed files with 3049 additions and 335 deletions
+2 -1
View File
@@ -133,7 +133,8 @@ let rendererConfig = {
resolve: {
alias: {
'@': path.join(__dirname, '../src/renderer'),
'vue$': 'vue/dist/vue.esm.js'
'vue$': 'vue/dist/vue.esm.js',
'utils': path.join(__dirname, '../src/renderer/utils')
},
extensions: ['.js', '.vue', '.json', '.css', '.node']
},
+1 -1
View File
@@ -1,4 +1,4 @@
test/unit/coverage/**
test/unit/*.js
test/e2e/*.js
dist/
dist/
+30
View File
@@ -0,0 +1,30 @@
<!--
PicGo Issue 模板
请依照该模板来提交,否则将会被关闭。
**提问之前请注意你看过FAQ、配置手册以及那些被关闭的issues。否则同样的提问也会被关闭!**
-->
## 问题类型
<!-- 你要提交的是Bug Report还是Feature Request-->
## PicGo的相关信息
<!-- 版本、所在平台(Mac或者Windows -->
## 问题重现
<!-- 如果是Bug Report请填写本项 -->
<!-- 请附上相关截图 -->
## 功能请求
<!-- 如果是Feature Request请填写本项 -->
<!-- 详细描述你所预想的功能或者是现有功能的改进。 -->
---
<!--
最后,喜欢PicGo的话不妨给它点个star~
如果可以的话,请我喝杯咖啡?首页有赞助二维码,谢谢你的支持!
-->
+1
View File
@@ -3,6 +3,7 @@ dist/electron/*
dist/web/*
build/*
!build/icons
!build/installer.nsh
coverage
node_modules/
npm-debug.log
+2 -2
View File
@@ -7,7 +7,7 @@ language: c
matrix:
include:
- os: osx
# - os: linux
- os: linux
env: CC=clang CXX=clang++ npm_config_clang=1
compiler: clang
cache:
@@ -25,7 +25,7 @@ before_install:
- mkdir -p /tmp/git-lfs && curl -L https://github.com/github/git-lfs/releases/download/v1.2.1/git-lfs-$([
"$TRAVIS_OS_NAME" == "linux" ] && echo "linux" || echo "darwin")-amd64-1.2.1.tar.gz
| tar -xz -C /tmp/git-lfs --strip-components 1 && /tmp/git-lfs/git-lfs pull
# - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install --no-install-recommends -y icnsutils graphicsmagick xz-utils; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install --no-install-recommends -y icnsutils graphicsmagick xz-utils; fi
install:
#- export DISPLAY=':99.0'
#- Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
+21 -1
View File
@@ -4,14 +4,34 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"type": "node",
"request": "launch",
"program": "${workspaceRoot}/src/main/index.dev.js",
"env": {
"DEBUG_ENV": "debug"
},
"stopOnEntry": false,
"args": [],
"cwd": "${workspaceRoot}",
// this points to the electron task runner
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron",
"runtimeArgs": [
"--nolazy"
],
"sourceMaps": true
},
{
"name": "Attach",
"type": "node",
"request": "attach",
"port": 5858,
"sourceMaps": false,
"sourceMaps": true,
"restart": true,
"outFiles": [],
"localRoot": "${workspaceRoot}",
"protocol": "inspector",
"remoteRoot": null
}
]
+58
View File
@@ -0,0 +1,58 @@
## 常见问题
> 在使用PicGo期间你会遇到很多问题,不过很多问题其实之前就有人提问过,也被解决,所以你可以先看看[使用文档](https://github.com/Molunerfinn/PicGo/wiki/%E8%AF%A6%E7%BB%86%E7%AA%97%E5%8F%A3%E7%9A%84%E4%BD%BF%E7%94%A8#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%BF%AB%E6%8D%B7%E9%94%AE),这份FAQ,以及那些被关闭的[issues](https://github.com/Molunerfinn/PicGo/issues?q=is%3Aissue+is%3Aclosed),应该能找到答案。
## 1.七牛图床上传图片成功后无法显示或图片无`http://`前缀
通常是你的七牛图床配置里的`设定访问网址`没有加上`http://`或者`https//`头。
参考:[issue#79](https://github.com/Molunerfinn/PicGo/issues/79)
## 2.能否支持图床远端同步删除
不能。有些图床(比如微博图床、SM.MS、Imgur等)不支持后台管理,为了架构统一不支持远端删除。
## 3.能否支持上传视频文件
目前不能。2.0版本出来后将会支持插件系统,届时如果有人开发了相应的插件理论可以支持任意文件上传。
## 4.微博图床上传之后无法显示预览图
通常是挂了全局代理导致的。
参考:[issue36](https://github.com/Molunerfinn/PicGo/issues/36)
## 5.能否支持某某某图床
截止v1.6,PicGo支持了如下图床:
- `微博图床` v1.0
- `七牛图床` v1.0
- `腾讯云COS v4\v5版本` v1.1 & v1.5.0
- `又拍云` v1.2.0
- `GitHub` v1.5.0
- `SM.MS` v1.5.1
- `阿里云OSS` v1.6.0
- `Imgur` v1.6.0
所以本体内将不会再支持其他图床。待2.0版本出来支持插件系统后可以由其他开发者开发相应的图床插件用以支持其他图床。
## 6.一个图床设置多个信息
不能。因为目前的架构只支持一个图床一份信息。
## 7.v2.0版本有什么新功能
在不改变PicGo现有使用界面和使用习惯的基础上,将会重构整个底层`传输->转换->上传`的架构,使其能够支持插件系统,方便其他开发者基于PicGo的底层进行二次开发。
理论上有了插件系统之后,其他开发者能够支持如下功能:
1. 能够实现上传前图片压缩
2. 能够通过图片url实现上传图片 -> 更深入地可以批量地实现图床的迁移
3. 能够支持其他图床甚至是自己的图床
等等。
届时底层架构将会独立出来成为一个独立的npm包,能够直接在命令行里调用。
目前开发进度可以参考[PicGo-Core](https://github.com/Molunerfinn/PicGo-Core)。
+26 -6
View File
@@ -22,13 +22,30 @@
## 应用说明
PicGo目前支持了`微博图床``七牛图床``腾讯云COS``又拍云`。未来将支持更多图床。
**PicGo在上传图片之后自动会将图片链接复制到你的剪贴板里,可选5种复制的链接格式。**
暂时只支持macOS系统,未来将支持windows和linux。
PicGo目前支持了
点击此处下载[应用](https://github.com/Molunerfinn/PicGo/releases)macOS用户请下载最新版本的`dmg`文件。
- `微博图床` v1.0
- `七牛图床` v1.0
- `腾讯云COS v4\v5版本` v1.1 & v1.5.0
- `又拍云` v1.2.0
- `GitHub` v1.5.0
- `SM.MS` v1.5.1
- `阿里云OSS` v1.6.0
- `Imgur` v1.6.0
如果第一次使用,请参考应用使用[手册](https://github.com/Molunerfinn/PicGo/wiki)
未来将不增加默认的图床支持。待PicGo v2.0出来后你可以自行开发第三方图床插件
支持macOS、windows 64位(>= v1.3.1),linux>= v1.6.0)。
支持快捷键`command+shift+p`macOS)或者`control+shift+p`windows\linux)用以支持快捷上传剪贴板里的图片(第一张)。PicGo v1.4.0版本及以上支持自定义快捷键,使用方法见[配置手册](https://github.com/Molunerfinn/PicGo/wiki/%E8%AF%A6%E7%BB%86%E7%AA%97%E5%8F%A3%E7%9A%84%E4%BD%BF%E7%94%A8#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%BF%AB%E6%8D%B7%E9%94%AE)。
**如果第一次使用,请参考应用使用[手册](https://github.com/Molunerfinn/PicGo/wiki)。遇到问题了还可以看看[FAQ](https://github.com/Molunerfinn/PicGo/blob/dev/FAQ.md)以及被关闭的[issues](https://github.com/Molunerfinn/PicGo/issues?q=is%3Aissue+is%3Aclosed)。**
点击此处下载[应用](https://github.com/Molunerfinn/PicGo/releases)macOS用户请下载最新版本的`dmg`文件,windows用户请下载最新版本的`exe`文件,linux用户请下载`AppImage`文件。**如果是国内用户下载github release文件速度很慢的话,推荐使用[Free Download Manager](http://www.freedownloadmanager.org/download.htm)来下载,速度会快。**
开发进度可以查看[Projects](https://github.com/Molunerfinn/PicGo/projects),会同步更新开发进度。
![](https://user-images.githubusercontent.com/12621342/34242857-d177930a-e658-11e7-9688-7405851dd5e5.gif)
@@ -36,13 +53,16 @@ PicGo目前支持了`微博图床`,`七牛图床`,`腾讯云COS`,`又拍
## 开发说明
> 目前仅针对Mac平台。WindowsLinux平台并未测试。
> 目前仅针对MacWindowsLinux平台并未测试。
如果你想要学习、开发、修改或自行构建PicGo,可以依照下面的指示:
> 如果想学习Electron-vue的开发,可以查看我写的系列教程——[Electron-vue开发实战](https://molunerfinn.com/tags/Electron-vue/)
1. 你需要有node、git环境。需要了解npm的相关知识。
2. `git clone https://github.com/Molunerfinn/PicGo.git` 并进入项目
3. `npm install` 下载依赖
4. Mac需要有Xcode环境,Windows需要有VS环境。
### 开发模式
@@ -68,7 +88,7 @@ npm run build
## 赞助
如果你喜欢PicGo并且它对你确实有帮助,欢迎给我打赏一杯咖啡的钱哈~
如果你喜欢PicGo并且它对你确实有帮助,欢迎给我打赏一杯咖啡哈~
支付宝:
+2 -3
View File
@@ -21,13 +21,12 @@ init:
install:
- ps: Install-Product node 8 x64
- choco install yarn --ignore-dependencies
- git reset --hard HEAD
- yarn
- npm install
- node --version
build_script:
#- yarn test
- yarn build
- npm run release
test: off
+8
View File
@@ -0,0 +1,8 @@
!macro preInit
SetRegView 64
WriteRegExpandStr HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation "C:\PicGo"
WriteRegExpandStr HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation "C:\PicGo"
SetRegView 32
WriteRegExpandStr HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation "C:\PicGo"
WriteRegExpandStr HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation "C:\PicGo"
!macroend
+13 -4
View File
@@ -5,10 +5,12 @@
img.logo(src="~icons/256x256.png", alt="PicGo")
h1.title PicGo
h2.desc 图片上传+管理新体验
button.download(@click="goLink('https://github.com/Molunerfinn/picgo/releases')") 免费下载Mac版
button.download(@click="goLink('https://github.com/Molunerfinn/picgo/releases')") 免费下载
button.download(@click="goLink('https://github.com/Molunerfinn/picgo')") 在github上查看
h3.desc
| 基于#[a(href="https://github.com/SimulatedGREG/electron-vue" target="_blank") electron-vue]开发
h3.desc
| 支持macOS,Windows,Linux
#container.container-fluid
.row.ex-width
img.gallery.col-xs-10.col-xs-offset-1.col-md-offset-2.col-md-8(src="https://ws1.sinaimg.cn/large/8700af19gy1fmayjwttnbj218g0p0q4e")
@@ -32,7 +34,12 @@ export default {
{
url: 'https://ws1.sinaimg.cn/large/8700af19ly1fma907llb5j20m30ed46a',
title: '精致设计',
desc: 'macOS系统下,支持拖拽至menubar图标实现上传。menubar app 窗口显示最新上传的5张图片以及剪贴板里的图片。点击图片自动将上传的链接复制到剪贴板。'
desc: 'macOS系统下,支持拖拽至menubar图标实现上传。menubar app 窗口显示最新上传的5张图片以及剪贴板里的图片。点击图片自动将上传的链接复制到剪贴板。Windows平台不支持)'
},
{
url: 'https://i.loli.net/2018/07/11/5b45768fb1276.png',
title: 'Mini小窗',
desc: 'Windows以及Linux系统下提供一个mini悬浮窗用于用户拖拽上传,节约你宝贵的桌面空间。'
},
{
url: 'https://ws1.sinaimg.cn/large/8700af19ly1fmd56zm2nej218g0p0teb',
@@ -42,12 +49,12 @@ export default {
{
url: 'https://ws1.sinaimg.cn/large/8700af19ly1fmd5ck9m0wj20lr0cxmzs',
title: '可选图床',
desc: '目前支持微博图床七牛图床。未来将支持更多。方便不同图床的上传需求。'
desc: '默认支持微博图床七牛图床、腾讯云COS、又拍云、GitHub、SM.MS、阿里云OSS、Imgur。方便不同图床的上传需求。'
},
{
url: 'https://ws1.sinaimg.cn/large/8700af19gy1fmayjwttnbj218g0p0q4e',
title: '多样链接',
desc: '支持4种剪贴板链接格式,让你的文本编辑游刃有余。'
desc: '支持4种默认剪贴板链接格式,以及一种自定义格式,让你的文本编辑游刃有余。'
}
]
}
@@ -172,6 +179,8 @@ h1
text-decoration none
color #fff
@media (max-width: 768px)
#header
padding 10vh
#container
.display-list
&__item
+14 -4
View File
@@ -1,11 +1,12 @@
{
"name": "picgo",
"version": "1.2.1",
"version": "1.6.1",
"author": "Molunerfinn <marksz@teamsz.xyz>",
"description": "Easy to upload your pic & copy to write",
"license": "MIT",
"main": "./dist/electron/main.js",
"scripts": {
"render": "webpack-dev-server --hot --colors --config .electron-vue/webpack.renderer.config.js --port 9080 --content-base app/dist",
"build": "node .electron-vue/build.js && electron-builder",
"release": "node .electron-vue/build.js && electron-builder",
"build:dir": "node .electron-vue/build.js && electron-builder --dir",
@@ -29,7 +30,7 @@
},
"build": {
"productName": "PicGo",
"appId": "org.simulatedgreg.electron-vue",
"appId": "com.molunerfinn.picgo",
"directories": {
"output": "build"
},
@@ -58,17 +59,25 @@
}
},
"win": {
"icon": "build/icons/icon.ico"
"icon": "build/icons/icon.ico",
"target": "nsis"
},
"nsis": {
"oneClick": false,
"allowToChangeInstallationDirectory": true
},
"linux": {
"icon": "build/icons"
"icon": "build/icons/"
}
},
"dependencies": {
"axios": "^0.16.1",
"dateformat": "^3.0.3",
"element-ui": "^2.0.5",
"fecha": "^2.3.3",
"fs-extra": "^4.0.2",
"image-size": "^0.6.1",
"keycode": "^2.1.9",
"lodash-id": "^0.14.0",
"lowdb": "^1.0.0",
"md5": "^2.2.1",
@@ -79,6 +88,7 @@
"vue": "^2.3.3",
"vue-electron": "^1.0.6",
"vue-gallery": "^1.2.4",
"vue-lazyload": "^1.2.6",
"vue-router": "^2.5.3",
"vuex": "^2.3.1"
},
+6
View File
@@ -29,4 +29,10 @@ if (!db.has('picBed').value()) {
}).write()
}
if (!db.has('shortKey').value()) {
db.set('shortKey', {
upload: 'CommandOrControl+Shift+P'
}).write()
}
export default db
+21
View File
@@ -0,0 +1,21 @@
import weiboUpload from '../main/utils/weiboUpload'
import qiniuUpload from '../main/utils/qiniuUpload'
import tcYunUpload from '../main/utils/tcYunUpload'
import upYunUpload from '../main/utils/upYunUpload'
import githubUpload from '../main/utils/githubUpload'
import smmsUpload from '../main/utils/smmsUpload'
import aliYunUpload from '../main/utils/aliYunUpload'
import imgurUpload from '../main/utils/imgurUpload'
const picBedHandler = {
weibo: weiboUpload,
qiniu: qiniuUpload,
tcyun: tcYunUpload,
upyun: upYunUpload,
github: githubUpload,
smms: smmsUpload,
aliyun: aliYunUpload,
imgur: imgurUpload
}
export default picBedHandler
+56
View File
@@ -0,0 +1,56 @@
import db from './index'
let picBed = [
{
type: 'weibo',
name: '微博图床',
visible: true
},
{
type: 'qiniu',
name: '七牛图床',
visible: true
},
{
type: 'tcyun',
name: '腾讯云COS',
visible: true
},
{
type: 'upyun',
name: '又拍云图床',
visible: true
},
{
type: 'github',
name: 'GitHub图床',
visible: true
},
{
type: 'smms',
name: 'SM.MS图床',
visible: true
},
{
type: 'aliyun',
name: '阿里云OSS',
visible: true
},
{
type: 'imgur',
name: 'Imgur图床',
visible: true
}
]
let picBedFromDB = db.read().get('picBed.list').value() || []
let oldLength = picBedFromDB.length
let newLength = picBed.length
if (oldLength !== newLength) {
for (let i = oldLength; i < newLength; i++) {
picBedFromDB.push(picBed[i])
}
}
export default picBedFromDB
+11
View File
@@ -24,4 +24,15 @@ require('electron').app.on('ready', () => {
})
// Require `main` process to boot app
if (process.env.DEBUG_ENV === 'debug') {
require('babel-core/register')({
'presets': [
['env', {
'targets': {
'node': true
}
}]
]
})
}
require('./index')
+247 -76
View File
@@ -6,6 +6,7 @@ import db from '../datastore'
import pasteTemplate from './utils/pasteTemplate'
import updateChecker from './utils/updateChecker'
import pkg from '../../package.json'
import picBed from '../datastore/pic-bed'
/**
* Set `__static` path to static files in production
* https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html
@@ -13,17 +14,25 @@ import pkg from '../../package.json'
if (process.env.NODE_ENV !== 'development') {
global.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
}
if (process.env.DEBUG_ENV === 'debug') {
global.__static = require('path').join(__dirname, '../../static').replace(/\\/g, '\\\\')
}
let window
let settingWindow
let miniWindow
let tray
let menu
let contextMenu
const winURL = process.env.NODE_ENV === 'development'
? `http://localhost:9080`
: `file://${__dirname}/index.html`
const settingWinURL = process.env.NODE_ENV === 'development'
? `http://localhost:9080/#setting/upload`
: `file://${__dirname}/index.html#setting/upload`
const miniWinURL = process.env.NODE_ENV === 'development'
? `http://localhost:9080/#mini-page`
: `file://${__dirname}/index.html#mini-page`
const uploadFailed = () => {
const notification = new Notification({
@@ -34,8 +43,22 @@ const uploadFailed = () => {
}
function createTray () {
tray = new Tray(`${__static}/menubar.png`)
const contextMenu = Menu.buildFromTemplate([
const menubarPic = process.platform === 'darwin' ? `${__static}/menubar.png` : `${__static}/menubar-nodarwin.png`
tray = new Tray(menubarPic)
const submenu = picBed.map(item => {
return {
label: item.name,
type: 'radio',
checked: db.read().get('picBed.current').value() === item.type,
click () {
db.read().set('picBed.current', item.type).write()
if (settingWindow) {
settingWindow.webContents.send('syncPicBed')
}
}
}
})
contextMenu = Menu.buildFromTemplate([
{
label: '关于',
click () {
@@ -56,49 +79,24 @@ function createTray () {
settingWindow.show()
settingWindow.focus()
}
if (miniWindow) {
miniWindow.hide()
}
}
},
{
label: '选择默认图床',
type: 'submenu',
submenu: [
{
label: '微博图床',
type: 'radio',
checked: db.read().get('picBed.current').value() === 'weibo',
click () {
db.read().set('picBed.current', 'weibo')
.write()
}
},
{
label: '七牛图床',
type: 'radio',
checked: db.read().get('picBed.current').value() === 'qiniu',
click () {
db.read().set('picBed.current', 'qiniu')
.write()
}
},
{
label: '腾讯云COS',
type: 'radio',
checked: db.read().get('picBed.current').value() === 'tcyun',
click () {
db.read().set('picBed.current', 'tcyun')
.write()
}
},
{
label: '又拍云图床',
type: 'radio',
checked: db.read().get('picBed.current').value() === 'upyun',
click () {
db.read().set('picBed.current', 'upyun')
.write()
}
}
]
submenu
},
{
label: '打开更新助手',
type: 'checkbox',
checked: db.get('picBed.showUpdateTip').value(),
click () {
const value = db.read().get('picBed.showUpdateTip').value()
db.read().set('picBed.showUpdateTip', !value).write()
}
},
{
role: 'quit',
@@ -106,25 +104,40 @@ function createTray () {
}
])
tray.on('right-click', () => {
window.hide()
if (window) {
window.hide()
}
tray.popUpContextMenu(contextMenu)
})
tray.on('click', () => {
let img = clipboard.readImage()
let obj = []
if (!img.isEmpty()) {
// 从剪贴板来的图片默认转为png
const imgUrl = 'data:image/png;base64,' + Buffer.from(img.toPNG(), 'binary').toString('base64')
obj.push({
width: img.getSize().width,
height: img.getSize().height,
imgUrl
})
if (process.platform === 'darwin') {
let img = clipboard.readImage()
let obj = []
if (!img.isEmpty()) {
// 从剪贴板来的图片默认转为png
const imgUrl = 'data:image/png;base64,' + Buffer.from(img.toPNG(), 'binary').toString('base64')
obj.push({
width: img.getSize().width,
height: img.getSize().height,
imgUrl
})
}
toggleWindow()
setTimeout(() => {
window.webContents.send('clipboardFiles', obj)
}, 0)
} else {
if (window) {
window.hide()
}
if (settingWindow === null) {
createSettingWindow()
settingWindow.show()
} else {
settingWindow.show()
settingWindow.focus()
}
}
toggleWindow()
setTimeout(() => {
window.webContents.send('clipboardFiles', obj)
}, 0)
})
tray.on('drag-enter', () => {
@@ -159,6 +172,9 @@ function createTray () {
}
const createWindow = () => {
if (process.platform !== 'darwin' && process.platform !== 'win32') {
return
}
window = new BrowserWindow({
height: 350,
width: 196, // 196
@@ -182,13 +198,41 @@ const createWindow = () => {
window.on('blur', () => {
window.hide()
})
}
createSettingWindow()
createMenu()
const createMiniWidow = () => {
if (miniWindow) {
return false
}
let obj = {
height: 64,
width: 64,
show: false,
frame: false,
fullscreenable: false,
resizable: false,
transparent: true,
icon: `${__static}/logo.png`,
webPreferences: {
backgroundThrottling: false
}
}
if (process.platform === 'linux') {
obj.transparent = false
}
miniWindow = new BrowserWindow(obj)
miniWindow.loadURL(miniWinURL)
miniWindow.on('closed', () => {
miniWindow = null
})
}
const createSettingWindow = () => {
settingWindow = new BrowserWindow({
const options = {
height: 450,
width: 800,
show: false,
@@ -196,20 +240,33 @@ const createSettingWindow = () => {
center: true,
fullscreenable: false,
resizable: false,
title: 'Pic',
title: 'PicGo',
vibrancy: 'ultra-dark',
transparent: true,
titleBarStyle: 'hidden',
webPreferences: {
backgroundThrottling: false
}
})
}
if (process.platform !== 'darwin') {
options.show = true
options.frame = false
options.backgroundColor = '#3f3c37'
options.transparent = false
options.icon = `${__static}/logo.png`
}
settingWindow = new BrowserWindow(options)
settingWindow.loadURL(settingWinURL)
settingWindow.on('closed', () => {
settingWindow = null
if (process.platform === 'linux') {
app.quit()
}
})
createMenu()
createMiniWidow()
}
const createMenu = () => {
@@ -278,23 +335,53 @@ const uploadClipboardFiles = async () => {
imgUrl
}
}
img = await uploader(uploadImg, 'imgFromClipboard', window.webContents)
let win
if (miniWindow.isVisible) {
win = miniWindow
} else {
win = settingWindow || window
}
img = await uploader(uploadImg, 'imgFromClipboard', win.webContents)
if (img !== false) {
const pasteStyle = db.read().get('picBed.pasteStyle').value() || 'markdown'
clipboard.writeText(pasteTemplate(pasteStyle, img[0].imgUrl))
const notification = new Notification({
title: '上传成功',
body: img[0].imgUrl,
icon: img[0].imgUrl
})
notification.show()
window.webContents.send('clipboardFiles', [])
window.webContents.send('uploadFiles', img)
if (img.length > 0) {
const pasteStyle = db.read().get('picBed.pasteStyle').value() || 'markdown'
clipboard.writeText(pasteTemplate(pasteStyle, img[0].imgUrl))
const notification = new Notification({
title: '上传成功',
body: img[0].imgUrl,
icon: img[0].imgUrl
})
notification.show()
window.webContents.send('clipboardFiles', [])
window.webContents.send('uploadFiles', img)
} else {
const notification = new Notification({
title: '上传不成功',
body: '你剪贴板最新的一条记录不是图片哦'
})
notification.show()
}
} else {
uploadFailed()
}
}
const updateDefaultPicBed = () => {
if (process.platform === 'darwin' || process.platform === 'win32') {
const types = picBed.map(item => item.type)
let submenuItem = contextMenu.items[2].submenu.items
submenuItem.forEach((item, index) => {
const result = db.read().get('picBed.current').value() === types[index]
if (result) {
item.click() // It's a bug which can not set checked status
return true
}
})
} else {
return false
}
}
ipcMain.on('uploadClipboardFiles', async (evt, file) => {
const img = await uploader(file, 'imgFromClipboard', window.webContents)
if (img !== false) {
@@ -314,8 +401,12 @@ ipcMain.on('uploadClipboardFiles', async (evt, file) => {
}
})
ipcMain.on('uploadClipboardFilesFromUploadPage', () => {
uploadClipboardFiles()
})
ipcMain.on('uploadChoosedFiles', async (evt, files) => {
const imgs = await uploader(files, 'imgFromUploader', settingWindow.webContents)
const imgs = await uploader(files, 'imgFromUploader', evt.sender)
if (imgs !== false) {
const pasteStyle = db.read().get('picBed.pasteStyle').value() || 'markdown'
let pasteText = ''
@@ -337,6 +428,69 @@ ipcMain.on('uploadChoosedFiles', async (evt, files) => {
}
})
ipcMain.on('updateShortKey', (evt, oldKey) => {
globalShortcut.unregisterAll()
for (let key in oldKey) {
globalShortcut.register(db.read().get('shortKey').value()[key], () => {
return shortKeyHash[key]()
})
}
const notification = new Notification({
title: '操作成功',
body: '你的快捷键已经修改成功'
})
notification.show()
})
ipcMain.on('updateCustomLink', (evt, oldLink) => {
const notification = new Notification({
title: '操作成功',
body: '你的自定义链接格式已经修改成功'
})
notification.show()
})
ipcMain.on('autoStart', (evt, val) => {
app.setLoginItemSettings({
openAtLogin: val
})
})
ipcMain.on('openSettingWindow', (evt) => {
if (!settingWindow) {
createSettingWindow()
} else {
settingWindow.show()
}
miniWindow.hide()
})
ipcMain.on('openMiniWindow', (evt) => {
if (!miniWindow) {
createMiniWidow()
}
miniWindow.show()
miniWindow.focus()
settingWindow.hide()
})
// update
ipcMain.on('updateDefaultPicBed', (evt) => {
updateDefaultPicBed()
})
// from mini window
ipcMain.on('syncPicBed', (evt) => {
if (settingWindow) {
settingWindow.webContents.send('syncPicBed')
}
updateDefaultPicBed()
})
const shortKeyHash = {
upload: uploadClipboardFiles
}
const isSecondInstance = app.makeSingleInstance(() => {
if (settingWindow) {
if (settingWindow.isMinimized()) {
@@ -347,16 +501,26 @@ const isSecondInstance = app.makeSingleInstance(() => {
})
if (isSecondInstance) {
console.log('is 2')
app.quit()
}
if (process.platform === 'win32') {
app.setAppUserModelId(pkg.build.appId)
}
if (process.env.XDG_CURRENT_DESKTOP && process.env.XDG_CURRENT_DESKTOP.includes('Unity')) {
process.env.XDG_CURRENT_DESKTOP = 'Unity'
}
app.on('ready', () => {
createWindow()
createTray()
createSettingWindow()
if (process.platform === 'darwin' || process.platform === 'win32') {
createTray()
}
updateChecker()
globalShortcut.register('CommandOrControl+Shift+P', () => {
globalShortcut.register(db.read().get('shortKey.upload').value(), () => {
uploadClipboardFiles()
})
})
@@ -368,15 +532,22 @@ app.on('window-all-closed', () => {
})
app.on('activate', () => {
if (window === null || settingWindow === null) {
if (window === null) {
createWindow()
}
if (settingWindow === null) {
createSettingWindow()
}
})
app.on('will-quit', () => {
globalShortcut.unregisterAll()
})
app.setLoginItemSettings({
openAtLogin: db.read().get('picBed.autoStart').value() || false
})
/**
* Auto Updater
*
+83
View File
@@ -0,0 +1,83 @@
import request from 'request-promise'
import * as img2Base64 from './img2base64'
import db from '../../datastore/index'
import { Notification, clipboard } from 'electron'
import crypto from 'crypto'
import mime from 'mime-types'
// generate OSS signature
const generateSignature = (fileName) => {
const options = db.read().get('picBed.aliyun').value()
const date = new Date().toGMTString()
const signString = `PUT\n\n${mime.lookup(fileName)}\n${date}\n/${options.bucket}/${options.path}${fileName}`
const signature = crypto.createHmac('sha1', options.accessKeySecret).update(signString).digest('base64')
return `OSS ${options.accessKeyId}:${signature}`
}
const postOptions = (fileName, signature, imgBase64) => {
const options = db.read().get('picBed.aliyun').value()
return {
method: 'PUT',
url: `https://${options.bucket}.${options.area}.aliyuncs.com/${encodeURI(options.path)}${encodeURI(fileName)}`,
headers: {
Host: `${options.bucket}.${options.area}.aliyuncs.com`,
Authorization: signature,
Date: new Date().toGMTString(),
'content-type': mime.lookup(fileName)
},
body: Buffer.from(imgBase64, 'base64'),
resolveWithFullResponse: true
}
}
const aliYunUpload = async (img, type, webContents) => {
try {
webContents.send('uploadProgress', 0)
const imgList = await img2Base64[type](img)
webContents.send('uploadProgress', 30)
const aliYunOptions = db.read().get('picBed.aliyun').value()
const customUrl = aliYunOptions.customUrl
const path = aliYunOptions.path
const length = imgList.length
generateSignature()
for (let i in imgList) {
const signature = generateSignature(imgList[i].fileName)
const options = postOptions(imgList[i].fileName, signature, imgList[i].base64Image)
let body = await request(options)
if (body.statusCode === 200) {
delete imgList[i].base64Image
if (customUrl) {
imgList[i]['imgUrl'] = `${customUrl}/${path}${imgList[i].fileName}`
} else {
imgList[i]['imgUrl'] = `https://${aliYunOptions.bucket}.${aliYunOptions.area}.aliyuncs.com/${path}${imgList[0].fileName}`
}
imgList[i]['type'] = 'aliyun'
if (i - length === -1) {
webContents.send('uploadProgress', 60)
}
} else {
webContents.send('uploadProgress', -1)
const notification = new Notification({
title: '上传失败!',
body: '上传失败!'
})
notification.show()
return false
}
}
webContents.send('uploadProgress', 100)
return imgList
} catch (err) {
webContents.send('uploadProgress', -1)
const notification = new Notification({
title: '上传失败!',
body: `请检查你的配置项是否正确`
})
notification.show()
clipboard.writeText('https://cloud.tencent.com/document/product/436/8432')
throw new Error(err)
}
}
export default aliYunUpload
+66
View File
@@ -0,0 +1,66 @@
import request from 'request-promise'
import * as img2Base64 from './img2base64'
import db from '../../datastore/index'
import { Notification } from 'electron'
const postOptions = (fileName, options, data) => {
const path = options.path || ''
const {token, repo} = options
return {
method: 'PUT',
url: `https://api.github.com/repos/${repo}/contents/${encodeURI(path)}${encodeURI(fileName)}`,
headers: {
Authorization: `token ${token}`,
'User-Agent': 'PicGo'
},
body: data,
json: true
}
}
const githubUpload = async function (img, type, webContents) {
try {
webContents.send('uploadProgress', 0)
const imgList = await img2Base64[type](img)
const length = imgList.length
const githubOptions = db.read().get('picBed.github').value()
webContents.send('uploadProgress', 30)
for (let i in imgList) {
const data = {
message: 'Upload by PicGo',
branch: githubOptions.branch,
content: imgList[i].base64Image,
path: githubOptions.path + encodeURI(imgList[i].fileName)
}
const postConfig = postOptions(imgList[i].fileName, githubOptions, data)
const body = await request(postConfig)
if (body) {
delete imgList[i].base64Image
if (githubOptions.customUrl) {
imgList[i]['imgUrl'] = `${githubOptions.customUrl}/${githubOptions.path}${imgList[i].fileName}`
} else {
imgList[i]['imgUrl'] = body.content.download_url
}
imgList[i]['type'] = 'github'
if (i - length === -1) {
webContents.send('uploadProgress', 60)
}
} else {
webContents.send('uploadProgress', -1)
return new Error()
}
}
webContents.send('uploadProgress', 100)
return imgList
} catch (err) {
webContents.send('uploadProgress', -1)
const notification = new Notification({
title: '上传失败!',
body: '服务端出错,请重试'
})
notification.show()
throw new Error(err)
}
}
export default githubUpload
+101 -12
View File
@@ -1,33 +1,86 @@
import fs from 'fs-extra'
import path from 'path'
import sizeOf from 'image-size'
import fecha from 'fecha'
import { BrowserWindow, ipcMain } from 'electron'
import db from '../../datastore/index.js'
const renameURL = process.env.NODE_ENV === 'development' ? `http://localhost:9080/#rename-page` : `file://${__dirname}/index.html#rename-page`
const createRenameWindow = () => {
let options = {
height: 175,
width: 300,
show: true,
fullscreenable: false,
resizable: false,
vibrancy: 'ultra-dark',
webPreferences: {
backgroundThrottling: false
}
}
if (process.platform !== 'darwin') {
options.show = true
options.backgroundColor = '#3f3c37'
options.autoHideMenuBar = true
options.transparent = false
}
const window = new BrowserWindow(options)
window.loadURL(renameURL)
return window
}
const imgFromPath = async (imgPath) => {
let results = []
const rename = db.read().get('picBed.rename').value()
const autoRename = db.read().get('picBed.autoRename').value()
await Promise.all(imgPath.map(async item => {
let name
let fileName
if (autoRename) {
fileName = fecha.format(new Date(), 'YYYYMMDDHHmmss') + path.extname(item)
} else {
fileName = path.basename(item)
}
if (rename) {
const window = createRenameWindow()
await waitForShow(window.webContents)
window.webContents.send('rename', fileName, window.webContents.id)
name = await waitForRename(window, window.webContents.id)
}
let buffer = await fs.readFile(item)
let base64Image = Buffer.from(buffer, 'binary').toString('base64')
let fileName = path.basename(item)
let base64Image = Buffer.from(buffer).toString('base64')
let imgSize = sizeOf(item)
results.push({
base64Image,
fileName,
fileName: name || fileName,
width: imgSize.width,
height: imgSize.height
height: imgSize.height,
extname: path.extname(item)
})
}))
return results
}
const imgFromClipboard = (file) => {
const imgFromClipboard = async (file) => {
let result = []
let rename = db.read().get('picBed.rename').value()
if (file !== null) {
const today = new Date().toLocaleString().replace(/[ ]+/g, '-').replace(/\/+/g, '-')
let name
const today = fecha.format(new Date(), 'YYYYMMDDHHmmss') + '.png'
if (rename) {
const window = createRenameWindow()
await waitForShow(window.webContents)
window.webContents.send('rename', today, window.webContents.id)
name = await waitForRename(window, window.webContents.id)
}
result.push({
base64Image: file.imgUrl.replace(/^data\S+,/, ''),
fileName: `${today}.png`,
fileName: name || today,
width: file.width,
height: file.height
height: file.height,
extname: '.png'
})
}
return result
@@ -35,21 +88,57 @@ const imgFromClipboard = (file) => {
const imgFromUploader = async (files) => {
let results = []
const rename = db.read().get('picBed.rename').value()
const autoRename = db.read().get('picBed.autoRename').value()
await Promise.all(files.map(async item => {
let name
let fileName
if (autoRename) {
fileName = fecha.format(new Date(), 'YYYYMMDDHHmmss') + path.extname(item.name)
} else {
fileName = path.basename(item.path)
}
if (rename) {
const window = createRenameWindow()
await waitForShow(window.webContents)
window.webContents.send('rename', fileName, window.webContents.id)
name = await waitForRename(window, window.webContents.id)
}
let buffer = await fs.readFile(item.path)
let base64Image = Buffer.from(buffer, 'binary').toString('base64')
let fileName = item.name
let base64Image = Buffer.from(buffer).toString('base64')
let imgSize = sizeOf(item.path)
results.push({
base64Image,
fileName,
fileName: name || fileName,
width: imgSize.width,
height: imgSize.height
height: imgSize.height,
extname: path.extname(item.name)
})
}))
return results
}
const waitForShow = (webcontent) => {
return new Promise((resolve, reject) => {
webcontent.on('dom-ready', () => {
resolve()
})
})
}
const waitForRename = (window, id) => {
return new Promise((resolve, reject) => {
ipcMain.once(`rename${id}`, (evt, newName) => {
resolve(newName)
window.hide()
})
window.on('close', () => {
resolve(null)
ipcMain.removeAllListeners(`rename${id}`)
})
})
}
export {
imgFromPath,
imgFromClipboard,
+65
View File
@@ -0,0 +1,65 @@
import request from 'request-promise'
import * as img2Base64 from './img2base64'
import db from '../../datastore/index'
import { Notification, clipboard } from 'electron'
const postOptions = (fileName, imgBase64) => {
const options = db.read().get('picBed.imgur').value()
const clientId = options.clientId
let obj = {
method: 'POST',
url: `https://api.imgur.com/3/image`,
headers: {
Authorization: 'Client-ID ' + clientId,
'content-type': 'multipart/form-data',
'User-Agent': 'PicGo'
},
formData: {
image: imgBase64,
type: 'base64',
name: fileName
}
}
if (options.proxy) {
obj.proxy = options.proxy
}
return obj
}
const imgurUpload = async (img, type, webContents) => {
try {
webContents.send('uploadProgress', 0)
const imgList = await img2Base64[type](img)
webContents.send('uploadProgress', 30)
const length = imgList.length
for (let i in imgList) {
const options = postOptions(imgList[i].fileName, imgList[i].base64Image)
let body = await request(options)
body = JSON.parse(body)
if (body.success) {
delete imgList[i].base64Image
imgList[i]['imgUrl'] = `${body.data.link}`
imgList[i]['type'] = 'imgur'
if (i - length === -1) {
webContents.send('uploadProgress', 60)
}
} else {
webContents.send('uploadProgress', -1)
return new Error()
}
}
webContents.send('uploadProgress', 100)
return imgList
} catch (err) {
webContents.send('uploadProgress', -1)
const notification = new Notification({
title: '上传失败!',
body: `请检查你的配置以及网络!`
})
notification.show()
clipboard.writeText('http://docs.imgur.com/api/errno/')
throw new Error(err)
}
}
export default imgurUpload
+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/g, 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').value() || ''
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}`,
+55
View File
@@ -0,0 +1,55 @@
import request from 'request-promise'
import * as img2Base64 from './img2base64'
import { Notification } from 'electron'
const postOptions = (fileName, imgBase64) => {
return {
method: 'POST',
url: `https://sm.ms/api/upload`,
headers: {
contentType: 'multipart/form-data',
'User-Agent': 'PicGo'
},
formData: {
smfile: {
value: Buffer.from(imgBase64, 'base64'),
options: {
filename: fileName
}
},
ssl: 'true'
}
}
}
const smmsUpload = async function (img, type, webContents) {
try {
webContents.send('uploadProgress', 0)
const imgList = await img2Base64[type](img)
webContents.send('uploadProgress', 30)
for (let i in imgList) {
const postConfig = postOptions(imgList[i].fileName, imgList[i].base64Image)
let body = await request(postConfig)
body = JSON.parse(body)
if (body.code === 'success') {
delete imgList[i].base64Image
imgList[i]['imgUrl'] = body.data.url
} else {
webContents.send('uploadProgress', -1)
return new Error()
}
}
webContents.send('uploadProgress', 100)
return imgList
} catch (err) {
webContents.send('uploadProgress', -1)
const notification = new Notification({
title: '上传失败!',
body: '服务端出错,请重试'
})
notification.show()
throw new Error(err)
}
}
export default smmsUpload
+110 -34
View File
@@ -3,44 +3,75 @@ import * as img2Base64 from './img2base64'
import db from '../../datastore/index'
import { Notification, clipboard } from 'electron'
import crypto from 'crypto'
import mime from 'mime-types'
// generate COS signature string
const generateSignature = () => {
const generateSignature = (fileName) => {
const options = db.read().get('picBed.tcyun').value()
const secretId = options.secretId
const secretKey = options.secretKey
const appId = options.appId
const bucket = options.bucket
const random = Math.floor(Math.random() * 10000000000)
const current = parseInt(new Date().getTime() / 1000) - 1
const expired = current + 3600
let signature
let signTime
if (!options.version || options.version === 'v4') {
const random = Math.floor(Math.random() * 10000000000)
const current = parseInt(new Date().getTime() / 1000) - 1
const expired = current + 3600
const multiSignature = `a=${appId}&b=${bucket}&k=${secretId}&e=${expired}&t=${current}&r=${random}&f=`
const multiSignature = `a=${appId}&b=${bucket}&k=${secretId}&e=${expired}&t=${current}&r=${random}&f=`
const signHexKey = crypto.createHmac('sha1', secretKey).update(multiSignature).digest()
const tempString = Buffer.concat([signHexKey, Buffer.from(multiSignature)])
const signature = Buffer.from(tempString).toString('base64')
const signHexKey = crypto.createHmac('sha1', secretKey).update(multiSignature).digest()
const tempString = Buffer.concat([signHexKey, Buffer.from(multiSignature)])
signature = Buffer.from(tempString).toString('base64')
} else {
// https://cloud.tencent.com/document/product/436/7778#signature
const today = Math.floor(new Date().getTime() / 1000)
const tomorrow = today + 86400
signTime = `${today};${tomorrow}`
const signKey = crypto.createHmac('sha1', secretKey).update(signTime).digest('hex')
const httpString = `put\n/${options.path}${fileName}\n\nhost=${options.bucket}.cos.${options.area}.myqcloud.com\n`
const sha1edHttpString = crypto.createHash('sha1').update(httpString).digest('hex')
const stringToSign = `sha1\n${signTime}\n${sha1edHttpString}\n`
signature = crypto.createHmac('sha1', signKey).update(stringToSign).digest('hex')
}
return {
signature,
appId,
bucket
bucket,
signTime
}
}
const postOptions = (fileName, signature, imgBase64) => {
const area = db.read().get('picBed.tcyun.area').value()
const path = db.read().get('picBed.tcyun.path').value()
return {
method: 'POST',
url: `http://${area}.file.myqcloud.com/files/v2/${signature.appId}/${signature.bucket}/${path}${fileName}`,
headers: {
Host: `${area}.file.myqcloud.com`,
Authorization: signature.signature,
contentType: 'multipart/form-data'
},
formData: {
op: 'upload',
filecontent: Buffer.from(imgBase64, 'base64')
const options = db.read().get('picBed.tcyun').value()
const area = options.area
const path = options.path
if (!options.version || options.version === 'v4') {
return {
method: 'POST',
url: `http://${area}.file.myqcloud.com/files/v2/${signature.appId}/${signature.bucket}/${encodeURI(path)}${fileName}`,
headers: {
Host: `${area}.file.myqcloud.com`,
Authorization: signature.signature,
contentType: 'multipart/form-data'
},
formData: {
op: 'upload',
filecontent: Buffer.from(imgBase64, 'base64')
}
}
} else {
return {
method: 'PUT',
url: `http://${options.bucket}.cos.${options.area}.myqcloud.com/${encodeURI(path)}${encodeURI(fileName)}`,
headers: {
Host: `${options.bucket}.cos.${options.area}.myqcloud.com`,
Authorization: `q-sign-algorithm=sha1&q-ak=${options.secretId}&q-sign-time=${signature.signTime}&q-key-time=${signature.signTime}&q-header-list=host&q-url-param-list=&q-signature=${signature.signature}`,
contentType: mime.lookup(fileName)
},
body: Buffer.from(imgBase64, 'base64'),
resolveWithFullResponse: true
}
}
}
@@ -50,15 +81,49 @@ const tcYunUpload = async (img, type, webContents) => {
webContents.send('uploadProgress', 0)
const imgList = await img2Base64[type](img)
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
const useV4 = !tcYunOptions.version || tcYunOptions.version === 'v4'
for (let i in imgList) {
const options = postOptions(imgList[i].fileName, singature, imgList[i].base64Image)
const signature = generateSignature(imgList[i].fileName)
const options = postOptions(imgList[i].fileName, signature, imgList[i].base64Image)
const res = await request(options)
const body = JSON.parse(res)
if (body.message === 'SUCCESS') {
.then(res => res)
.catch(err => {
console.log(err.response.body)
return {
statusCode: 400,
body: {
msg: '认证失败!'
}
}
})
let body
if (useV4) {
body = JSON.parse(res)
} else {
body = res
}
if (useV4 && 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)
}
} else if (!useV4 && body && body.statusCode === 200) {
delete imgList[i].base64Image
if (customUrl) {
imgList[i]['imgUrl'] = `${customUrl}/${path}${imgList[i].fileName}`
} else {
imgList[i]['imgUrl'] = `https://${tcYunOptions.bucket}.cos.${tcYunOptions.area}.myqcloud.com/${path}${imgList[i].fileName}`
}
imgList[i]['type'] = 'tcyun'
if (i - length === -1) {
webContents.send('uploadProgress', 60)
@@ -70,19 +135,30 @@ const tcYunUpload = async (img, type, webContents) => {
body: res.body.msg
})
notification.show()
return false
}
}
webContents.send('uploadProgress', 100)
return imgList
} catch (err) {
const body = JSON.parse(err.error)
const options = db.read().get('picBed.tcyun').value()
let body
if (!options.version || options.version === 'v4') {
body = JSON.parse(err.error)
const notification = new Notification({
title: '上传失败!',
body: `错误码:${body.code},请打开浏览器粘贴地址查看相关原因。`
})
notification.show()
clipboard.writeText('https://cloud.tencent.com/document/product/436/8432')
} else {
const notification = new Notification({
title: '上传失败!',
body: `请检查你的配置项是否正确`
})
notification.show()
}
webContents.send('uploadProgress', -1)
const notification = new Notification({
title: '上传失败!',
body: `错误码:${body.code},请打开浏览器粘贴地址查看相关原因。`
})
notification.show()
clipboard.writeText('https://cloud.tencent.com/document/product/436/8432')
throw new Error(err)
}
}
+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}/${encodeURI(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}/${encodeURI(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)
+6 -5
View File
@@ -22,7 +22,7 @@ const checkVersion = async () => {
type: 'info',
title: '发现新版本',
buttons: ['Yes', 'No'],
message: '发现新版本,是否去下载最新的版本?',
message: '发现新版本,更新了很多功能,是否去下载最新的版本?',
checkboxLabel: '以后不再提醒',
checkboxChecked: false
}, (res, checkboxChecked) => {
@@ -44,15 +44,16 @@ const checkVersion = async () => {
const compareVersion2Update = (current, latest) => {
const currentVersion = current.split('.').map(item => parseInt(item))
const latestVersion = latest.split('.').map(item => parseInt(item))
let flag = false
for (let i = 0; i < 3; i++) {
if (currentVersion[i] < latestVersion[i]) {
flag = true
return true
}
if (currentVersion[i] > latestVersion[i]) {
return false
}
}
return flag
return false
}
export default checkVersion
+25 -24
View File
@@ -1,34 +1,35 @@
import weiboUpload from './weiboUpload'
import qiniuUpload from './qiniuUpload'
import tcYunUpload from './tcYunUpload'
import upYunUpload from './upYunUpload'
import db from '../../datastore/index'
import { Notification } from 'electron'
import picBeds from '../../datastore/pic-bed-handler'
const checkUploader = (type) => {
const currentUploader = db.read().get(`picBed.${type}`).value()
if (currentUploader) {
return true
} else {
return false
}
}
// const checkUploader = (type) => {
// const currentUploader = db.read().get(`picBed.${type}`).value()
// if (currentUploader) {
// return true
// } else {
// return false
// }
// }
const uploader = (img, type, webContents) => {
if (db.read().get('picBed.uploadNotification').value()) {
const notification = new Notification({
title: '上传进度',
body: '正在上传'
})
notification.show()
}
const uploadType = db.read().get('picBed.current').value()
if (checkUploader(uploadType)) {
switch (uploadType) {
case 'weibo':
return weiboUpload(img, type, webContents)
case 'qiniu':
return qiniuUpload(img, type, webContents)
case 'tcyun':
return tcYunUpload(img, type, webContents)
case 'upyun':
return upYunUpload(img, type, webContents)
}
} else {
// if (checkUploader(uploadType)) {
try {
return picBeds[uploadType](img, type, webContents)
} catch (e) {
console.log(e)
return false
}
// } else {
// return false
// }
}
export default uploader
+34 -8
View File
@@ -28,26 +28,51 @@ const weiboUpload = async function (img, type, webContents) {
password: db.read().get('picBed.weibo.password').value()
}
const quality = db.read().get('picBed.weibo.quality').value()
const cookie = db.read().get('picBed.weibo.cookie').value()
const chooseCookie = db.read().get('picBed.weibo.chooseCookie').value()
const options = postOptions(formData)
const res = await rp(options)
let res
if (!chooseCookie) {
res = await rp(options)
}
webContents.send('uploadProgress', 30)
if (res.body.retcode === 20000000) {
for (let i in res.body.data.crossdomainlist) {
await rp.get(res.body.data.crossdomainlist[i])
if (chooseCookie || res.body.retcode === 20000000) {
if (res) {
for (let i in res.body.data.crossdomainlist) {
await rp.get(res.body.data.crossdomainlist[i])
}
}
webContents.send('uploadProgress', 60)
const imgList = await img2Base64[type](img)
for (let i in imgList) {
let result = await rp.post(UPLOAD_URL, {
let opt = {
formData: {
b64_data: imgList[i].base64Image
}
})
}
if (chooseCookie) {
opt.headers = {
Cookie: cookie
}
}
let result = await rp.post(UPLOAD_URL, opt)
result = result.replace(/<.*?\/>/, '').replace(/<(\w+).*?>.*?<\/\1>/, '')
delete imgList[i].base64Image
const resTextJson = JSON.parse(result)
imgList[i]['imgUrl'] = `https://ws1.sinaimg.cn/${quality}/${resTextJson.data.pics.pic_1.pid}`
imgList[i]['type'] = 'weibo'
if (resTextJson.data.pics.pic_1.pid === undefined) {
webContents.send('uploadProgress', -1)
const notification = new Notification({
title: '上传失败!',
body: '微博Cookie失效,请在网页版重新登录一遍'
})
notification.show()
return new Error()
} else {
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
@@ -58,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)
+5 -1
View File
@@ -18,6 +18,10 @@
height 100%
font-family "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif
#app
overflow-x hidden
user-select none
overflow hidden
.el-button-group
width 100%
.el-button
width 50%
</style>
+7 -5
View File
@@ -1,10 +1,10 @@
@font-face {font-family: "iconfont";
src: url('iconfont.eot?t=1513753554908'); /* IE9*/
src: url('iconfont.eot?t=1513753554908#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff;charset=utf-8;base64,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') format('woff'),
url('iconfont.ttf?t=1513753554908') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
url('iconfont.svg?t=1513753554908#iconfont') format('svg'); /* iOS 4.1- */
src: url('iconfont.eot?t=1523001890286'); /* IE9*/
src: url('iconfont.eot?t=1523001890286#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff;charset=utf-8;base64,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') format('woff'),
url('iconfont.ttf?t=1523001890286') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
url('iconfont.svg?t=1523001890286#iconfont') format('svg'); /* iOS 4.1- */
}
[class*=" el-icon-ui"], [class^=el-icon-ui] {
@@ -15,6 +15,8 @@
-moz-osx-font-smoothing: grayscale;
}
.el-icon-ui-github:before { content: "\e7ab"; }
.el-icon-ui-weibo:before { content: "\e61c"; }
.el-icon-ui-tcyun:before { content: "\e64c"; }
Binary file not shown.
+3
View File
@@ -27,6 +27,9 @@ t9.5 -10.5t21.5 -4h37h67h81h80h64h36q23 0 34 12t2 38q-5 13 -9.5 30.5t-9.5 34.5q-
<glyph glyph-name="github" unicode="&#59307;" d="M512 822.894c-248.508 0-450-201.456-450-450 0-198.828 128.934-367.506 307.728-426.996 22.482-4.158 30.762 9.756 30.762 21.654 0 10.728-0.414 46.188-0.612 83.772-125.19-27.216-151.614 53.1-151.614 53.1-20.466 52.002-49.968 65.844-49.968 65.844-40.824 27.936 3.078 27.36 3.078 27.36 45.18-3.168 68.976-46.368 68.976-46.368 40.14-68.796 105.264-48.906 130.968-37.404 4.032 29.088 15.696 48.942 28.566 60.174-99.954 11.376-205.02 49.968-205.02 222.39 0 49.122 17.586 89.28 46.368 120.78-4.68 11.34-20.088 57.096 4.356 119.088 0 0 37.8 12.078 123.786-46.134 35.892 9.972 74.394 14.976 112.644 15.156 38.232-0.18 76.752-5.166 112.716-15.156 85.896 58.23 123.624 46.134 123.624 46.134 24.498-61.992 9.09-107.748 4.428-119.088 28.854-31.518 46.314-71.658 46.314-120.78 0-172.836-105.282-210.888-205.488-222.03 16.146-13.968 30.528-41.346 30.528-83.322 0-60.21-0.522-108.666-0.522-123.498 0-11.97 8.1-26.01 30.906-21.6 178.704 59.562 307.476 228.186 307.476 426.942 0 248.544-201.474 450-450 450z" horiz-adv-x="1024" />
<glyph glyph-name="weibo" unicode="&#58908;" d="M1013.46529415 545.47540804c0-14.8526376-11.46535652-26.88232091-25.58940469-26.8823209-14.12272255 0-25.56953354 12.03100762-25.56953352 26.8823209 0 1.34457994 0.18810806 2.64941756 0.37224319 3.94895792l-0.37224319 0c0 139.92901597-108.14394722 253.3466299-241.5222759 253.3466299-2.53151878 0-4.99680252-0.32587799-7.5296456-0.39211435l0 0.7842274c-12.33966437 1.93142522-21.81663342 13.00334437-21.81663343 26.49020656 0 13.48421356 9.47564343 24.53891019 21.81663343 26.4703354l0 0.02251979c0.06358643 0 0.14571841 0 0.20532929 0 1.16441905 0.17486105 2.34605934 0.36959327 3.56744197 0.36959325 0.39608859 0 0.79085155-0.08610622 1.18164029-0.10862599 0.79217586 0.04371526 1.57640327 0.10862599 2.38712599 0.10862599 161.74962231 0 292.86932347-137.4968504 292.86932348-307.08875061l-0.39608859 0C1013.25863924 548.1235012899999 1013.46529415 546.8199879900001 1013.46529415 545.47540804zM863.34794096 518.59176283c-14.12139824 0-25.56953354 12.03100762-25.56953354 26.8823209 0 3.56081781 0.68487418 6.96797006 1.88770995 10.0730871-2.98854387 64.2960783-52.1948614 115.73982917-113.60042345 118.60649873-2.81765575-1.13130087-5.84726626-1.80292934-9.0384895-1.80292935-14.11874832 0-25.58940468 12.02968331-25.5894047 26.86112543 0 13.50540903 9.47564343 24.55878134 21.81663342 26.49020656l0 0c0.06358643 0 0.12319732 0.0238454 0.18678375 0.0238454 1.18429021 0.17221243 2.3646062 0.36694464 3.58731185 0.36694464 0.39608859 0 0.79085155-0.10862599 1.18164028-0.12849716 0.79217586 0.06358643 1.57640327 0.12849716 2.38712598 0.12849716 92.9614561 0 168.34005063-79.10500064 168.34005064-176.6711449l-0.39078874 0c0.18810806-1.30086468 0.39078875-2.60437798 0.39078874-3.94895792C888.93602132 530.6227704400001 877.47066481 518.59176283 863.34794096 518.59176283zM754.87281718 449.10547541c20.4879504 2.58450683 43.02787472 1.45453025 68.32981684-5.21405452 70.0267688-18.47969046 98.02449494-65.7929995 94.95381909-137.84392388-3.10909257-73.41934842-80.46017767-204.8583047-196.12979627-275.14471646-77.16430135-51.85441078-177.86470788-87.75137581-282.42001895-87.7513758-221.16017403 0-429.07193204 134.69774021-429.07193204 300.83612299 0 2.19239377 0.20797922 4.40730732 0.30070958 6.60367404 0 0.0834563 0.01059709 0.17221243 0.01059709 0.23712316 0.15499118 3.17135339 0.35237202 6.34138245 0.70474535 9.51406017C25.08266092 424.84872796 281.96361331 686.07605117 358.85634901 693.93819893c71.77008594 7.33756332 148.28925417-16.54694094 142.21546312-106.1635069-0.4583494-6.73084688-1.94997206-13.94123735-3.85755316-21.34636133 57.46322827 34.46230593 125.08565114 58.5640622 185.94940747 46.83906271C766.77400333 597.1774775700001 787.13875511 513.92348823 754.87281718 449.10547541zM420.4857885 420.8110152c-165.81383039 0-300.19098985-93.13366851-300.19098984-208.04555373 0-114.89068974 134.37715946-208.02700817 300.19098984-208.02700818 165.77276377 0 300.16979438 93.13631843 300.16979438 208.02700818C720.6569072 327.67734540000004 586.25855228 420.8110152 420.4857885 420.8110152zM387.57869037 58.58919872000001c-86.91018613 0-157.33436782 65.55852496-157.33436783 146.3988943 0 80.84566786 70.4241817 146.39889428 157.33436783 146.39889429 86.90753621 0 157.35291338-65.5519021 157.35291337-146.39889429C544.93160374 124.1490493 474.48622658 58.58919872000001 387.57869037 58.58919872000001zM369.22484715 220.25404044000004c-28.36864372 0-51.34307333-24.08056079-51.34307335-53.76331621 0-29.68407973 22.97442832-53.74741927 51.34307335-53.74741926 28.36731941 0 51.36559312 24.06333954 51.36559313 53.74741926C420.59044028 196.17480396999997 397.59216656 220.25404044000004 369.22484715 220.25404044000004z" horiz-adv-x="1024" />

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.
Binary file not shown.
+221
View File
@@ -0,0 +1,221 @@
<template>
<div id="mini-page"
:style="{ backgroundImage: 'url(' + logo + ')' }"
:class="{ linux: os === 'linux' }"
>
<!-- <i class="el-icon-upload2"></i> -->
<div
id="upload-area"
:class="{ 'is-dragover': dragover, uploading: showProgress, linux: os === 'linux' }" @drop.prevent="onDrop" @dragover.prevent="dragover = true" @dragleave.prevent="dragover = false"
:style="{ backgroundPosition: '0 ' + progress + '%'}"
>
<div id="upload-dragger" @dblclick="openUplodWindow">
<input type="file" id="file-uploader" @change="onChange" multiple>
</div>
</div>
</div>
</template>
<script>
import mixin from './mixin'
import picBed from '../../datastore/pic-bed.js'
export default {
name: 'mini-page',
mixins: [mixin],
data () {
return {
logo: 'static/logo.png',
dragover: false,
progress: 0,
showProgress: false,
showError: false,
dragging: false,
wX: '',
wY: '',
screenX: '',
screenY: '',
menu: null,
os: ''
}
},
created () {
this.os = process.platform
},
mounted () {
this.$electron.ipcRenderer.on('uploadProgress', (event, progress) => {
if (progress !== -1) {
this.showProgress = true
this.progress = progress
} else {
this.progress = 100
this.showError = true
}
})
this.buildMenu()
window.addEventListener('mousedown', this.handleMouseDown, false)
window.addEventListener('mousemove', this.handleMouseMove, false)
window.addEventListener('mouseup', this.handleMouseUp, false)
},
watch: {
progress (val) {
if (val === 100) {
setTimeout(() => {
this.showProgress = false
this.showError = false
}, 1000)
setTimeout(() => {
this.progress = 0
}, 1200)
}
}
},
methods: {
onDrop (e) {
this.dragover = false
this.ipcSendFiles(e.dataTransfer.files)
},
openUplodWindow () {
document.getElementById('file-uploader').click()
},
onChange (e) {
this.ipcSendFiles(e.target.files)
document.getElementById('file-uploader').value = ''
},
ipcSendFiles (files) {
let sendFiles = []
Array.from(files).forEach((item, index) => {
let obj = {
name: item.name,
path: item.path
}
sendFiles.push(obj)
})
this.$electron.ipcRenderer.send('uploadChoosedFiles', sendFiles)
},
handleMouseDown (e) {
this.dragging = true
this.wX = e.pageX
this.wY = e.pageY
this.screenX = e.screenX
this.screenY = e.screenY
},
handleMouseMove (e) {
e.preventDefault()
e.stopPropagation()
if (this.dragging) {
const xLoc = e.screenX - this.wX
const yLoc = e.screenY - this.wY
this.$electron.remote.BrowserWindow.getFocusedWindow().setBounds({
x: xLoc,
y: yLoc,
width: 64,
height: 64
})
}
},
handleMouseUp (e) {
this.dragging = false
if (this.screenX === e.screenX && this.screenY === e.screenY) {
if (e.button === 0) { // left mouse
this.openUplodWindow()
} else {
let _this = this
const types = picBed.map(item => item.type)
let submenuItem = this.menu.items[1].submenu.items
submenuItem.forEach((item, index) => {
const result = _this.$db.read().get('picBed.current').value() === types[index]
if (result) {
item.click()
return true
}
})
this.openContextMenu()
}
}
},
openContextMenu () {
this.menu.popup(this.$electron.remote.getCurrentWindow())
},
buildMenu () {
const _this = this
const submenu = picBed.map(item => {
return {
label: item.name,
type: 'radio',
checked: this.$db.read().get('picBed.current').value() === item.type,
click () {
_this.$db.read().set('picBed.current', item.type).write()
_this.$electron.ipcRenderer.send('syncPicBed')
}
}
})
const template = [
{
label: '打开详细窗口',
click () {
_this.$electron.ipcRenderer.send('openSettingWindow')
}
},
{
label: '选择默认图床',
type: 'submenu',
submenu
},
{
label: '剪贴板图片上传',
click () {
_this.$electron.ipcRenderer.send('uploadClipboardFilesFromUploadPage')
}
},
{
role: 'quit',
label: '退出'
}
]
this.menu = this.$electron.remote.Menu.buildFromTemplate(template)
}
},
beforeDestroy () {
this.$electron.ipcRenderer.removeAllListeners('uploadProgress')
window.removeEventListener('mousedown', this.handleMouseDown, false)
window.removeEventListener('mousemove', this.handleMouseMove, false)
window.removeEventListener('mouseup', this.handleMouseUp, false)
}
}
</script>
<style lang='stylus'>
#mini-page
background #409EFF
color #FFF
height 100vh
width 100vw
border-radius 50%
text-align center
line-height 100vh
font-size 40px
background-size 90vh 90vw
background-position center center
background-repeat no-repeat
position relative
border 4px solid #fff
box-sizing border-box
cursor pointer
&.linux
border-radius 0
background-size 100vh 100vw
#upload-area
height 100%
width 100%
border-radius 50%
transition all .2s ease-in-out
&.linux
border-radius 0
&.uploading
background: linear-gradient(to top, #409EFF 50%, #fff 51%)
background-size 200%
#upload-dragger
height 100%
&.is-dragover
background rgba(0,0,0,0.3)
#file-uploader
display none
</style>
+59
View File
@@ -0,0 +1,59 @@
<template>
<div id="rename-page">
<el-form
@submit.native.prevent
>
<el-form-item
label="文件改名"
>
<el-input
v-model="fileName"
size="small"
@keyup.enter.native="confirmName"
></el-input>
</el-form-item>
</el-form>
<el-row>
<div class="pull-right">
<el-button @click="cancel" round size="mini">取消</el-button>
<el-button type="primary" @click="confirmName" round size="mini">确定</el-button>
</div>
</el-row>
</div>
</template>
<script>
export default {
name: 'rename-page',
data () {
return {
fileName: '',
id: null
}
},
created () {
this.$electron.ipcRenderer.on('rename', (event, name, id) => {
this.fileName = name
this.id = id
})
},
methods: {
confirmName () {
this.$electron.ipcRenderer.send(`rename${this.id}`, this.fileName)
},
cancel () {
this.$electron.ipcRenderer.send(`rename${this.id}`, null)
}
},
beforeDestroy () {
this.$electron.ipcRenderer.removeAllListeners('rename')
}
}
</script>
<style lang='stylus'>
#rename-page
padding 0 20px
.pull-right
float right
.el-form-item__label
color #ddd
</style>
+215 -31
View File
@@ -2,13 +2,19 @@
<div id="setting-page">
<div class="fake-title-bar">
PicGo - {{ version }}
<div class="handle-bar" v-if="os !== 'darwin'">
<i class="el-icon-minus" @click="minimizeWindow"></i>
<i class="el-icon-circle-plus-outline" @click="openMiniWindow"></i>
<i class="el-icon-close" @click="closeWindow"></i>
</div>
</div>
<el-row style="padding-top: 22px;">
<el-col :span="5">
<el-row style="padding-top: 22px;" class="main-content">
<el-col :span="5" class="side-bar-menu">
<el-menu
class="picgo-sidebar"
:default-active="defaultActive"
@select="handleSelect"
:unique-opened="true"
>
<el-menu-item index="upload">
<i class="el-icon-upload"></i>
@@ -18,29 +24,37 @@
<i class="el-icon-picture"></i>
<span slot="title">相册</span>
</el-menu-item>
<el-menu-item index="weibo">
<i class="el-icon-ui-weibo"></i>
<span slot="title">微博设置</span>
<el-submenu
index="sub-menu"
>
<template slot="title">
<i class="el-icon-menu"></i>
<span>图床设置</span>
</template>
<template
v-for="item in picBed"
>
<el-menu-item
v-if="item.visible"
:index="item.type"
:key="item.type"
>
<!-- <i :class="`el-icon-ui-${item.type}`"></i> -->
<span slot="title">{{ item.name }}</span>
</el-menu-item>
</template>
</el-submenu>
<el-menu-item index="setting">
<i class="el-icon-setting"></i>
<span slot="title">PicGo设置</span>
</el-menu-item>
<el-menu-item index="qiniu">
<i class="el-icon-ui-qiniu"></i>
<span slot="title">七牛云设置</span>
</el-menu-item>
<el-menu-item index="tcyun">
<i class="el-icon-ui-tcyun"></i>
<span slot="title">腾讯COS设置</span>
</el-menu-item>
<el-menu-item index="upyun">
<i class="el-icon-ui-upyun"></i>
<span slot="title">又拍云设置</span>
</el-menu-item>
<i class="el-icon-setting" @click="openDialog"></i>
</el-menu>
<i class="el-icon-info setting-window" @click="openDialog"></i>
</el-col>
<el-col :span="19" :offset="5">
<el-col :span="19" :offset="5" style="height: 428px">
<router-view></router-view>
</el-col>
</el-row>
</el-row>
<el-dialog
title="赞助PicGo"
:visible.sync="visible"
@@ -59,23 +73,100 @@
</el-col>
</el-row>
</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>
import pkg from '../../../package.json'
import keyDetect from 'utils/key-binding'
import { remote } from 'electron'
const { Menu, dialog } = remote
import db from '../../datastore'
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
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()
},
picBed: this.$picBed
}
},
created () {
this.os = process.platform
this.buildMenu()
},
methods: {
@@ -84,6 +175,14 @@ export default {
name: index
})
},
minimizeWindow () {
const window = BrowserWindow.getFocusedWindow()
window.minimize()
},
closeWindow () {
const window = BrowserWindow.getFocusedWindow()
window.close()
},
buildMenu () {
const _this = this
const template = [
@@ -107,7 +206,38 @@ export default {
this.menu = Menu.buildFromTemplate(template)
},
openDialog () {
this.menu.popup(remote.getCurrentWindow)
this.menu.popup(remote.getCurrentWindow())
},
keyDetect (type, event) {
this.shortKey[type] = keyDetect(event).join('+')
},
cancelKeyBinding () {
this.keyBindingVisible = false
this.shortKey = db.read().get('shortKey').value()
},
confirmKeyBinding () {
const oldKey = db.read().get('shortKey').value()
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
}
})
},
openMiniWindow () {
this.$electron.ipcRenderer.send('openMiniWindow')
}
},
beforeRouteEnter: (to, from, next) => {
@@ -128,14 +258,34 @@ export default {
font-size 12px
line-height h
position fixed
.picgo-sidebar
height calc(100vh - 22px)
.el-menu
border-right none
background transparent
position fixed
.el-icon-setting
z-index 100
.handle-bar
position absolute
top 2px
right 4px
width 60px
z-index 10000
-webkit-app-region no-drag
i
cursor pointer
font-size 16px
.el-icon-minus
&:hover
color #409EFF
.el-icon-close
&:hover
color #F15140
.el-icon-circle-plus-outline
&:hover
color #69C282
.side-bar-menu
position fixed
height calc(100vh - 22px)
overflow-x hidden
overflow-y auto
width 170px
.el-icon-info.setting-window
position fixed
bottom 4px
left 4px
cursor pointer
@@ -143,6 +293,10 @@ export default {
transition .2s all ease-in-out
&:hover
color #409EFF
.el-menu
border-right none
background transparent
width 170px
&-item
color #eee
position relative
@@ -160,9 +314,39 @@ export default {
right 0
top 18px
background active-color
.el-submenu__title
span
color #eee
&:hover
background transparent
span
color #fff
.el-submenu
.el-menu-item
min-width 166px
&.is-active
&:before
top 16px
.main-content
padding-top 22px
position relative
z-index 10
.el-dialog__body
padding 20px
.support
text-align center
&-title
text-align center
color #878d99
.align-center
input
text-align center
*::-webkit-scrollbar
width 8px
height 8px
*::-webkit-scrollbar-thumb
border-radius 4px
background #6f6f6f
*::-webkit-scrollbar-track
background-color transparent
</style>
@@ -0,0 +1,154 @@
<template>
<div id="aliyun-view">
<el-row :gutter="16">
<el-col :span="16" :offset="4">
<div class="view-title">
阿里云OSS设置
</div>
<el-form
ref="aliyun"
label-position="right"
label-width="120px"
:model="form"
size="mini">
<el-form-item
label="设定KeyId"
prop="accessKeyId"
:rules="{
required: true, message: 'AccessKeyId不能为空', trigger: 'blur'
}">
<el-input v-model="form.accessKeyId" placeholder="AccessKeyId" @keyup.native.enter="confirm"></el-input>
</el-form-item>
<el-form-item
label="设定KeySecret"
prop="accessKeySecret"
:rules="{
required: true, message: 'AccessKeySecret不能为空', trigger: 'blur'
}">
<el-input v-model="form.accessKeySecret" type="password" @keyup.native.enter="confirm" placeholder="AccessKeySecret"></el-input>
</el-form-item>
<el-form-item
label="设定存储空间名"
prop="bucket"
:rules="{
required: true, message: 'Bucket不能为空', trigger: 'blur'
}">
<el-input v-model="form.bucket" @keyup.native.enter="confirm" placeholder="Bucket"></el-input>
</el-form-item>
<el-form-item
label="确认存储区域"
prop="area"
:rules="{
required: true, message: '区域代码不能为空', trigger: 'blur'
}">
<el-input v-model="form.area" @keyup.native.enter="confirm" placeholder="例如oss-cn-beijing"></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
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>
<el-button type="success" @click="setDefaultPicBed('aliyun')" round :disabled="defaultPicBed === 'aliyun'">设为默认图床</el-button>
</el-button-group>
</el-form-item>
</el-form>
</el-col>
</el-row>
</div>
</template>
<script>
import mixin from '../mixin'
export default {
name: 'aliyun',
mixins: [mixin],
data () {
return {
form: {
accessKeyId: '',
accessKeySecret: '',
bucket: '',
area: '',
path: '',
customUrl: ''
}
}
},
created () {
const config = this.$db.get('picBed.aliyun').value()
if (config) {
for (let i in config) {
this.form[i] = config[i]
}
}
},
methods: {
confirm () {
this.$refs.aliyun.validate((valid) => {
if (valid) {
this.$db.set('picBed.aliyun', this.form).write()
const successNotification = new window.Notification('设置结果', {
body: '设置成功'
})
successNotification.onclick = () => {
return true
}
} else {
return false
}
})
}
}
}
</script>
<style lang='stylus'>
.view-title
color #eee
font-size 20px
text-align center
margin 20px auto
#aliyun-view
.el-form
label
line-height 22px
padding-bottom 0
color #eee
.el-input__inner
border-radius 19px
&-item
margin-bottom 10.5px
.el-radio-group
width 100%
label
width 25%
.el-radio-button__inner
width 100%
.el-radio-button:first-child
.el-radio-button__inner
border-left none
border-radius 14px 0 0 14px
.el-radio-button:last-child
.el-radio-button__inner
border-left none
border-radius 0 14px 14px 0
.el-switch__label
color #eee
&.is-active
color #409EFF
.el-icon-question
font-size 20px
float right
margin-top 9px
color #eee
cursor pointer
transition .2s color ease-in-out
&:hover
color #409EFF
</style>
+234 -9
View File
@@ -1,9 +1,39 @@
<template>
<div id="gallery-view">
<div class="view-title">
相册
相册 - {{ filterList.length }} <i class="el-icon-caret-bottom" @click="toggleHandleBar" :class="{'active': handleBarActive}"></i>
</div>
<el-row class="gallery-list">
<transition name="el-zoom-in-center">
<el-row v-show="handleBarActive">
<el-col :span="20" :offset="2" :class="{ 'long-list': filterList.length > 4 }">
<el-row class="handle-bar" :gutter="16">
<el-col :span="6" v-for="item in $picBed" :key="item.type">
<div class="pic-bed-item" @click="choosePicBed(item.type)" :class="{active: choosedPicBed.indexOf(item.type) !== -1}">
{{ item.name }}
</div>
</el-col>
</el-row>
<el-row class="handle-bar" :gutter="16">
<el-col :span="12">
<el-input placeholder="搜索" size="mini" v-model="searchText">
<i slot="suffix" class="el-input__icon el-icon-close" v-if="searchText" @click="cleanSearch" style="cursor: pointer"></i>
</el-input>
</el-col>
<el-col :span="6">
<div class="item-base copy" :class="{ active: isMultiple(choosedList)}" @click="multiCopy">
<i class="el-icon-document"></i> 批量复制
</div>
</el-col>
<el-col :span="6">
<div class="item-base delete" :class="{ active: isMultiple(choosedList)}" @click="multiDelete">
<i class="el-icon-delete"></i> 批量删除
</div>
</el-col>
</el-row>
</el-col>
</el-row>
</transition>
<el-row class="gallery-list" :class="{ small: handleBarActive }">
<el-col :span="20" :offset="2">
<el-row :gutter="16">
<gallerys
@@ -12,21 +42,35 @@
@close="handleClose"
:options="options"
></gallerys>
<el-col :span="6" v-for="(item, index) in images" :key="item.id">
<el-col :span="6" v-for="(item, index) in images" :key="item.id" class="gallery-list__img">
<div
class="gallery-list__item"
:style="{ 'background-image': `url(${item.imgUrl})` }"
v-lazy:background-image="item.imgUrl"
@click="zoomImage(index)"
>
</div>
<div class="gallery-list__tool-panel">
<i class="el-icon-document" @click="copy(item.imgUrl)"></i>
<i class="el-icon-edit-outline" @click="openDialog(item)"></i>
<i class="el-icon-delete" @click="remove(item.id)"></i>
<el-checkbox v-model="choosedList[item.id]" class="pull-right" @change=" handleBarActive = true"></el-checkbox>
</div>
</el-col>
</el-row>
</el-col>
</el-row>
<el-dialog
:visible.sync="dialogVisible"
title="修改图片URL"
width="500px"
:modal-append-to-body="false"
>
<el-input v-model="imgInfo.imgUrl"></el-input>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="confirmModify"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
@@ -45,15 +89,54 @@ export default {
titleProperty: 'fileName',
urlProperty: 'imgUrl',
closeOnSlideClick: true
}
},
dialogVisible: false,
imgInfo: {
id: null,
imgUrl: ''
},
choosedList: {},
choosedPicBed: [],
searchText: '',
handleBarActive: false
}
},
created () {
this.getGallery()
},
computed: {
filterList (val) {
return this.getGallery()
}
},
methods: {
getGallery () {
this.images = this.$db.read().get('uploaded').slice().reverse().value()
if (this.choosedPicBed.length > 0) {
let arr = []
this.choosedPicBed.forEach(item => {
let obj = {
type: item
}
if (this.searchText) {
obj.fileName = this.searchText
}
arr = arr.concat(this.$db.read().get('uploaded').filter(obj => {
return obj.fileName.indexOf(this.searchText) !== -1 && obj.type === item
}).reverse().value())
})
this.images = arr
} else {
if (this.searchText) {
let data = this.$db.read().get('uploaded')
.filter(item => {
return item.fileName.indexOf(this.searchText) !== -1
}).reverse().value()
this.images = data
} else {
this.images = this.$db.read().get('uploaded').slice().reverse().value()
}
}
return this.images
},
zoomImage (index) {
this.idx = index
@@ -62,7 +145,7 @@ export default {
this.idx = null
},
copy (url) {
const style = this.$db.read().get('picBed.pasteStyle').value()
const style = this.$db.read().get('picBed.pasteStyle').value() || 'markdown'
const copyLink = pasteStyle(style, url)
const obj = {
title: '复制链接成功',
@@ -94,6 +177,92 @@ export default {
}).catch(() => {
return true
})
},
openDialog (item) {
this.imgInfo.id = item.id
this.imgInfo.imgUrl = item.imgUrl
this.dialogVisible = true
},
confirmModify () {
this.$db.read().get('uploaded')
.getById(this.imgInfo.id)
.assign({imgUrl: this.imgInfo.imgUrl})
.write()
const obj = {
title: '修改图片URL成功',
body: this.imgInfo.imgUrl,
icon: this.imgInfo.imgUrl
}
const myNotification = new window.Notification(obj.title, obj)
myNotification.onclick = () => {
return true
}
this.dialogVisible = false
this.getGallery()
},
choosePicBed (type) {
let idx = this.choosedPicBed.indexOf(type)
if (idx !== -1) {
this.choosedPicBed.splice(idx, 1)
} else {
this.choosedPicBed.push(type)
}
},
cleanSearch () {
this.searchText = ''
},
isMultiple (obj) {
return Object.values(obj).some(item => item)
},
multiDelete () {
if (Object.values(this.choosedList).some(item => item)) {
this.$confirm('将删除刚才选中的图片,是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
Object.keys(this.choosedList).forEach(key => {
if (this.choosedList[key]) {
this.$db.read().get('uploaded').removeById(key).write()
}
})
this.choosedList = {}
this.getGallery()
const obj = {
title: '操作结果',
body: '删除成功'
}
const myNotification = new window.Notification(obj.title, obj)
myNotification.onclick = () => {
return true
}
}).catch(() => {
return true
})
}
},
multiCopy () {
if (Object.values(this.choosedList).some(item => item)) {
let copyString = ''
const style = this.$db.read().get('picBed.pasteStyle').value() || 'markdown'
Object.keys(this.choosedList).forEach(key => {
if (this.choosedList[key]) {
copyString += pasteStyle(style, this.$db.read().get('uploaded').getById(key).value().imgUrl) + '\n'
}
})
const obj = {
title: '批量复制链接成功',
body: copyString
}
const myNotification = new window.Notification(obj.title, obj)
this.$electron.clipboard.writeText(copyString)
myNotification.onclick = () => {
return true
}
}
},
toggleHandleBar () {
this.handleBarActive = !this.handleBarActive
}
}
}
@@ -103,15 +272,56 @@ export default {
color #eee
font-size 20px
text-align center
margin 20px auto
margin 10px auto
.sub-title
font-size 14px
.el-icon-caret-bottom
cursor: pointer
transition all .2s ease-in-out
&.active
transform: rotate(180deg)
.item-base
background #2E2E2E
text-align center
margin-bottom 10px
padding 5px 0
cursor pointer
font-size 13px
transition all .2s ease-in-out
&.copy
cursor not-allowed
background #49B1F5
&.active
cursor pointer
background #1B9EF3
color #fff
&.delete
cursor not-allowed
background #F47466
&.active
cursor pointer
background #F15140
color #fff
.long-list
width: calc(83.3333333% - 6px)
#gallery-view
position relative
.pull-right
float right
.gallery-list
height 360px
box-sizing border-box
padding 8px 0
overflow-y auto
overflow-x hidden
.el-col
position absolute
top: 38px
transition all .2s ease-in-out .1s
width 100%
&.small
height: 245px
top: 152px
&__img
height 150px
position relative
margin-bottom 16px
@@ -142,10 +352,25 @@ export default {
&.el-icon-document
&:hover
color #49B1F5
&.el-icon-edit-outline
&:hover
color #69C282
&.el-icon-delete
&:hover
color #F15140
.blueimp-gallery
.title
top 30px
.handle-bar
color #ddd
.pic-bed-item
@extend .item-base
&:hover
background #A4D8FA
color #fff
&.active
background #49B1F5
color #fff
.el-input__inner
border-radius 0
</style>
@@ -0,0 +1,130 @@
<template>
<div id="github-view">
<el-row :gutter="16">
<el-col :span="16" :offset="4">
<div class="view-title">
GitHub设置
</div>
<el-form
ref="github"
label-position="right"
label-width="120px"
:model="form"
size="mini">
<el-form-item
label="设定仓库名"
prop="repo"
:rules="{
required: true, message: '仓库名不能为空', trigger: 'blur'
}">
<el-input v-model="form.repo" @keyup.native.enter="confirm" placeholder="格式:username/repo"></el-input>
</el-form-item>
<el-form-item
label="设定分支名"
prop="branch"
:rules="{
required: true, message: '分支名不能为空', trigger: 'blur'
}">
<el-input v-model="form.branch" @keyup.native.enter="confirm" placeholder="例如:master"></el-input>
</el-form-item>
<el-form-item
label="设定Token"
prop="token"
:rules="{
required: true, message: 'Token不能为空', trigger: 'blur'
}">
<el-input v-model="form.token" @keyup.native.enter="confirm" placeholder="token"></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
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>
<el-button type="success" @click="setDefaultPicBed('github')" round :disabled="defaultPicBed === 'github'">设为默认图床</el-button>
</el-button-group>
</el-form-item>
</el-form>
</el-col>
</el-row>
</div>
</template>
<script>
import mixin from '../mixin'
export default {
name: 'upyun',
mixins: [mixin],
data () {
return {
form: {
repo: '',
token: '',
path: '',
customUrl: '',
branch: ''
}
}
},
created () {
const config = this.$db.get('picBed.github').value()
if (config) {
for (let i in config) {
this.form[i] = config[i]
}
}
},
methods: {
confirm () {
this.$refs.github.validate((valid) => {
if (valid) {
this.$db.set('picBed.github', this.form).write()
const successNotification = new window.Notification('设置结果', {
body: '设置成功'
})
successNotification.onclick = () => {
return true
}
} else {
return false
}
})
}
}
}
</script>
<style lang='stylus'>
.view-title
color #eee
font-size 20px
text-align center
margin 20px auto
#github-view
.el-form
label
line-height 22px
padding-bottom 0
color #eee
.el-input__inner
border-radius 19px
.el-radio-group
width 100%
label
width 25%
.el-radio-button__inner
width 100%
.el-radio-button:first-child
.el-radio-button__inner
border-left none
border-radius 14px 0 0 14px
.el-radio-button:last-child
.el-radio-button__inner
border-left none
border-radius 0 14px 14px 0
</style>
@@ -0,0 +1,122 @@
<template>
<div id="imgur-view">
<el-row :gutter="16">
<el-col :span="16" :offset="4">
<div class="view-title">
Imgur图床设置
</div>
<el-form
ref="imgur"
label-position="right"
label-width="120px"
:model="form"
size="mini">
<el-form-item
label="设定ClientId"
prop="clientId"
:rules="{
required: true, message: 'ClientId不能为空', trigger: 'blur'
}">
<el-input v-model="form.clientId" placeholder="ClientId" @keyup.native.enter="confirm"></el-input>
</el-form-item>
<el-form-item
label="设定代理"
prop="proxy"
>
<el-input v-model="form.proxy" placeholder="例如:http://127.0.0.1:1080" @keyup.native.enter="confirm"></el-input>
</el-form-item>
<el-form-item>
<el-button-group>
<el-button type="primary" @click="confirm" round>确定</el-button>
<el-button type="success" @click="setDefaultPicBed('imgur')" round :disabled="defaultPicBed === 'imgur'">设为默认图床</el-button>
</el-button-group>
</el-form-item>
</el-form>
</el-col>
</el-row>
</div>
</template>
<script>
import mixin from '../mixin'
export default {
name: 'imgur',
mixins: [mixin],
data () {
return {
form: {
clientId: '',
proxy: ''
}
}
},
created () {
const config = this.$db.get('picBed.imgur').value()
if (config) {
for (let i in config) {
this.form[i] = config[i]
}
}
},
methods: {
confirm () {
this.$refs.imgur.validate((valid) => {
if (valid) {
this.$db.set('picBed.imgur', this.form).write()
const successNotification = new window.Notification('设置结果', {
body: '设置成功'
})
successNotification.onclick = () => {
return true
}
} else {
return false
}
})
}
}
}
</script>
<style lang='stylus'>
.view-title
color #eee
font-size 20px
text-align center
margin 20px auto
#imgur-view
.el-form
label
line-height 22px
padding-bottom 0
color #eee
.el-input__inner
border-radius 19px
&-item
margin-bottom 10.5px
.el-radio-group
width 100%
label
width 25%
.el-radio-button__inner
width 100%
.el-radio-button:first-child
.el-radio-button__inner
border-left none
border-radius 14px 0 0 14px
.el-radio-button:last-child
.el-radio-button__inner
border-left none
border-radius 0 14px 14px 0
.el-switch__label
color #eee
&.is-active
color #409EFF
.el-icon-question
font-size 20px
float right
margin-top 9px
color #eee
cursor pointer
transition .2s color ease-in-out
&:hover
color #409EFF
</style>
@@ -0,0 +1,378 @@
<template>
<div id="picgo-setting">
<div class="view-title">
PicGo设置
</div>
<el-row class="setting-list">
<el-col :span="15" :offset="4">
<el-row>
<el-form
label-width="120px"
label-position="right"
size="small"
>
<el-form-item
label="修改快捷键"
>
<el-button type="primary" round size="mini" @click="keyBindingVisible = true">点击设置</el-button>
</el-form-item>
<el-form-item
label="自定义链接格式"
>
<el-button type="primary" round size="mini" @click="customLinkVisible = true">点击设置</el-button>
</el-form-item>
<el-form-item
label="检查更新"
>
<el-button type="primary" round size="mini" @click="checkUpdate">点击设置</el-button>
</el-form-item>
<el-form-item
label="打开更新助手"
>
<el-switch
v-model="form.updateHelper"
active-text=""
inactive-text=""
@change="updateHelperChange"
></el-switch>
</el-form-item>
<el-form-item
label="开机自启"
>
<el-switch
v-model="form.autoStart"
active-text=""
inactive-text=""
@change="handleAutoStartChange"
></el-switch>
</el-form-item>
<el-form-item
label="上传前重命名"
>
<el-switch
v-model="form.rename"
active-text=""
inactive-text=""
@change="handleRename"
></el-switch>
</el-form-item>
<el-form-item
label="时间戳重命名"
>
<el-switch
v-model="form.autoRename"
active-text=""
inactive-text=""
@change="handleAutoRename"
></el-switch>
</el-form-item>
<el-form-item
label="开启上传提示"
>
<el-switch
v-model="form.uploadNotification"
active-text=""
inactive-text=""
@change="handleUploadNotification"
></el-switch>
</el-form-item>
<el-form-item
label="选择显示的图床"
>
<el-checkbox-group
v-model="form.showPicBedList"
@change="handleShowPicBedListChange"
>
<el-checkbox
v-for="item in picBed"
:label="item.name"
:key="item.name"
></el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-form>
</el-row>
</el-col>
</el-row>
<el-dialog
title="修改快捷键"
:visible.sync="keyBindingVisible"
:modal-append-to-body="false"
>
<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"
:modal-append-to-body="false"
>
<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>
<el-dialog
title="检查更新"
:visible.sync="checkUpdateVisible"
:modal-append-to-body="false"
>
<div>
当前版本{{ version }}
</div>
<div>
最新版本{{ latestVersion ? latestVersion : '正在获取中...' }}
</div>
<div v-if="needUpdate">
PicGo更新啦请点击确定打开下载页面
</div>
<span slot="footer">
<el-button @click="cancelCheckVersion">取消</el-button>
<el-button type="primary" @click="confirmCheckVersion">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import db from '../../../datastore'
import keyDetect from 'utils/key-binding'
import pkg from '../../../../package.json'
const release = 'https://api.github.com/repos/Molunerfinn/PicGo/releases/latest'
const downloadUrl = 'https://github.com/Molunerfinn/PicGo/releases/latest'
export default {
name: 'picgo-setting',
computed: {
needUpdate () {
if (this.latestVersion) {
return this.compareVersion2Update(this.version, this.latestVersion)
} else {
return false
}
}
},
data () {
const customLinkRule = (rule, value, callback) => {
if (!/\$url/.test(value)) {
return callback(new Error('必须含有$url'))
} else {
return callback()
}
}
return {
form: {
updateHelper: this.$db.get('picBed.showUpdateTip').value(),
showPicBedList: [],
autoStart: this.$db.get('picBed.autoStart').value() || false,
rename: this.$db.get('picBed.rename').value() || false,
autoRename: this.$db.get('picBed.autoRename').value() || false,
uploadNotification: this.$db.get('picBed.uploadNotification').value() || false
},
picBed: this.$picBed,
keyBindingVisible: false,
customLinkVisible: false,
checkUpdateVisible: false,
customLink: {
value: db.read().get('customLink').value() || '$url'
},
shortKey: {
upload: db.read().get('shortKey.upload').value()
},
rules: {
value: [
{ validator: customLinkRule, trigger: 'blur' }
]
},
version: pkg.version,
latestVersion: ''
}
},
created () {
this.form.showPicBedList = this.picBed.map(item => {
if (item.visible) {
return item.name
}
})
},
methods: {
keyDetect (type, event) {
this.shortKey[type] = keyDetect(event).join('+')
},
cancelKeyBinding () {
this.keyBindingVisible = false
this.shortKey = db.read().get('shortKey').value()
},
confirmKeyBinding () {
const oldKey = db.read().get('shortKey').value()
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
}
})
},
updateHelperChange (val) {
this.$db.read().set('picBed.showUpdateTip', val).write()
},
handleShowPicBedListChange (val) {
const list = this.picBed.map(item => {
if (!val.includes(item.name)) {
item.visible = false
} else {
item.visible = true
}
return item
})
this.$db.read().set('picBed.list', list).write()
},
handleAutoStartChange (val) {
this.$db.read().set('picBed.autoStart', val).write()
this.$electron.ipcRenderer.send('autoStart', val)
},
handleRename (val) {
this.$db.read().set('picBed.rename', val).write()
},
handleAutoRename (val) {
this.$db.read().set('picBed.autoRename', val).write()
},
compareVersion2Update (current, latest) {
const currentVersion = current.split('.').map(item => parseInt(item))
const latestVersion = latest.split('.').map(item => parseInt(item))
for (let i = 0; i < 3; i++) {
if (currentVersion[i] < latestVersion[i]) {
return true
}
if (currentVersion[i] > latestVersion[i]) {
return false
}
}
return false
},
checkUpdate () {
this.checkUpdateVisible = true
this.$http.get(release)
.then(res => {
this.latestVersion = res.data.name
}).catch(err => {
console.log(err)
})
},
confirmCheckVersion () {
if (this.needUpdate) {
this.$electron.remote.shell.openExternal(downloadUrl)
}
this.checkUpdateVisible = false
},
cancelCheckVersion () {
this.checkUpdateVisible = false
},
handleUploadNotification (val) {
this.$db.read().set('picBed.uploadNotification', val).write()
}
},
beforeDestroy () {
this.$electron.ipcRenderer.removeAllListeners('autoStart')
}
}
</script>
<style lang='stylus'>
.el-message
left 60%
.view-title
color #eee
font-size 20px
text-align center
margin 20px auto
#picgo-setting
.sub-title
font-size 14px
.setting-list
height 360px
box-sizing border-box
overflow-y auto
overflow-x hidden
.setting-list
.el-form
label
line-height 32px
padding-bottom 0
color #eee
.el-button-group
width 100%
.el-button
width 50%
.el-input__inner
border-radius 19px
.el-radio-group
margin-left 25px
.el-switch__label
color #eee
&.is-active
color #409EFF
.el-icon-question
font-size 20px
float right
margin-top 9px
color #eee
cursor pointer
transition .2s color ease-in-out
&:hover
color #409EFF
.el-checkbox-group
label
margin-right 30px
width 100px
.el-checkbox+.el-checkbox
margin-right 30px
margin-left 0
.confirm-button
width 100%
</style>
+13 -5
View File
@@ -58,8 +58,16 @@
>
<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 type="primary" @click="confirm">确定</el-button>
<el-button-group>
<el-button type="primary" @click="confirm" round>确定</el-button>
<el-button type="success" @click="setDefaultPicBed('qiniu')" round :disabled="defaultPicBed === 'qiniu'">设为默认图床</el-button>
</el-button-group>
</el-form-item>
</el-form>
</el-col>
@@ -79,7 +87,8 @@ export default {
bucket: '',
url: '',
area: 'z0',
options: ''
options: '',
path: ''
}
}
},
@@ -122,11 +131,10 @@ export default {
line-height 22px
padding-bottom 0
color #eee
.el-button
width 100%
border-radius 19px
.el-input__inner
border-radius 19px
&-item
margin-bottom 10.5px
.el-radio-group
width 100%
label
@@ -0,0 +1,51 @@
<template>
<div id="smms-view">
<el-row :gutter="16">
<el-col :span="16" :offset="4">
<div class="view-title">
SM.MS设置
</div>
<div class="content">
感谢SM.MS提供的优质服务
</div>
<div style="text-align: center; margin-top: 20px;">
<el-button type="success" @click="confirm" round :disabled="defaultPicBed === 'smms'" size="mini">设为默认图床</el-button>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import mixin from '../mixin'
export default {
name: 'upyun',
mixins: [mixin],
data () {
return {}
},
methods: {
confirm () {
this.$db.set('picBed.smms', true).write()
this.setDefaultPicBed('smms')
const successNotification = new window.Notification('设置结果', {
body: '设置成功'
})
successNotification.onclick = () => {
return true
}
}
}
}
</script>
<style lang='stylus'>
.view-title
color #eee
font-size 20px
text-align center
margin 20px auto
#smms-view
.content
text-align center
font-size 14px
color #eee
</style>
+43 -5
View File
@@ -11,6 +11,19 @@
label-width="120px"
:model="form"
size="mini">
<el-form-item
label="COS版本"
>
<el-switch
v-model="form.version"
active-text="v4"
inactive-text="v5"
active-value="v4"
inactive-value="v5"
inactive-color="#67C23A"
></el-switch>
<i class="el-icon-question" @click="openWiki"></i>
</el-form-item>
<el-form-item
label="设定SecretId"
prop="secretId"
@@ -56,8 +69,16 @@
>
<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 type="primary" @click="confirm">确定</el-button>
<el-button-group>
<el-button type="primary" @click="confirm" round>确定</el-button>
<el-button type="success" @click="setDefaultPicBed('tcyun')" round :disabled="defaultPicBed === 'tcyun'">设为默认图床</el-button>
</el-button-group>
</el-form-item>
</el-form>
</el-col>
@@ -77,7 +98,9 @@ export default {
bucket: '',
appId: '',
area: '',
path: ''
path: '',
customUrl: '',
version: 'v4'
}
}
},
@@ -104,6 +127,9 @@ export default {
return false
}
})
},
openWiki () {
this.$electron.remote.shell.openExternal('https://github.com/Molunerfinn/PicGo/wiki/%E8%AF%A6%E7%BB%86%E7%AA%97%E5%8F%A3%E7%9A%84%E4%BD%BF%E7%94%A8#%E5%BE%AE%E5%8D%9A%E5%9B%BE%E5%BA%8A')
}
}
}
@@ -120,11 +146,10 @@ export default {
line-height 22px
padding-bottom 0
color #eee
.el-button
width 100%
border-radius 19px
.el-input__inner
border-radius 19px
&-item
margin-bottom 10.5px
.el-radio-group
width 100%
label
@@ -139,4 +164,17 @@ export default {
.el-radio-button__inner
border-left none
border-radius 0 14px 14px 0
.el-switch__label
color #eee
&.is-active
color #409EFF
.el-icon-question
font-size 20px
float right
margin-top 9px
color #eee
cursor pointer
transition .2s color ease-in-out
&:hover
color #409EFF
</style>
+11 -5
View File
@@ -48,8 +48,16 @@
>
<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 type="primary" @click="confirm">确定</el-button>
<el-button-group>
<el-button type="primary" @click="confirm" round>确定</el-button>
<el-button type="success" @click="setDefaultPicBed('upyun')" round :disabled="defaultPicBed === 'upyun'">设为默认图床</el-button>
</el-button-group>
</el-form-item>
</el-form>
</el-col>
@@ -67,7 +75,8 @@ export default {
bucket: '',
operator: '',
password: '',
options: ''
options: '',
path: ''
}
}
},
@@ -110,9 +119,6 @@ export default {
line-height 22px
padding-bottom 0
color #eee
.el-button
width 100%
border-radius 19px
.el-input__inner
border-radius 19px
.el-radio-group
+47 -16
View File
@@ -1,9 +1,9 @@
<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">
图片上传
图片上传 - {{ picBed }}
</div>
<div
id="upload-area"
@@ -25,19 +25,28 @@
:status="showError ? 'exception' : ''"
></el-progress>
<div class="paste-style">
<div class="paste-style__text">
链接格式
<div class="el-col-16">
<div class="paste-style__text">
链接格式
</div>
<el-radio-group v-model="pasteStyle" size="mini"
@change="handlePasteStyleChange"
>
<el-radio-button label="markdown">
Markdown
</el-radio-button>
<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">
<div class="paste-style__text">
快捷上传
</div>
<el-button type="primary" round size="mini" @click="uploadClipboardFiles" class="paste-upload">剪贴板图片上传</el-button>
</div>
<el-radio-group v-model="pasteStyle" size="mini"
@change="handlePasteStyleChange"
>
<el-radio-button label="markdown">
Markdown
</el-radio-button>
<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-group>
</div>
</el-col>
</el-row>
@@ -54,7 +63,8 @@ export default {
progress: 0,
showProgress: false,
showError: false,
pasteStyle: ''
pasteStyle: '',
picBed: ''
}
},
mounted () {
@@ -68,6 +78,10 @@ export default {
}
})
this.getPasteStyle()
this.getDefaultPicBed()
this.$electron.ipcRenderer.on('syncPicBed', () => {
this.getDefaultPicBed()
})
},
watch: {
progress (val) {
@@ -84,6 +98,7 @@ export default {
},
beforeDestroy () {
this.$electron.ipcRenderer.removeAllListeners('uploadProgress')
this.$electron.ipcRenderer.removeAllListeners('syncPicBed')
},
methods: {
onDrop (e) {
@@ -114,6 +129,17 @@ export default {
handlePasteStyleChange (val) {
this.$db.read().set('picBed.pasteStyle', val)
.write()
},
uploadClipboardFiles () {
this.$electron.ipcRenderer.send('uploadClipboardFilesFromUploadPage')
},
getDefaultPicBed () {
const current = this.$db.read().get('picBed.current').value()
this.$picBed.forEach(item => {
if (item.type === current) {
this.picBed = item.name
}
})
}
}
}
@@ -130,6 +156,8 @@ export default {
border 2px dashed #dddddd
border-radius 8px
text-align center
width 450px
margin 0 auto
color #dddddd
cursor pointer
transition all .2s ease-in-out
@@ -149,9 +177,10 @@ export default {
#file-uploader
display none
.upload-progress
margin-top 20px
opacity 0
transition all .2s ease-in-out
width 450px
margin 20px auto 0
&.show
opacity 1
.el-progress-bar__inner
@@ -174,4 +203,6 @@ export default {
.el-radio-button__inner
border-left none
border-radius 0 14px 14px 0
.paste-upload
width 100%
</style>
+58 -11
View File
@@ -1,30 +1,47 @@
<template>
<div id="weibo-view">
<el-row :gutter="16">
<el-col :span="12" :offset="6">
<el-col :span="16" :offset="4">
<div class="view-title">
微博图床设置
</div>
<el-form
ref="weiboForm"
label-position="top"
label-width="80px"
label-position="right"
label-width="120px"
size="small"
:model="form">
<el-form-item
label="设定用户名"
prop="username"
:rules="{
required: true, message: '用户名不能为空', trigger: 'blur'
required: !chooseCookie, message: '用户名不能为空', trigger: 'blur'
}">
<el-input v-model="form.username" placeholder="用户名" @keyup.native.enter="confirm('weiboForm')"></el-input>
<el-input v-model="form.username" placeholder="用户名" @keyup.native.enter="confirm('weiboForm')" :disabled="chooseCookie"></el-input>
</el-form-item>
<el-form-item
label="设定密码"
prop="password"
:rules="{required: !chooseCookie,messsage: '密码不能为空',trigger: 'blur'}">
<el-input v-model="form.password" type="password" @keyup.native.enter="confirm('weiboForm')" placeholder="密码" :disabled="chooseCookie"></el-input>
</el-form-item>
<el-form-item
label="使用Cookie上传"
>
<el-switch
v-model="chooseCookie"
active-text="cookie模式"
@change="handleSwitchChange"
></el-switch>
<i class="el-icon-question" @click="openWiki"></i>
</el-form-item>
<el-form-item
label="设定Cookie"
prop="cookie"
:rules="{
required: true, message: '密码不能为空', trigger: 'blur'
required: chooseCookie, message: '密码不能为空', trigger: 'blur'
}">
<el-input v-model="form.password" type="password" @keyup.native.enter="confirm('weiboForm')" placeholder="密码"></el-input>
<el-input v-model="form.cookie" @keyup.native.enter="confirm('weiboForm')" placeholder="Cookie" :disabled="!chooseCookie"></el-input>
</el-form-item>
<el-form-item label="* 图片质量">
<el-radio-group v-model="quality">
@@ -34,7 +51,10 @@
</el-radio-group>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="confirm('weiboForm')" round>确定</el-button>
<el-button-group>
<el-button type="primary" @click="confirm('weiboForm')" round>确定</el-button>
<el-button type="success" @click="setDefaultPicBed('weibo')" round :disabled="defaultPicBed === 'weibo'">设为默认图床</el-button>
</el-button-group>
</el-form-item>
</el-form>
</el-col>
@@ -50,8 +70,10 @@ export default {
return {
form: {
username: '',
password: ''
password: '',
cookie: ''
},
chooseCookie: false,
quality: 'large'
}
},
@@ -61,6 +83,8 @@ export default {
this.form.username = config.username
this.form.password = config.password
this.quality = config.quality || 'large'
this.form.cookie = config.cookie
this.chooseCookie = config.chooseCookie
}
},
methods: {
@@ -70,7 +94,9 @@ export default {
this.$db.read().set('picBed.weibo', {
username: this.form.username,
password: this.form.password,
quality: this.quality
quality: this.quality,
cookie: this.form.cookie,
chooseCookie: this.chooseCookie
}).write()
const successNotification = new window.Notification('设置结果', {
body: '设置成功'
@@ -82,6 +108,12 @@ export default {
return false
}
})
},
handleSwitchChange () {
this.$refs['weiboForm'].resetFields()
},
openWiki () {
this.$electron.remote.shell.openExternal('https://github.com/Molunerfinn/PicGo/wiki/%E8%AF%A6%E7%BB%86%E7%AA%97%E5%8F%A3%E7%9A%84%E4%BD%BF%E7%94%A8#%E5%BE%AE%E5%8D%9A%E5%9B%BE%E5%BA%8A')
}
}
}
@@ -100,10 +132,25 @@ export default {
line-height 22px
padding-bottom 0
color #eee
.el-button
.el-button-group
width 100%
.el-button
width 50%
.el-input__inner
border-radius 19px
.el-radio-group
margin-left 25px
.el-switch__label
color #eee
&.is-active
color #409EFF
.el-icon-question
font-size 20px
float right
margin-top 9px
color #eee
cursor pointer
transition .2s color ease-in-out
&:hover
color #409EFF
</style>
+1 -1
View File
@@ -78,7 +78,7 @@
this.notification.body = item.imgUrl
this.notification.icon = item.imgUrl
const myNotification = new window.Notification(this.notification.title, this.notification)
const pasteStyle = this.$db.read().get('picBed.pasteStyle').value()
const pasteStyle = this.$db.read().get('picBed.pasteStyle').value() || 'markdown'
this.$electron.clipboard.writeText(pasteTemplate(pasteStyle, item.imgUrl))
myNotification.onclick = () => {
return true
+17
View File
@@ -1,7 +1,13 @@
import db from '../../datastore'
export default {
mounted () {
this.disableDragEvent()
},
data () {
return {
defaultPicBed: db.read().get('picBed.current').value()
}
},
methods: {
disableDragEvent () {
window.addEventListener('dragenter', this.disableDrag, false)
@@ -15,6 +21,17 @@ export default {
e.dataTransfer.effectAllowed = 'none'
e.dataTransfer.dropEffect = 'none'
}
},
setDefaultPicBed (type) {
db.read().set('picBed.current', type).write()
this.defaultPicBed = type
this.$electron.ipcRenderer.send('updateDefaultPicBed', type)
const successNotification = new window.Notification('设置默认图床', {
body: '设置成功'
})
successNotification.onclick = () => {
return true
}
}
},
beforeDestroy () {
+5
View File
@@ -8,7 +8,11 @@ import store from './store'
import db from '../datastore/index'
import { webFrame } from 'electron'
import './assets/fonts/iconfont.css'
import picBed from '../datastore/pic-bed'
import VueLazyLoad from 'vue-lazyload'
Vue.use(ElementUI)
Vue.use(VueLazyLoad)
webFrame.setVisualZoomLevelLimits(1, 1)
webFrame.setLayoutZoomLevelLimits(0, 0)
@@ -16,6 +20,7 @@ webFrame.setLayoutZoomLevelLimits(0, 0)
if (!process.env.IS_WEB) Vue.use(require('vue-electron'))
Vue.http = Vue.prototype.$http = axios
Vue.prototype.$db = db
Vue.prototype.$picBed = picBed
Vue.config.productionTip = false
/* eslint-disable no-new */
+35
View File
@@ -10,6 +10,16 @@ export default new Router({
name: 'tray-page',
component: require('@/components/TrayPage').default
},
{
path: '/rename-page',
name: 'rename-page',
component: require('@/components/RenamePage').default
},
{
path: '/mini-page',
name: 'mini-page',
component: require('@/components/MiniPage').default
},
{
path: '/setting',
name: 'setting-page',
@@ -40,10 +50,35 @@ export default new Router({
component: require('@/components/SettingView/UpYun').default,
name: 'upyun'
},
{
path: 'github',
component: require('@/components/SettingView/GitHub').default,
name: 'github'
},
{
path: 'smms',
component: require('@/components/SettingView/SMMS').default,
name: 'smms'
},
{
path: 'aliyun',
component: require('@/components/SettingView/AliYun').default,
name: 'aliyun'
},
{
path: 'imgur',
component: require('@/components/SettingView/Imgur').default,
name: 'imgur'
},
{
path: 'gallery',
component: require('@/components/SettingView/Gallery').default,
name: 'gallery'
},
{
path: 'setting',
component: require('@/components/SettingView/PicGoSetting').default,
name: 'setting'
}
]
},
+38
View File
@@ -0,0 +1,38 @@
import keycode from 'keycode'
const isSpecialKey = (keyCode) => {
const keyArr = [
16, // Shift
17, // Ctrl
18, // Alt
91, // Left Meta
93 // Right Meta
]
return keyArr.includes(keyCode)
}
const keyDetect = (event) => {
const meta = process.platform === 'darwin' ? 'Cmd' : 'Super'
let specialKey = {
Ctrl: event.ctrlKey,
Shift: event.shiftKey,
Alt: event.altKey
}
specialKey[meta] = event.metaKey
let pressKey = []
for (let i in specialKey) {
if (specialKey[i]) {
pressKey.push(i)
}
}
if (!isSpecialKey(event.keyCode)) {
pressKey.push(keycode(event.keyCode).toUpperCase())
}
return pressKey
}
export default keyDetect
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 744 B

+124 -54
View File
@@ -88,7 +88,7 @@ acorn@^5.0.0, acorn@^5.2.1:
address@>=0.0.1:
version "1.0.3"
resolved "https://registry.yarnpkg.com/address/-/address-1.0.3.tgz#b5f50631f8d6cec8bd20c963963afb55e06cbce9"
resolved "http://registry.npm.taobao.org/address/download/address-1.0.3.tgz#b5f50631f8d6cec8bd20c963963afb55e06cbce9"
after@0.8.2:
version "0.8.2"
@@ -178,7 +178,7 @@ ansi-styles@^3.1.0:
any-promise@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
resolved "http://registry.npm.taobao.org/any-promise/download/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
anymatch@^1.3.0:
version "1.3.2"
@@ -348,8 +348,8 @@ async-exit-hook@^2.0.1:
resolved "https://registry.yarnpkg.com/async-exit-hook/-/async-exit-hook-2.0.1.tgz#8bd8b024b0ec9b1c01cccb9af9db29bd717dfaf3"
async-validator@~1.8.1:
version "1.8.1"
resolved "https://registry.yarnpkg.com/async-validator/-/async-validator-1.8.1.tgz#6665788ca39269af770e5ee02f0e557f2438d2ca"
version "1.8.2"
resolved "https://registry.yarnpkg.com/async-validator/-/async-validator-1.8.2.tgz#b77597226e96242f8d531c0d46ae295f62422ba4"
dependencies:
babel-runtime "6.x"
@@ -627,8 +627,8 @@ babel-helper-to-multiple-sequence-expressions@^0.2.0:
resolved "https://registry.yarnpkg.com/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.2.0.tgz#d1a419634c6cb301f27858c659167cfee0a9d318"
babel-helper-vue-jsx-merge-props@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.2.tgz#aceb1c373588279e2755ea1cfd35c22394fd33f8"
version "2.0.3"
resolved "https://registry.yarnpkg.com/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz#22aebd3b33902328e513293a8e4992b384f9f1b6"
babel-helpers@^6.24.1:
version "6.24.1"
@@ -1674,11 +1674,11 @@ builtin-modules@^1.0.0, builtin-modules@^1.1.1:
builtin-status-codes@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
resolved "http://registry.npm.taobao.org/builtin-status-codes/download/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
bytes@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
resolved "http://registry.npm.taobao.org/bytes/download/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
caller-path@^0.1.0:
version "0.1.0"
@@ -1968,7 +1968,7 @@ clone@^1.0.2:
co@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
resolved "http://registry.npm.taobao.org/co/download/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
coa@~1.0.1:
version "1.0.4"
@@ -2189,7 +2189,7 @@ content-disposition@0.5.2:
content-type@^1.0.2, content-type@~1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
resolved "http://registry.npm.taobao.org/content-type/download/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
convert-source-map@^1.5.0:
version "1.5.0"
@@ -2220,10 +2220,14 @@ copy-webpack-plugin@^4.0.1:
minimatch "^3.0.4"
node-dir "^0.1.10"
core-js@^2.2.0, core-js@^2.4.0, core-js@^2.5.0:
core-js@^2.2.0, core-js@^2.5.0:
version "2.5.1"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.1.tgz#ae6874dc66937789b80754ff5428df66819ca50b"
core-js@^2.4.0:
version "2.5.7"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e"
core-util-is@1.0.2, core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
@@ -2491,13 +2495,17 @@ dateformat@^1.0.6:
get-stdin "^4.0.1"
meow "^3.3.0"
dateformat@^3.0.3:
version "3.0.3"
resolved "http://registry.npm.taobao.org/dateformat/download/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
de-indent@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
debug@*, debug@^3.0.0, debug@^3.0.1, debug@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
resolved "http://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
dependencies:
ms "2.0.0"
@@ -2545,7 +2553,7 @@ deep-extend@~0.4.0:
deep-is@~0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
resolved "http://registry.npm.taobao.org/deep-is/download/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
deepmerge@^1.2.0:
version "1.5.2"
@@ -2557,7 +2565,7 @@ deepmerge@~2.0.1:
default-user-agent@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/default-user-agent/-/default-user-agent-1.0.0.tgz#16c46efdcaba3edc45f24f2bd4868b01b7c2adc6"
resolved "http://registry.npm.taobao.org/default-user-agent/download/default-user-agent-1.0.0.tgz#16c46efdcaba3edc45f24f2bd4868b01b7c2adc6"
dependencies:
os-name "~1.0.3"
@@ -2616,7 +2624,7 @@ des.js@^1.0.0:
destroy@^1.0.4, destroy@~1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
resolved "http://registry.npm.taobao.org/destroy/download/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
detect-indent@^4.0.0:
version "4.0.0"
@@ -2662,7 +2670,7 @@ diffie-hellman@^5.0.0:
digest-header@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/digest-header/-/digest-header-0.0.1.tgz#11ccf6deec5766ac379744d901c12cba49514be6"
resolved "http://registry.npm.taobao.org/digest-header/download/digest-header-0.0.1.tgz#11ccf6deec5766ac379744d901c12cba49514be6"
dependencies:
utility "0.1.11"
@@ -2811,7 +2819,7 @@ ecc-jsbn@~0.1.1:
ee-first@1.1.1, ee-first@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
resolved "http://registry.npm.taobao.org/ee-first/download/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
ejs@^2.5.7, ejs@~2.5.6:
version "2.5.7"
@@ -2983,12 +2991,14 @@ electron@^1.7.5:
extract-zip "^1.0.3"
element-ui@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/element-ui/-/element-ui-2.0.5.tgz#e001cb3514d8303a54f2b7d893b916acfc9ac57d"
version "2.4.3"
resolved "https://registry.yarnpkg.com/element-ui/-/element-ui-2.4.3.tgz#17a09ba6332b17a90002d86070697dcdb88fe0a5"
dependencies:
async-validator "~1.8.1"
babel-helper-vue-jsx-merge-props "^2.0.0"
deepmerge "^1.2.0"
normalize-wheel "^1.0.1"
resize-observer-polyfill "^1.5.0"
throttle-debounce "^1.0.1"
elliptic@^6.0.0:
@@ -3011,12 +3021,18 @@ encodeurl@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20"
end-of-stream@^1.0.0, end-of-stream@^1.1.0:
end-of-stream@^1.0.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.0.tgz#7a90d833efda6cfa6eac0f4949dbb0fad3a63206"
dependencies:
once "^1.4.0"
end-of-stream@^1.1.0:
version "1.4.1"
resolved "http://registry.npm.taobao.org/end-of-stream/download/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43"
dependencies:
once "^1.4.0"
engine.io-client@1.8.3:
version "1.8.3"
resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-1.8.3.tgz#1798ed93451246453d4c6f635d7a201fe940d5ab"
@@ -3172,7 +3188,7 @@ es6-weak-map@^2.0.1:
escape-html@~1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
resolved "http://registry.npm.taobao.org/escape-html/download/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
version "1.0.5"
@@ -3366,7 +3382,7 @@ estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0:
esutils@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
resolved "http://registry.npm.taobao.org/esutils/download/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
etag@~1.8.1:
version "1.8.1"
@@ -3532,7 +3548,7 @@ fast-json-stable-stringify@^2.0.0:
fast-levenshtein@~2.0.4:
version "2.0.6"
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
resolved "http://registry.npm.taobao.org/fast-levenshtein/download/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
fastparse@^1.0.0, fastparse@^1.1.1:
version "1.1.1"
@@ -3556,6 +3572,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"
@@ -4255,10 +4275,16 @@ humanize-plus@^1.8.1:
version "1.8.2"
resolved "https://registry.yarnpkg.com/humanize-plus/-/humanize-plus-1.8.2.tgz#a65b34459ad6367adbb3707a82a3c9f916167030"
iconv-lite@0.4.19, iconv-lite@^0.4.15, iconv-lite@^0.4.17, iconv-lite@^0.4.19, iconv-lite@~0.4.11:
iconv-lite@0.4.19, iconv-lite@^0.4.17, iconv-lite@^0.4.19, iconv-lite@~0.4.11:
version "0.4.19"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
iconv-lite@^0.4.15:
version "0.4.23"
resolved "http://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63"
dependencies:
safer-buffer ">= 2.1.2 < 3"
icss-replace-symbols@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded"
@@ -4625,7 +4651,7 @@ is-wsl@^1.1.0:
isarray@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
resolved "http://registry.npm.taobao.org/isarray/download/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
version "1.0.0"
@@ -4647,7 +4673,7 @@ isobject@^2.0.0:
isstream@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
resolved "http://registry.npm.taobao.org/isstream/download/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
istanbul-lib-coverage@^1.1.1:
version "1.1.1"
@@ -4884,6 +4910,10 @@ keyboardevents-areequal@^0.2.1:
version "0.2.2"
resolved "https://registry.yarnpkg.com/keyboardevents-areequal/-/keyboardevents-areequal-0.2.2.tgz#88191ec738ce9f7591c25e9056de928b40277194"
keycode@^2.1.9:
version "2.1.9"
resolved "https://registry.yarnpkg.com/keycode/-/keycode-2.1.9.tgz#964a23c54e4889405b4861a5c9f0480d45141dfa"
keypress@0.1.x:
version "0.1.0"
resolved "https://registry.yarnpkg.com/keypress/-/keypress-0.1.0.tgz#4a3188d4291b66b4f65edb99f806aa9ae293592a"
@@ -5372,10 +5402,14 @@ mime@1.3.6, mime@1.3.x:
version "1.3.6"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.6.tgz#591d84d3653a6b0b4a3b9df8de5aa8108e72e5e0"
mime@1.4.1, mime@^1.3.4:
mime@1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
mime@^1.3.4:
version "1.6.0"
resolved "http://registry.npm.taobao.org/mime/download/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
mime@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/mime/-/mime-2.0.3.tgz#4353337854747c48ea498330dc034f9f4bbbcc0b"
@@ -5400,11 +5434,11 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
minimist@0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
resolved "http://registry.npm.taobao.org/minimist/download/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
minimist@1.2.0, minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
resolved "http://registry.npm.taobao.org/minimist/download/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
minimist@~0.0.1:
version "0.0.10"
@@ -5453,9 +5487,13 @@ ms@0.7.2:
version "0.7.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765"
ms@2.0.0, ms@^2.0.0:
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
resolved "http://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
ms@^2.0.0:
version "2.1.1"
resolved "http://registry.npm.taobao.org/ms/download/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
multicast-dns-service-types@^1.1.0:
version "1.1.0"
@@ -5622,6 +5660,10 @@ normalize-url@^1.4.0:
query-string "^4.1.0"
sort-keys "^1.0.0"
normalize-wheel@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/normalize-wheel/-/normalize-wheel-1.0.1.tgz#aec886affdb045070d856447df62ecf86146ec45"
npm-install-package@~2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/npm-install-package/-/npm-install-package-2.1.0.tgz#d7efe3cfcd7ab00614b896ea53119dc9ab259125"
@@ -5790,7 +5832,7 @@ os-locale@^2.0.0:
os-name@~1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/os-name/-/os-name-1.0.3.tgz#1b379f64835af7c5a7f498b357cb95215c159edf"
resolved "http://registry.npm.taobao.org/os-name/download/os-name-1.0.3.tgz#1b379f64835af7c5a7f498b357cb95215c159edf"
dependencies:
osx-release "^1.0.0"
win-release "^1.0.0"
@@ -5808,7 +5850,7 @@ osenv@^0.1.4:
osx-release@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/osx-release/-/osx-release-1.1.0.tgz#f217911a28136949af1bf9308b241e2737d3cd6c"
resolved "http://registry.npm.taobao.org/osx-release/download/osx-release-1.1.0.tgz#f217911a28136949af1bf9308b241e2737d3cd6c"
dependencies:
minimist "^1.1.0"
@@ -6335,7 +6377,7 @@ prebuild-install@^2.3.0:
prelude-ls@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
resolved "http://registry.npm.taobao.org/prelude-ls/download/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
prepend-http@^1.0.0, prepend-http@^1.0.1:
version "1.0.4"
@@ -6405,7 +6447,7 @@ prr@~0.0.0:
pseudomap@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
resolved "http://registry.npm.taobao.org/pseudomap/download/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
public-encrypt@^4.0.0:
version "4.0.0"
@@ -6553,10 +6595,14 @@ qjobs@^1.1.4:
version "1.1.5"
resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.1.5.tgz#659de9f2cf8dcc27a1481276f205377272382e73"
qs@6.5.1, qs@^6.4.0, qs@~6.5.1:
qs@6.5.1, qs@~6.5.1:
version "6.5.1"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8"
qs@^6.4.0:
version "6.5.2"
resolved "http://registry.npm.taobao.org/qs/download/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
qs@~6.4.0:
version "6.4.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
@@ -6756,8 +6802,8 @@ regenerator-runtime@^0.10.0:
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658"
regenerator-runtime@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz#7e54fe5b5ccd5d6624ea6255c3473be090b802e1"
version "0.11.1"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
regenerator-transform@^0.10.0:
version "0.10.1"
@@ -6944,6 +6990,10 @@ requires-port@1.0.x, requires-port@1.x.x, requires-port@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
resize-observer-polyfill@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.0.tgz#660ff1d9712a2382baa2cad450a4716209f9ca69"
resolve-cwd@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
@@ -7025,10 +7075,18 @@ rx-lite@*, rx-lite@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444"
safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2"
resolved "http://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
"safer-buffer@>= 2.1.2 < 3":
version "2.1.2"
resolved "http://registry.npm.taobao.org/safer-buffer/download/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
sanitize-filename@^1.6.1:
version "1.6.1"
resolved "https://registry.yarnpkg.com/sanitize-filename/-/sanitize-filename-1.6.1.tgz#612da1c96473fa02dccda92dcd5b4ab164a6772a"
@@ -7065,7 +7123,7 @@ semver-diff@^2.0.0:
dependencies:
semver "^5.0.3"
"semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1:
"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1:
version "5.4.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e"
@@ -7073,6 +7131,10 @@ semver@5.3.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
semver@^5.0.1:
version "5.5.0"
resolved "http://registry.npm.taobao.org/semver/download/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
semver@~4.3.3:
version "4.3.6"
resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da"
@@ -7141,7 +7203,7 @@ setprototypeof@1.0.3:
setprototypeof@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
resolved "http://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
sha.js@^2.4.0, sha.js@^2.4.8:
version "2.4.9"
@@ -7321,7 +7383,7 @@ source-map@0.5.x, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, sourc
source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
resolved "http://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
source-map@~0.2.0:
version "0.2.0"
@@ -7408,10 +7470,14 @@ stat-mode@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-0.2.2.tgz#e6c80b623123d7d80cf132ce538f346289072502"
"statuses@>= 1.3.1 < 2", statuses@^1.3.1:
"statuses@>= 1.3.1 < 2":
version "1.4.0"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087"
statuses@^1.3.1:
version "1.5.0"
resolved "http://registry.npm.taobao.org/statuses/download/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
statuses@~1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e"
@@ -7470,7 +7536,7 @@ string_decoder@^1.0.0, string_decoder@~1.0.3:
string_decoder@~0.10.x:
version "0.10.31"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
resolved "http://registry.npm.taobao.org/string_decoder/download/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
stringstream@~0.0.4, stringstream@~0.0.5:
version "0.0.5"
@@ -7692,8 +7758,8 @@ text-table@^0.2.0, text-table@~0.2.0:
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
throttle-debounce@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-1.0.1.tgz#dad0fe130f9daf3719fdea33dc36a8e6ba7f30b5"
version "1.1.0"
resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-1.1.0.tgz#51853da37be68a155cb6e827b3514a3c422e89cd"
throttleit@0.0.2:
version "0.0.2"
@@ -7753,7 +7819,7 @@ to-array@0.1.4:
to-arraybuffer@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
resolved "http://registry.npm.taobao.org/to-arraybuffer/download/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
to-fast-properties@^1.0.3:
version "1.0.3"
@@ -7807,7 +7873,7 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
type-check@~0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
resolved "http://registry.npm.taobao.org/type-check/download/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
dependencies:
prelude-ls "~1.1.2"
@@ -8003,7 +8069,7 @@ utf8-byte-length@^1.0.1:
util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
resolved "http://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
util@0.10.3, util@^0.10.3:
version "0.10.3"
@@ -8021,7 +8087,7 @@ utila@~0.4:
utility@0.1.11:
version "0.1.11"
resolved "https://registry.yarnpkg.com/utility/-/utility-0.1.11.tgz#fde60cf9b4e4751947a0cf5d104ce29367226715"
resolved "http://registry.npm.taobao.org/utility/download/utility-0.1.11.tgz#fde60cf9b4e4751947a0cf5d104ce29367226715"
dependencies:
address ">=0.0.1"
@@ -8098,6 +8164,10 @@ vue-html-loader@^1.2.4:
loader-utils "^1.0.2"
object-assign "^4.1.0"
vue-lazyload@^1.2.6:
version "1.2.6"
resolved "https://registry.yarnpkg.com/vue-lazyload/-/vue-lazyload-1.2.6.tgz#baa04c172d52a812608eb12c7a6bfb14f5c91079"
vue-loader@^13.0.5:
version "13.5.0"
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-13.5.0.tgz#52f7b3790a267eff80012b77ea187a54586dd5d4"
@@ -8333,7 +8403,7 @@ widest-line@^1.0.0:
win-release@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/win-release/-/win-release-1.1.1.tgz#5fa55e02be7ca934edfc12665632e849b72e5209"
resolved "http://registry.npm.taobao.org/win-release/download/win-release-1.1.1.tgz#5fa55e02be7ca934edfc12665632e849b72e5209"
dependencies:
semver "^5.0.1"
@@ -8358,7 +8428,7 @@ wordwrap@0.0.2:
wordwrap@^1.0.0, wordwrap@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
resolved "http://registry.npm.taobao.org/wordwrap/download/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
wordwrap@~0.0.2:
version "0.0.3"
@@ -8373,7 +8443,7 @@ wrap-ansi@^2.0.0:
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
resolved "http://registry.npm.taobao.org/wrappy/download/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
write-file-atomic@^2.0.0:
version "2.3.0"
@@ -8436,7 +8506,7 @@ y18n@^3.2.1:
yallist@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
resolved "http://registry.npm.taobao.org/yallist/download/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
yargs-parser@^4.2.0:
version "4.2.1"