mirror of
https://github.com/Kuingsmile/PicList.git
synced 2026-07-12 16:11:27 +08:00
First beta version
This commit is contained in:
23
src/datastore/index.js
Normal file
23
src/datastore/index.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import Datastore from 'lowdb'
|
||||
import FileSync from 'lowdb/adapters/FileSync'
|
||||
import path from 'path'
|
||||
import { remote, app } from 'electron'
|
||||
|
||||
const APP = process.type === 'renderer' ? remote.app : app
|
||||
const STORE_PATH = APP.getPath('userData')
|
||||
|
||||
const adapter = new FileSync(path.join(STORE_PATH, '/data.json'))
|
||||
|
||||
const db = Datastore(adapter)
|
||||
|
||||
if (!db.has('uploaded').value()) {
|
||||
db.set('uploaded', []).write()
|
||||
}
|
||||
|
||||
if (!db.has('picBed').value()) {
|
||||
db.set('picBed', {
|
||||
current: 'weibo'
|
||||
}).write()
|
||||
}
|
||||
|
||||
export default db
|
||||
22
src/index.ejs
Normal file
22
src/index.ejs
Normal file
@@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>PicGo</title>
|
||||
<% if (htmlWebpackPlugin.options.nodeModules) { %>
|
||||
<!-- Add `node_modules/` to global paths so `require` works properly in development -->
|
||||
<script>
|
||||
require('module').globalPaths.push("<%= htmlWebpackPlugin.options.nodeModules.replace(/\\/g, '\\\\') %>")
|
||||
</script>
|
||||
<% } %>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<!-- Set `__static` path to static files in production -->
|
||||
<script>
|
||||
if (process.env.NODE_ENV !== 'development') window.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
|
||||
</script>
|
||||
|
||||
<!-- webpack builds are automatically injected -->
|
||||
</body>
|
||||
</html>
|
||||
27
src/main/index.dev.js
Normal file
27
src/main/index.dev.js
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* This file is used specifically and only for development. It installs
|
||||
* `electron-debug` & `vue-devtools`. There shouldn't be any need to
|
||||
* modify this file, but it can be used to extend your development
|
||||
* environment.
|
||||
*/
|
||||
|
||||
/* eslint-disable */
|
||||
|
||||
// Set environment for development
|
||||
process.env.NODE_ENV = 'development'
|
||||
|
||||
// Install `electron-debug` with `devtron`
|
||||
require('electron-debug')({ showDevTools: false })
|
||||
|
||||
// Install `vue-devtools`
|
||||
require('electron').app.on('ready', () => {
|
||||
let installExtension = require('electron-devtools-installer')
|
||||
installExtension.default(installExtension.VUEJS_DEVTOOLS)
|
||||
.then(() => {})
|
||||
.catch(err => {
|
||||
console.log('Unable to install `vue-devtools`: \n', err)
|
||||
})
|
||||
})
|
||||
|
||||
// Require `main` process to boot app
|
||||
require('./index')
|
||||
230
src/main/index.js
Normal file
230
src/main/index.js
Normal file
@@ -0,0 +1,230 @@
|
||||
'use strict'
|
||||
|
||||
import { weiboUpload } from './utils/weiboUpload.js'
|
||||
import { app, BrowserWindow, Tray, Menu, Notification, clipboard, ipcMain } from 'electron'
|
||||
import db from '../datastore/index'
|
||||
/**
|
||||
* Set `__static` path to static files in production
|
||||
* https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html
|
||||
*/
|
||||
if (process.env.NODE_ENV !== 'development') {
|
||||
global.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
|
||||
}
|
||||
|
||||
let window
|
||||
let settingWindow
|
||||
let tray
|
||||
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`
|
||||
|
||||
function createTray () {
|
||||
tray = new Tray(`${__static}/menubarDefaultTemplate.png`)
|
||||
const contextMenu = Menu.buildFromTemplate([
|
||||
{
|
||||
role: 'quit',
|
||||
label: 'Quit'
|
||||
},
|
||||
{
|
||||
label: 'Open setting Window',
|
||||
click () {
|
||||
if (settingWindow === null) {
|
||||
createSettingWindow()
|
||||
} else {
|
||||
settingWindow.show()
|
||||
settingWindow.focus()
|
||||
}
|
||||
}
|
||||
}
|
||||
])
|
||||
tray.on('right-click', () => {
|
||||
window.hide()
|
||||
tray.popUpContextMenu(contextMenu)
|
||||
})
|
||||
tray.on('click', () => {
|
||||
let img = clipboard.readImage()
|
||||
let obj = []
|
||||
if (!img.isEmpty()) {
|
||||
obj.push({
|
||||
width: img.getSize().width,
|
||||
height: img.getSize().height,
|
||||
imgUrl: img.toDataURL()
|
||||
})
|
||||
}
|
||||
toggleWindow()
|
||||
setTimeout(() => {
|
||||
window.webContents.send('clipboardFiles', obj)
|
||||
}, 0)
|
||||
})
|
||||
|
||||
tray.on('drag-enter', () => {
|
||||
tray.setImage(`${__static}/upload.png`)
|
||||
})
|
||||
|
||||
tray.on('drag-end', () => {
|
||||
tray.setImage(`${__static}/menubarDefaultTemplate.png`)
|
||||
})
|
||||
|
||||
tray.on('drop-files', async (event, files) => {
|
||||
const imgs = await weiboUpload(files, 'imgFromPath')
|
||||
for (let i in imgs) {
|
||||
clipboard.writeText(imgs[i].imgUrl)
|
||||
const notification = new Notification({
|
||||
title: '上传成功',
|
||||
body: imgs[i].imgUrl,
|
||||
icon: files[i]
|
||||
})
|
||||
setTimeout(() => {
|
||||
notification.show()
|
||||
}, i * 100)
|
||||
}
|
||||
console.log('drag-files')
|
||||
window.webContents.send('dragFiles', imgs)
|
||||
})
|
||||
toggleWindow()
|
||||
}
|
||||
|
||||
const createWindow = () => {
|
||||
window = new BrowserWindow({
|
||||
height: 350,
|
||||
width: 196, // 196
|
||||
show: false,
|
||||
frame: false,
|
||||
fullscreenable: false,
|
||||
resizable: false,
|
||||
transparent: true,
|
||||
vibrancy: 'ultra-dark',
|
||||
webPreferences: {
|
||||
backgroundThrottling: false
|
||||
}
|
||||
})
|
||||
|
||||
window.loadURL(winURL)
|
||||
|
||||
window.on('closed', () => {
|
||||
window = null
|
||||
})
|
||||
|
||||
window.on('blur', () => {
|
||||
window.hide()
|
||||
})
|
||||
|
||||
createSettingWindow()
|
||||
}
|
||||
|
||||
const createSettingWindow = () => {
|
||||
settingWindow = new BrowserWindow({
|
||||
height: 450,
|
||||
width: 800,
|
||||
show: true,
|
||||
frame: true,
|
||||
center: true,
|
||||
fullscreenable: false,
|
||||
resizable: false,
|
||||
title: 'Pic',
|
||||
vibrancy: 'ultra-dark',
|
||||
transparent: true,
|
||||
titleBarStyle: 'hidden',
|
||||
webPreferences: {
|
||||
backgroundThrottling: false
|
||||
}
|
||||
})
|
||||
|
||||
settingWindow.loadURL(settingWinURL)
|
||||
|
||||
settingWindow.on('closed', () => {
|
||||
settingWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
const getWindowPosition = () => {
|
||||
const windowBounds = window.getBounds()
|
||||
const trayBounds = tray.getBounds()
|
||||
const x = Math.round(trayBounds.x + (trayBounds.width / 2) - (windowBounds.width / 2))
|
||||
const y = Math.round(trayBounds.y + trayBounds.height - 10)
|
||||
|
||||
return {
|
||||
x,
|
||||
y
|
||||
}
|
||||
}
|
||||
|
||||
const toggleWindow = () => {
|
||||
if (window.isVisible()) {
|
||||
window.hide()
|
||||
} else {
|
||||
showWindow()
|
||||
}
|
||||
}
|
||||
|
||||
// const toggleSettingWindow = () => {
|
||||
// if (settingWindow.isVisible()) {
|
||||
// settingWindow.hide()
|
||||
// } else {
|
||||
// settingWindow.show()
|
||||
// settingWindow.focus()
|
||||
// }
|
||||
// }
|
||||
|
||||
const showWindow = () => {
|
||||
const position = getWindowPosition()
|
||||
window.setPosition(position.x, position.y, false)
|
||||
window.show()
|
||||
window.focus()
|
||||
}
|
||||
|
||||
ipcMain.on('uploadClipboardFiles', async (evt, file) => {
|
||||
const img = await weiboUpload(file, 'imgFromClipboard')
|
||||
clipboard.writeText(img[0].imgUrl)
|
||||
const notification = new Notification({
|
||||
title: '上传成功',
|
||||
body: img[0].imgUrl,
|
||||
icon: file[0]
|
||||
})
|
||||
notification.show()
|
||||
clipboard.clear()
|
||||
window.webContents.send('clipboardFiles', [])
|
||||
window.webContents.send('uploadClipboardFiles', img)
|
||||
console.log('clipboard-upload')
|
||||
})
|
||||
|
||||
app.on('ready', () => {
|
||||
createWindow()
|
||||
createTray()
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (window === null || settingWindow === null) {
|
||||
createWindow()
|
||||
createTray()
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Auto Updater
|
||||
*
|
||||
* Uncomment the following code below and install `electron-updater` to
|
||||
* support auto updating. Code Signing with a valid certificate is required.
|
||||
* https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-electron-builder.html#auto-updating
|
||||
*/
|
||||
|
||||
// import { autoUpdater } from 'electron-updater'
|
||||
|
||||
// autoUpdater.on('update-downloaded', () => {
|
||||
// autoUpdater.quitAndInstall()
|
||||
// })
|
||||
|
||||
// app.on('ready', () => {
|
||||
// if (process.env.NODE_ENV === 'production') {
|
||||
// autoUpdater.checkForUpdates()
|
||||
// }
|
||||
// })
|
||||
35
src/main/utils/img2base64.js
Normal file
35
src/main/utils/img2base64.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import fs from 'fs-extra'
|
||||
import path from 'path'
|
||||
import sizeOf from 'image-size'
|
||||
|
||||
const imgFromPath = async (imgPath) => {
|
||||
let results = []
|
||||
await Promise.all(imgPath.map(async item => {
|
||||
let buffer = await fs.readFile(item)
|
||||
let base64Image = Buffer.from(buffer, 'binary').toString('base64')
|
||||
let fileName = path.basename(item)
|
||||
let imgSize = sizeOf(item)
|
||||
results.push({
|
||||
base64Image,
|
||||
fileName,
|
||||
width: imgSize.width,
|
||||
height: imgSize.height
|
||||
})
|
||||
}))
|
||||
return results
|
||||
}
|
||||
|
||||
const imgFromClipboard = (file) => {
|
||||
let result = []
|
||||
result.push({
|
||||
base64Image: file.imgUrl.replace(/^data\S+,/, ''),
|
||||
width: file.width,
|
||||
height: file.height
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
export {
|
||||
imgFromPath,
|
||||
imgFromClipboard
|
||||
}
|
||||
66
src/main/utils/weiboUpload.js
Normal file
66
src/main/utils/weiboUpload.js
Normal 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 j = request.jar()
|
||||
const rp = request.defaults({jar: j})
|
||||
const UPLOAD_URL = 'http://picupload.service.weibo.com/interface/pic_upload.php?ori=1&mime=image%2Fjpeg&data=base64&url=0&markpos=1&logo=&nick=0&marks=1&app=miniblog'
|
||||
|
||||
function postOptions (formData) {
|
||||
return {
|
||||
method: 'POST',
|
||||
url: 'https://passport.weibo.cn/sso/login',
|
||||
headers: {
|
||||
Referer: 'https://passport.weibo.cn/signin/login',
|
||||
contentType: 'application/x-www-form-urlencoded'
|
||||
},
|
||||
formData,
|
||||
json: true,
|
||||
resolveWithFullResponse: true
|
||||
}
|
||||
}
|
||||
|
||||
const weiboUpload = async function (img, type) {
|
||||
try {
|
||||
const formData = {
|
||||
username: db.read().get('picBed.weibo.username').value(),
|
||||
password: db.read().get('picBed.weibo.password').value()
|
||||
}
|
||||
const options = postOptions(formData)
|
||||
const res = await rp(options)
|
||||
if (res.body.retcode === 20000000) {
|
||||
for (let i in res.body.data.crossdomainlist) {
|
||||
await rp.get(res.body.data.crossdomainlist[i])
|
||||
}
|
||||
const imgList = await img2Base64[type](img)
|
||||
let resText = []
|
||||
for (let i in imgList) {
|
||||
let result = await rp.post(UPLOAD_URL, {
|
||||
formData: {
|
||||
b64_data: imgList[i].base64Image
|
||||
}
|
||||
})
|
||||
resText.push(result.replace(/<.*?\/>/, '').replace(/<(\w+).*?>.*?<\/\1>/, ''))
|
||||
}
|
||||
for (let i in imgList) {
|
||||
const resTextJson = JSON.parse(resText[i])
|
||||
imgList[i]['imgUrl'] = `https://ws1.sinaimg.cn/large/${resTextJson.data.pics.pic_1.pid}`
|
||||
delete imgList[i].base64Image
|
||||
}
|
||||
return imgList
|
||||
} else {
|
||||
const notification = new Notification({
|
||||
title: '上传失败!',
|
||||
body: res.body.msg
|
||||
})
|
||||
notification.show()
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('This is error', err, err.name === 'RequestError')
|
||||
throw new Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
weiboUpload
|
||||
}
|
||||
20
src/renderer/App.vue
Normal file
20
src/renderer/App.vue
Normal file
@@ -0,0 +1,20 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'picgo'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus">
|
||||
body,
|
||||
html
|
||||
padding 0
|
||||
margin 0
|
||||
height 100%
|
||||
font-family "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif
|
||||
</style>
|
||||
0
src/renderer/assets/.gitkeep
Normal file
0
src/renderer/assets/.gitkeep
Normal file
BIN
src/renderer/assets/logo.png
Normal file
BIN
src/renderer/assets/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 60 KiB |
83
src/renderer/components/SettingPage.vue
Normal file
83
src/renderer/components/SettingPage.vue
Normal file
@@ -0,0 +1,83 @@
|
||||
<template>
|
||||
<div id="setting-page">
|
||||
<div class="fake-title-bar">
|
||||
PicGo
|
||||
</div>
|
||||
<el-row>
|
||||
<el-col :span="5">
|
||||
<el-menu
|
||||
class="picgo-sidebar"
|
||||
:default-active="defaultActive"
|
||||
@select="handleSelect"
|
||||
>
|
||||
<el-menu-item index="upload">
|
||||
<i class="el-icon-upload"></i>
|
||||
<span slot="title">上传区</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="weibo">
|
||||
<i class="el-icon-setting"></i>
|
||||
<span slot="title">微博设置</span>
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
</el-col>
|
||||
<el-col :span="19">
|
||||
<router-view></router-view>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'setting-page',
|
||||
data () {
|
||||
return {
|
||||
defaultActive: 'upload'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleSelect (index) {
|
||||
this.$router.push({
|
||||
name: index
|
||||
})
|
||||
}
|
||||
},
|
||||
beforeRouteEnter: (to, from, next) => {
|
||||
next(vm => {
|
||||
vm.defaultActive = to.name
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
#setting-page
|
||||
.fake-title-bar
|
||||
-webkit-app-region drag
|
||||
height h = 22px
|
||||
width 100%
|
||||
text-align center
|
||||
color #eee
|
||||
font-size 12px
|
||||
line-height h
|
||||
.picgo-sidebar
|
||||
height calc(100vh - 22px)
|
||||
.el-menu
|
||||
border-right none
|
||||
background transparent
|
||||
&-item
|
||||
color #eee
|
||||
position relative
|
||||
&:focus,
|
||||
&:hover
|
||||
color #fff
|
||||
background transparent
|
||||
&.is-active
|
||||
color active-color = #409EFF
|
||||
&:before
|
||||
content ''
|
||||
position absolute
|
||||
width 3px
|
||||
height 20px
|
||||
right 0
|
||||
top 18px
|
||||
background active-color
|
||||
</style>
|
||||
37
src/renderer/components/SettingView/ChoosePicBed.vue
Normal file
37
src/renderer/components/SettingView/ChoosePicBed.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<div id="choose-pic-bed">
|
||||
<span>选择 {{ label }} 作为你默认图床:</span>
|
||||
<el-switch
|
||||
v-model="value"
|
||||
@change="choosePicBed"
|
||||
>
|
||||
</el-switch>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'choose-pic-bed',
|
||||
props: {
|
||||
type: String,
|
||||
label: String
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
value: false
|
||||
}
|
||||
},
|
||||
created () {
|
||||
if (this.type === this.$db.get('picBed.current').value()) {
|
||||
this.value = true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
choosePicBed (val) {
|
||||
this.$db.set('picBed.current', this.type)
|
||||
this.$emit('update:choosed', this.type)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
</style>
|
||||
17
src/renderer/components/SettingView/Upload.vue
Normal file
17
src/renderer/components/SettingView/Upload.vue
Normal file
@@ -0,0 +1,17 @@
|
||||
<template>
|
||||
<div id="upload-view">
|
||||
upload
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'upload',
|
||||
data () {
|
||||
return {
|
||||
msg: '123'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
</style>
|
||||
94
src/renderer/components/SettingView/Weibo.vue
Normal file
94
src/renderer/components/SettingView/Weibo.vue
Normal file
@@ -0,0 +1,94 @@
|
||||
<template>
|
||||
<div id="weibo-view">
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12" :offset="6">
|
||||
<div class="view-title">
|
||||
微博图床设置
|
||||
</div>
|
||||
<el-form
|
||||
ref="weiboForm"
|
||||
label-position="top"
|
||||
label-width="80px"
|
||||
:model="form">
|
||||
<el-form-item
|
||||
label="设定用户名"
|
||||
prop="username"
|
||||
:rules="{
|
||||
required: true, message: '用户名不能为空', trigger: 'blur'
|
||||
}">
|
||||
<el-input v-model="form.username" placeholder="用户名"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="设定密码"
|
||||
prop="password"
|
||||
:rules="{
|
||||
required: true, message: '密码不能为空', trigger: 'blur'
|
||||
}">
|
||||
<el-input v-model="form.password" type="password" placeholder="密码"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="confirm('weiboForm')">确定</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'weibo',
|
||||
data () {
|
||||
return {
|
||||
form: {
|
||||
username: '',
|
||||
password: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
created () {
|
||||
const account = this.$db.get('picBed.weibo').value()
|
||||
console.log(account)
|
||||
if (account) {
|
||||
this.form.username = account.username
|
||||
this.form.password = account.password
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
confirm (formName) {
|
||||
this.$refs[formName].validate((valid) => {
|
||||
if (valid) {
|
||||
this.$db.set('picBed.weibo', {
|
||||
username: this.form.username,
|
||||
password: this.form.password
|
||||
}).write()
|
||||
console.log(this.$db.get('picBed.weibo').value())
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '设置成功'
|
||||
})
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang='stylus'>
|
||||
.el-message
|
||||
left 60%
|
||||
#weibo-view
|
||||
.view-title
|
||||
color #eee
|
||||
font-size 20px
|
||||
text-align center
|
||||
margin 20px auto
|
||||
.el-form
|
||||
label
|
||||
line-height 22px
|
||||
padding-bottom 0
|
||||
color #eee
|
||||
.el-button
|
||||
width 100%
|
||||
margin-top 10px
|
||||
</style>
|
||||
142
src/renderer/components/TrayPage.vue
Normal file
142
src/renderer/components/TrayPage.vue
Normal file
@@ -0,0 +1,142 @@
|
||||
<template>
|
||||
<div id="tray-page">
|
||||
<div class="content">
|
||||
<div class="wait-upload-img" v-if="clipboardFiles.length > 0">
|
||||
<div class="list-title">等待上传</div>
|
||||
<div v-for="(item, index) in clipboardFiles" :key="index" class="img-list" :style="{height: calcHeight(item.width, item.height) + 'px'}">
|
||||
<div class="upload-img__container" @click="uploadClipboardFiles">
|
||||
<img :src="item.imgUrl" class="upload-img">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="uploaded-img">
|
||||
<div class="list-title">已上传</div>
|
||||
<div v-for="(item, index) in files" :key="index" class="img-list" :style="{height: calcHeight(item.width, item.height) + 'px'}">
|
||||
<div class="upload-img__container" @click="copyTheLink(item)">
|
||||
<img :src="item.imgUrl" class="upload-img">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'tray-page',
|
||||
data () {
|
||||
return {
|
||||
files: [],
|
||||
notification: {
|
||||
title: '复制链接成功',
|
||||
body: '',
|
||||
icon: ''
|
||||
},
|
||||
clipboardFiles: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
reverseList () {
|
||||
return this.files.slice().reverse()
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.disableDragFile()
|
||||
this.getData()
|
||||
this.$electron.ipcRenderer.on('dragFiles', (event, files) => {
|
||||
this.$db.get('uploaded').push(...files).write()
|
||||
this.files = this.$db.get('uploaded').slice().reverse().slice(0, 5).value()
|
||||
})
|
||||
this.$electron.ipcRenderer.on('clipboardFiles', (event, files) => {
|
||||
this.clipboardFiles = files
|
||||
})
|
||||
this.$electron.ipcRenderer.on('uploadClipboardFiles', (event, files) => {
|
||||
this.$db.get('uploaded').push(...files).write()
|
||||
this.files = this.$db.get('uploaded').slice().reverse().slice(0, 5).value()
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
getData () {
|
||||
this.files = this.$db.get('uploaded').slice().reverse().slice(0, 5).value()
|
||||
},
|
||||
copyTheLink (item) {
|
||||
this.notification.body = item.imgUrl
|
||||
this.notification.icon = item.imgUrl
|
||||
const myNotification = new window.Notification(this.notification.title, this.notification)
|
||||
myNotification.onclick = () => {
|
||||
this.$electron.clipboard.writeText(item.imgUrl)
|
||||
}
|
||||
},
|
||||
calcHeight (width, height) {
|
||||
return height * 160 / width
|
||||
},
|
||||
disableDragFile () {
|
||||
window.addEventListener('dragover', (e) => {
|
||||
e = e || event
|
||||
e.preventDefault()
|
||||
}, false)
|
||||
window.addEventListener('drop', (e) => {
|
||||
e = e || event
|
||||
e.preventDefault()
|
||||
}, false)
|
||||
},
|
||||
uploadClipboardFiles () {
|
||||
this.$electron.ipcRenderer.send('uploadClipboardFiles', this.clipboardFiles[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus">
|
||||
#tray-page
|
||||
.list-title
|
||||
text-align center
|
||||
color #858585
|
||||
font-size 12px
|
||||
padding 6px 0
|
||||
position relative
|
||||
&:before
|
||||
content ''
|
||||
position absolute
|
||||
height 1px
|
||||
width calc(100% - 36px)
|
||||
bottom 0
|
||||
left 18px
|
||||
background #858585
|
||||
.header-arrow
|
||||
position absolute
|
||||
top 12px
|
||||
left 50%
|
||||
margin-left -10px
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 10px solid transparent
|
||||
border-right: 10px solid transparent
|
||||
border-bottom: 10px solid rgba(255,255,255, 1)
|
||||
.content
|
||||
position absolute
|
||||
top 0px
|
||||
width 100%
|
||||
// padding-top 10px
|
||||
// background-color rgba(255,255,255, 1)
|
||||
.img-list
|
||||
padding 16px 8px
|
||||
display flex
|
||||
justify-content space-between
|
||||
align-items center
|
||||
height 45px
|
||||
cursor pointer
|
||||
transition all .2s ease-in-out
|
||||
&:hover
|
||||
background #49B1F5
|
||||
.upload-img__index
|
||||
color #fff
|
||||
.upload-img
|
||||
height 100%
|
||||
width 100%
|
||||
margin 0 auto
|
||||
&__container
|
||||
width 100%
|
||||
padding 8px 10px
|
||||
height 100%
|
||||
</style>
|
||||
22
src/renderer/main.js
Normal file
22
src/renderer/main.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import Vue from 'vue'
|
||||
import axios from 'axios'
|
||||
import ElementUI from 'element-ui'
|
||||
import 'element-ui/lib/theme-chalk/index.css'
|
||||
import App from './App'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
import db from '../datastore/index'
|
||||
Vue.use(ElementUI)
|
||||
|
||||
if (!process.env.IS_WEB) Vue.use(require('vue-electron'))
|
||||
Vue.http = Vue.prototype.$http = axios
|
||||
Vue.prototype.$db = db
|
||||
Vue.config.productionTip = false
|
||||
|
||||
/* eslint-disable no-new */
|
||||
new Vue({
|
||||
components: { App },
|
||||
router,
|
||||
store,
|
||||
template: '<App/>'
|
||||
}).$mount('#app')
|
||||
35
src/renderer/router/index.js
Normal file
35
src/renderer/router/index.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
export default new Router({
|
||||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
name: 'tray-page',
|
||||
component: require('@/components/TrayPage').default
|
||||
},
|
||||
{
|
||||
path: '/setting',
|
||||
name: 'setting-page',
|
||||
component: require('@/components/SettingPage').default,
|
||||
children: [
|
||||
{
|
||||
path: 'upload',
|
||||
component: require('@/components/SettingView/Upload').default,
|
||||
name: 'upload'
|
||||
},
|
||||
{
|
||||
path: 'weibo',
|
||||
component: require('@/components/SettingView/Weibo').default,
|
||||
name: 'weibo'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '*',
|
||||
redirect: '/'
|
||||
}
|
||||
]
|
||||
})
|
||||
11
src/renderer/store/index.js
Normal file
11
src/renderer/store/index.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
|
||||
import modules from './modules'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
export default new Vuex.Store({
|
||||
modules,
|
||||
strict: process.env.NODE_ENV !== 'production'
|
||||
})
|
||||
25
src/renderer/store/modules/Counter.js
Normal file
25
src/renderer/store/modules/Counter.js
Normal file
@@ -0,0 +1,25 @@
|
||||
const state = {
|
||||
main: 0
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
DECREMENT_MAIN_COUNTER (state) {
|
||||
state.main--
|
||||
},
|
||||
INCREMENT_MAIN_COUNTER (state) {
|
||||
state.main++
|
||||
}
|
||||
}
|
||||
|
||||
const actions = {
|
||||
someAsyncTask ({ commit }) {
|
||||
// do something async
|
||||
commit('INCREMENT_MAIN_COUNTER')
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
state,
|
||||
mutations,
|
||||
actions
|
||||
}
|
||||
14
src/renderer/store/modules/index.js
Normal file
14
src/renderer/store/modules/index.js
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* The file enables `@/store/index.js` to import all vuex modules
|
||||
* in a one-shot manner. There should not be any reason to edit this file.
|
||||
*/
|
||||
|
||||
const files = require.context('.', false, /\.js$/)
|
||||
const modules = {}
|
||||
|
||||
files.keys().forEach(key => {
|
||||
if (key === './index.js') return
|
||||
modules[key.replace(/(\.\/|\.js)/g, '')] = files(key).default
|
||||
})
|
||||
|
||||
export default modules
|
||||
Reference in New Issue
Block a user