张恒

合并分支

正在显示 58 个修改的文件 包含 1203 行增加623 行删除
......@@ -5,7 +5,6 @@ process.env.NODE_ENV = 'production'
const { say } = require('cfonts')
const chalk = require('chalk')
const del = require('del')
const { spawn } = require('child_process')
const webpack = require('webpack')
const Multispinner = require('multispinner')
......@@ -24,8 +23,8 @@ else if (process.env.BUILD_TARGET === 'web') web()
else build()
function clean () {
del.sync(['build/*', '!build/icons','!build/lib','!build/lib/electron-build.*', '!build/icons/icon.*'])
console.log(`\n${doneLog}\n`)
del.sync(['dist/electron/*','build/*', '!build/icons','!build/lib','!build/lib/electron-build.*', '!build/icons/icon.*'])
console.log(`\n${doneLog}clear done`)
process.exit()
}
......@@ -117,8 +116,8 @@ function greeting () {
const cols = process.stdout.columns
let text = ''
if (cols > 85) text = 'lets-build'
else if (cols > 60) text = 'lets-|build'
if (cols > 85) text = `let's-build`
else if (cols > 60) text = `let's-|build`
else text = false
if (text && !isCI) {
......@@ -127,6 +126,6 @@ function greeting () {
font: 'simple3d',
space: false
})
} else console.log(chalk.yellow.bold('\n lets-build'))
} else console.log(chalk.yellow.bold(`\n let's-build`))
console.log()
}
\ No newline at end of file
......
const hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
hotClient.subscribe(event => {
/**
* Reload browser when HTMLWebpackPlugin emits a new index.html
*
* Currently disabled until jantimon/html-webpack-plugin#680 is resolved.
* https://github.com/SimulatedGREG/electron-vue/issues/437
* https://github.com/jantimon/html-webpack-plugin/issues/680
*/
// if (event.action === 'reload') {
// window.location.reload()
// }
/**
* Notify `mainWindow` when `main` process is compiling,
* giving notice for an expected reload of the `electron` process
*/
if (event.action === 'compiling') {
document.body.innerHTML += `
<style>
#dev-client {
background: #4fc08d;
border-radius: 4px;
bottom: 20px;
box-shadow: 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12), 0 2px 4px -1px rgba(0, 0, 0, 0.3);
color: #fff;
font-family: 'Source Sans Pro', sans-serif;
left: 20px;
padding: 8px 12px;
position: absolute;
}
</style>
<div id="dev-client">
Compiling Main Process...
</div>
`
}
})
......@@ -9,6 +9,7 @@ const config = require('../config')
const webpack = require('webpack')
const WebpackDevServer = require('webpack-dev-server')
const webpackHotMiddleware = require('webpack-hot-middleware')
const Portfinder = require("portfinder")
const mainConfig = require('./webpack.main.config')
const rendererConfig = require('./webpack.renderer.config')
......@@ -20,7 +21,7 @@ let hotMiddleware
function logStats(proc, data) {
let log = ''
log += chalk.yellow.bold(`┏ ${proc} Process ${new Array((19 - proc.length) + 1).join('-')}`)
log += chalk.yellow.bold(`┏ ${proc} ${config.dev.chineseLog ? '编译过程' : 'Process'} ${new Array((19 - proc.length) + 1).join('-')}`)
log += '\n\n'
if (typeof data === 'object') {
......@@ -61,53 +62,64 @@ function removeJunk(chunk) {
}
function startRenderer() {
return new Promise((resolve) => {
rendererConfig.entry.renderer = [path.join(__dirname, 'dev-client')].concat(rendererConfig.entry.renderer)
return new Promise((resolve, reject) => {
rendererConfig.mode = 'development'
const compiler = webpack(rendererConfig)
hotMiddleware = webpackHotMiddleware(compiler, {
log: false,
heartbeat: 2500
})
compiler.hooks.compilation.tap('compilation', compilation => {
compilation.hooks.htmlWebpackPluginAfterEmit.tapAsync('html-webpack-plugin-after-emit', (data, cb) => {
hotMiddleware.publish({ action: 'reload' })
cb()
})
})
compiler.hooks.done.tap('done', stats => {
logStats('Renderer', stats)
})
const server = new WebpackDevServer(
compiler,
{
contentBase: path.join(__dirname, '../'),
quiet: true,
before(app, ctx) {
app.use(hotMiddleware)
ctx.middleware.waitUntilValid(() => {
resolve()
Portfinder.basePort = config.dev.port || 9080
Portfinder.getPort((err, port) => {
if (err) {
reject("PortError:" + err)
} else {
const compiler = webpack(rendererConfig)
hotMiddleware = webpackHotMiddleware(compiler, {
log: false,
heartbeat: 2500
})
compiler.hooks.compilation.tap('compilation', compilation => {
compilation.hooks.htmlWebpackPluginAfterEmit.tapAsync('html-webpack-plugin-after-emit', (data, cb) => {
hotMiddleware.publish({
action: 'reload'
})
cb()
})
})
compiler.hooks.done.tap('done', stats => {
logStats('Renderer', stats)
})
const server = new WebpackDevServer(
compiler, {
contentBase: path.join(__dirname, '../'),
quiet: true,
before(app, ctx) {
app.use(hotMiddleware)
ctx.middleware.waitUntilValid(() => {
resolve()
})
}
}
)
process.env.PORT = port
server.listen(port)
}
)
})
server.listen(9080)
})
}
function startMain() {
return new Promise((resolve) => {
mainConfig.entry.main = [path.join(__dirname, '../src/main/index.dev.js')].concat(mainConfig.entry.main)
mainConfig.mode = 'development'
const compiler = webpack(mainConfig)
compiler.hooks.watchRun.tapAsync('watch-run', (compilation, done) => {
logStats('Main', chalk.white.bold('compiling...'))
hotMiddleware.publish({ action: 'compiling' })
logStats(`${config.dev.chineseLog ? '主进程' : 'Main'}`, chalk.white.bold(`${config.dev.chineseLog ? '正在处理资源文件...' : 'compiling...'}`))
hotMiddleware.publish({
action: 'compiling'
})
done()
})
......@@ -117,7 +129,7 @@ function startMain() {
return
}
logStats('Main', stats)
logStats(`${config.dev.chineseLog ? '主进程' : 'Main'}`, stats)
if (electronProcess && electronProcess.kill) {
manualRestart = true
......@@ -163,20 +175,23 @@ function startElectron() {
}
function electronLog(data, color) {
let log = ''
data = data.toString().split(/\r?\n/)
data.forEach(line => {
log += ` ${line}\n`
})
if (/[0-9A-z]+/.test(log)) {
console.log(
chalk[color].bold('┏ Electron -------------------') +
'\n\n' +
log +
chalk[color].bold('┗ ----------------------------') +
'\n'
)
if (data) {
let log = ''
data = data.toString().split(/\r?\n/)
data.forEach(line => {
log += ` ${line}\n`
})
if (/[0-9A-z]+/.test(log)) {
console.log(
chalk[color].bold(`┏ ${config.dev.chineseLog ? '主程序日志' : 'Electron'} -------------------`) +
'\n\n' +
log +
chalk[color].bold('┗ ----------------------------') +
'\n'
)
}
}
}
function greeting() {
......@@ -194,19 +209,20 @@ function greeting() {
space: false
})
} else console.log(chalk.yellow.bold('\n electron-vue'))
console.log(chalk.blue(' getting ready......') + '\n')
console.log(chalk.blue(`${config.dev.chineseLog ? ' 准备启动...' : ' getting ready...'}`) + '\n')
}
function init() {
async function init() {
greeting()
Promise.all([startRenderer(), startMain()])
.then(() => {
startElectron()
})
.catch(err => {
console.error(err)
})
try {
await startRenderer()
await startMain()
await startElectron()
} catch (error) {
console.error(error)
}
}
init()
init()
\ No newline at end of file
......
......@@ -2,12 +2,13 @@
process.env.BABEL_ENV = 'main'
const os = require('os')
const path = require('path')
const { dependencies } = require('../package.json')
const webpack = require('webpack')
const BabiliWebpackPlugin = require('babili-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const MinifyPlugin = require("babel-minify-webpack-plugin");
const HappyPack = require('happypack')
const HappyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length })
function resolve(dir) {
return path.join(__dirname, '..', dir)
......@@ -35,7 +36,7 @@ let mainConfig = {
// },
{
test: /\.js$/,
use: 'babel-loader',
use: 'happypack/loader?id=MainHappyBabel',
exclude: /node_modules/
},
{
......@@ -55,13 +56,22 @@ let mainConfig = {
},
plugins: [
new webpack.NoEmitOnErrorsPlugin(),
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: resolve('dist/electron')
new HappyPack({
id: "MainHappyBabel",
loaders: [{
loader: 'babel-loader',
options: {
cacheDirectory: true
}
}],
threadPool: HappyThreadPool
})
],
resolve: {
extensions: ['.js', '.json', '.node']
alias: {
'@config': resolve('config'),
},
extensions: ['.tsx', '.ts', '.js', '.json', '.node']
},
target: 'electron-main'
}
......@@ -82,7 +92,7 @@ if (process.env.NODE_ENV !== 'production') {
*/
if (process.env.NODE_ENV === 'production') {
mainConfig.plugins.push(
new BabiliWebpackPlugin(),
new MinifyPlugin(),
new webpack.DefinePlugin({
'process.env.NODE_ENV': '"production"'
})
......
......@@ -2,17 +2,21 @@
process.env.BABEL_ENV = 'renderer'
const os = require('os')
const path = require('path')
const { dependencies } = require('../package.json')
const webpack = require('webpack')
const config = require('../config')
const BabiliWebpackPlugin = require('babili-webpack-plugin')
const MinifyPlugin = require("babel-minify-webpack-plugin");
const CopyWebpackPlugin = require('copy-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const TerserPlugin = require('terser-webpack-plugin');
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader')
const HappyPack = require('happypack')
const HappyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length })
function resolve(dir) {
return path.join(__dirname, '..', dir)
......@@ -24,7 +28,7 @@ function resolve(dir) {
* that provide pure *.vue files that need compiling
* https://simulatedgreg.gitbooks.io/electron-vue/content/en/webpack-configurations.html#white-listing-externals
*/
let whiteListedModules = ['vue', 'element-ui']
let whiteListedModules = ['vue', "element-ui"]
let rendererConfig = {
devtool: '#cheap-module-eval-source-map',
......@@ -69,7 +73,7 @@ let rendererConfig = {
},
{
test: /\.js$/,
use: 'babel-loader',
use: 'happypack/loader?id=HappyRendererBabel',
exclude: /node_modules/
},
{
......@@ -104,8 +108,8 @@ let rendererConfig = {
use: {
loader: 'url-loader',
query: {
limit: 10000,
esModule: false,
limit: 10000,
name: 'imgs/[name]--[folder].[ext]'
}
},
......@@ -114,8 +118,8 @@ let rendererConfig = {
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
esModule: false,
limit: 10000,
name: 'media/[name]--[folder].[ext]'
}
},
......@@ -124,8 +128,8 @@ let rendererConfig = {
use: {
loader: 'url-loader',
query: {
limit: 10000,
esModule: false,
limit: 10000,
name: 'fonts/[name]--[folder].[ext]'
}
}
......@@ -167,7 +171,18 @@ let rendererConfig = {
nodeModules: false
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin()
new webpack.NoEmitOnErrorsPlugin(),
new HardSourceWebpackPlugin(),
new HappyPack({
id: 'HappyRendererBabel',
loaders: [{
loader: 'babel-loader',
options: {
cacheDirectory: true
}
}],
threadPool: HappyThreadPool
}),
],
output: {
filename: '[name].js',
......@@ -190,7 +205,8 @@ let rendererConfig = {
if (process.env.NODE_ENV !== 'production') {
rendererConfig.plugins.push(
new webpack.DefinePlugin({
'__static': `"${path.join(__dirname, '../static').replace(/\\/g, '\\\\')}"`
'__static': `"${path.join(__dirname, '../static').replace(/\\/g, '\\\\')}"`,
'__lib': `"${path.join(__dirname, `../${config.DllFolder}`).replace(/\\/g, '\\\\')}"`
})
)
}
......@@ -202,7 +218,7 @@ if (process.env.NODE_ENV === 'production') {
rendererConfig.devtool = ''
rendererConfig.plugins.push(
new BabiliWebpackPlugin(),
new MinifyPlugin(),
new CopyWebpackPlugin([
{
from: path.join(__dirname, '../static'),
......
......@@ -5,7 +5,7 @@ process.env.BABEL_ENV = 'web'
const path = require('path')
const webpack = require('webpack')
const BabiliWebpackPlugin = require('babili-webpack-plugin')
const MinifyPlugin = require("babel-minify-webpack-plugin");
const CopyWebpackPlugin = require('copy-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
......@@ -144,7 +144,7 @@ if (process.env.NODE_ENV === 'production') {
webConfig.devtool = ''
webConfig.plugins.push(
new BabiliWebpackPlugin(),
new MinifyPlugin(),
new CopyWebpackPlugin([
{
from: path.join(__dirname, '../static'),
......
module.exports = {
NODE_ENV: '"development"',
BASE_API: '""'
BASE_API: '"http://127.0.0.1:25565"'
}
......
module.exports = {
build: {
env: require('./prod.env')
env: require('./prod.env'),
DisableF12: true
},
dev: {
env: require('./dev.env'),
removeElectronJunk: true
}
removeElectronJunk: true,
chineseLog: false,
port: 9080
},
UseStartupChart: true,
IsUseSysTitle: true,
DllFolder: '',
BuiltInServerPort: 25565
}
......
module.exports = {
NODE_ENV: '"production"',
BASE_API: '""'
BASE_API: '"http://127.0.0.1:25565"'
}
......
......@@ -62,7 +62,9 @@
"dependencies": {
"axios": "^0.19.2",
"date-fns": "^2.12.0",
"electron-updater": "^4.2.5",
"element-ui": "^2.13.0",
"express": "^4.17.1",
"js-cookie": "^2.2.1",
"nedb": "^1.8.0",
"nprogress": "^0.2.0",
......@@ -78,6 +80,7 @@
"babel-core": "^6.26.3",
"babel-eslint": "^8.2.3",
"babel-loader": "^7.1.5",
"babel-minify-webpack-plugin": "^0.3.1",
"babel-plugin-dynamic-import-webpack": "^1.1.0",
"babel-plugin-istanbul": "^5.2.0",
"babel-plugin-transform-runtime": "^6.23.0",
......@@ -108,6 +111,8 @@
"eslint-plugin-promise": "^3.8.0",
"eslint-plugin-standard": "^3.1.0",
"file-loader": "^6.0.0",
"happypack": "^5.0.1",
"hard-source-webpack-plugin": "^0.13.1",
"html-webpack-plugin": "^3.2.0",
"inject-loader": "^4.0.1",
"karma": "^2.0.2",
......@@ -123,6 +128,7 @@
"multispinner": "^0.2.1",
"node-loader": "^0.6.0",
"node-sass": "^4.13.1",
"portfinder": "^1.0.25",
"require-dir": "^1.2.0",
"sass-loader": "^8.0.2",
"spectron": "^3.8.0",
......
......@@ -16,6 +16,7 @@
<% if (!process.browser) { %>
<script>
if (process.env.NODE_ENV !== 'development') window.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
if (process.env.NODE_ENV !== 'development') window.__lib = require('path').join(__dirname,'..','..','..','..',`${require('../config/index.js').DllFolder}`).replace(/\\/g, '\\\\')
</script>
<% } %>
......
import { globalShortcut } from 'electron'
import config from '@config'
export default {
Disablef12 () {
if (process.env.NODE_ENV === 'production' && config.DisableF12) {
globalShortcut.register('f12', () => {
console.log('用户试图启动控制台')
})
}
}
}
// 这里是定义菜单的地方,详情请查看 https://electronjs.org/docs/api/menu
const { dialog } = require('electron')
const menu = [{
label: '文档操作',
submenu: [{
label: '撤销',
accelerator: 'CmdOrCtrl+Z',
role: 'undo'
const os = require('os')
const version = require('../../../package.json').version
const menu = [
{
label: '设置',
submenu: [{
label: '快速重启',
accelerator: 'F5',
role: 'reload'
}, {
label: '退出',
accelerator: 'CmdOrCtrl+F4',
role: 'close'
}]
}, {
label: '复制',
accelerator: 'CmdOrCtrl+C',
role: 'copy'
label: '帮助',
submenu: [{
label: '关于',
role: 'about',
click: function () {
info()
}
}]
}]
},
{
label: '设置',
submenu: [{
label: '快速重启',
accelerator: 'F5',
role: 'reload'
}, {
label: '退出',
accelerator: 'CmdOrCtrl+F4',
role: 'close'
}]
}, {
label: '帮助',
submenu: [{
label: '切换到开发者模式',
accelerator: 'CmdOrCtrl+I',
role: 'toggledevtools'
}, {
label: '关于',
role: 'about',
click: function () {
dialog.showMessageBox({
title: '关于',
type: 'info',
message: '存放显示这个的信息是在,src/main/menu.js中,请自行修改'
})
}
}]
}]
function info () {
dialog.showMessageBox({
title: '关于',
type: 'info',
message: 'electron-Vue框架',
detail: `版本信息:${version}\n引擎版本:${process.versions.v8}\n当前系统:${os.type()} ${os.arch()} ${os.release()}`,
noLink: true,
buttons: ['查看github', '确定']
})
}
export default menu
......
/**
* 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 */
// Install `electron-debug` with `devtron`
require('electron-debug')({ showDevTools: true })
// 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')
\ No newline at end of file
'use strict'
import {
app,
BrowserWindow,
Menu
} from 'electron'
import menuconfig from './menu'
import { app } from 'electron'
import initWindow from './services/windowManager'
import DisableButton from './config/DisableButton'
/**
* 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, '\\\\')
function onAppReady () {
initWindow()
DisableButton.Disablef12()
}
let mainWindow
const winURL = process.env.NODE_ENV === 'development'
? `http://localhost:9080`
: `file://${__dirname}/index.html`
function createWindow () {
/**
* Initial window options
*/
mainWindow = new BrowserWindow({
height: 563,
useContentSize: true,
width: 1000,
show: false,
backgroundColor: '#fffff',
titleBarStyle: 'hidden',
webPreferences: {
nodeIntegration: true,
webSecurity: false,
experimentalFeatures: true
}
// 隐藏边框
// frame: false,
})
mainWindow.once('ready-to-show', () => {
mainWindow.show()
})
const menu = Menu.buildFromTemplate(menuconfig)
Menu.setApplicationMenu(menu)
mainWindow.loadURL(winURL)
mainWindow.on('closed', () => {
mainWindow = null
})
}
app.on('ready', createWindow)
app.isReady() ? onAppReady() : app.on('ready', onAppReady)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (mainWindow === null) {
createWindow()
}
})
/**
* 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()
app.on('browser-window-created', () => {
console.log('window-created')
})
*/
......
/* eslint-disable prefer-promise-reject-errors */
import app from './server'
import http from 'http'
import config from '@config'
const port = config.BuiltInServerPort
app.set('port', port)
export default {
StatrServer () {
return new Promise((resolve, reject) => {
const server = http.createServer(app)
server.listen(port)
server.on('error', (error) => {
switch (error.code) {
case 'EACCES':
reject('权限不足内置服务器启动失败,请使用管理员权限运行。')
break
case 'EADDRINUSE':
reject('内置服务器端口已被占用,请检查。')
break
default:
reject(error)
}
})
server.on('listening', () => {
resolve('服务端运行中')
})
})
}
}
import express from 'express'
const app = express()
app.get('/message', (req, res) => {
res.send('这是来自node服务端的信息')
})
app.post('/message', (req, res) => {
if (req) {
res.send(req + '--来自node')
}
})
export default app
import { autoUpdater } from 'electron-updater'
import { ipcMain } from 'electron'
/**
* -1 检查更新失败 0 正在检查更新 1 检测到新版本,准备下载 2 未检测到新版本 3 下载中 4 下载完成
**/
function Message (mainWindow, type, data) {
const senddata = {
state: type,
msg: data
}
mainWindow.webContents.send('UpdateMsg', senddata)
}
export default {
Update (mainWindow) {
// 设置地址要和package中的一样
autoUpdater.setFeedURL('http://127.0.0.1:25565/')
// 当更新发生错误的时候触发。
autoUpdater.on('error', (err) => {
console.log('更新出现错误')
console.log(err.message)
if (err.message.includes('sha512 checksum mismatch')) {
Message(mainWindow, -1, 'sha512校验失败')
}
})
// 当开始检查更新的时候触发
autoUpdater.on('checking-for-update', (event, arg) => {
console.log('开始检查更新')
Message(mainWindow, 0)
})
// 发现可更新数据时
autoUpdater.on('update-available', (event, arg) => {
console.log('有更新')
Message(mainWindow, 1)
})
// 没有可更新数据时
autoUpdater.on('update-not-available', (event, arg) => {
console.log('没有更新')
Message(mainWindow, 2)
})
// 下载监听
autoUpdater.on('download-progress', (progressObj) => {
Message(mainWindow, 3, progressObj)
})
// 下载完成
autoUpdater.on('update-downloaded', () => {
console.log('下载完成')
Message(mainWindow, 4)
})
// 执行自动更新检查
ipcMain.on('check-update', () => {
autoUpdater.checkForUpdates().catch(err => {
console.log('网络连接问题', err)
})
})
// 渲染进程执行更新操作
ipcMain.on('confirm-update', () => {
autoUpdater.quitAndInstall()
})
}
}
/* eslint-disable no-case-declarations */
import { app, ipcMain, dialog } from 'electron'
import path from 'path'
import os from 'os'
// 版本以package.json为基准。
const version = require('../../../package.json').version
// 您的下载地址
const baseUrl = 'http://127.0.0.1:25565/'
var Sysarch = null
var defaultDownloadUrL = null
// 识别操作系统位数D
os.arch().includes('64') ? Sysarch = 'win64' : Sysarch = 'win32'
// 识别操作系统
// linux自己修改后缀名哦,我没有linux就没有测试了
if (os.platform().includes('win32')) {
defaultDownloadUrL = baseUrl + `electron_${version}_${Sysarch}.exe?${new Date().getTime()}`
} else if (os.platform().includes('linux')) {
defaultDownloadUrL = baseUrl + `electron_${version}_${Sysarch}?${new Date().getTime()}`
} else {
defaultDownloadUrL = baseUrl + `electron_${version}_mac.dmg?${new Date().getTime()}`
}
export default {
download (mainWindow) {
ipcMain.on('start-download', (event, msg) => {
mainWindow.webContents.downloadURL(msg.downloadUrL || defaultDownloadUrL)
event.reply('confirm-download', true)
mainWindow.webContents.session.on('will-download', (event, item, webContents) => {
// 将文件保存在系统的下载目录
const filePath = path.join(app.getPath('downloads'), item.getFilename())
// 自动保存
item.setSavePath(filePath)
// 下载进度
item.on('updated', (event, state) => {
switch (state) {
case 'progressing':
mainWindow.webContents.send('download-progress', (item.getReceivedBytes() / item.getTotalBytes() * 100).toFixed(0))
break
case 'interrupted ':
mainWindow.webContents.send('download-paused', true)
break
default:
break
}
})
// 下载完成或失败
item.once('done', (event, state) => {
switch (state) {
case 'completed':
const data = {
filePath
}
mainWindow.webContents.send('download-done', data)
break
case 'interrupted':
mainWindow.webContents.send('download-error', true)
dialog.showErrorBox('下载出错', '由于网络或其他未知原因导致客户端下载出错,请前往官网进行重新安装')
break
default:
break
}
})
})
})
}
}
import { ipcMain, dialog } from 'electron'
import Server from '../server/index'
export default {
Mainfunc (mainWindow, IsUseSysTitle) {
ipcMain.on('IsUseSysTitle', (event) => {
const data = IsUseSysTitle
event.reply('CisUseSysTitle', data)
})
ipcMain.on('windows-mini', () => {
mainWindow.minimize()
})
ipcMain.on('window-max', (event) => {
if (mainWindow.isMaximized()) {
event.reply('window-confirm', false)
mainWindow.restore()
} else {
event.reply('window-confirm', true)
mainWindow.maximize()
}
})
ipcMain.on('window-close', () => {
mainWindow.close()
})
ipcMain.on('open-messagebox', (event, arg) => {
dialog.showMessageBox(mainWindow, {
type: arg.type || 'info',
title: arg.title || '',
buttons: arg.buttons || [],
message: arg.message || '',
noLink: arg.noLink || true
}).then(res => {
event.reply('confirm-message', res)
})
})
ipcMain.on('open-errorbox', (event, arg) => {
dialog.showErrorBox(
arg.title,
arg.message
)
})
ipcMain.on('statr-server', (event, arg) => {
Server.StatrServer().then(res => {
event.reply('confirm-start', res)
}).catch(err => {
dialog.showErrorBox(
'错误',
err
)
})
})
}
}
import { BrowserWindow, Menu } from 'electron'
import menuconfig from '../config/menu'
import config from '@config'
import setIpc from './ipcMain'
import electronDevtoolsInstaller, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
import upload from './checkupdate'
import DownloadUpdate from './downloadFile'
import path from 'path'
/**
* Set `__static` path to static files in production
* https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html
*/
// 这个瓜皮全局变量只能在单个js中生效,而并不是整个主进程中
if (process.env.NODE_ENV !== 'development') {
global.__static = path.join(__dirname, '/static').replace(/\\/g, '\\\\')
}
// 将文件地址挪到这里
const winURL = process.env.NODE_ENV === 'development' ? `http://localhost:${process.env.PORT}` : `file://${__dirname}/index.html`
const loadingURL = process.env.NODE_ENV === 'development' ? `http://localhost:${process.env.PORT}/static/loader.html` : `file://${__static}/loader.html`
var loadWindow = null
var mainWindow = null
function createMainWindow () {
/**
* Initial window options
*/
mainWindow = new BrowserWindow({
height: 800,
useContentSize: true,
width: 1700,
minWidth: 1366,
show: false,
frame: config.IsUseSysTitle,
titleBarStyle: 'hidden',
webPreferences: {
nodeIntegration: true,
webSecurity: false,
// 如果是开发模式可以使用devTools
devTools: process.env.NODE_ENV === 'development',
// 在macos中启用橡皮动画
scrollBounce: process.platform === 'darwin'
}
})
// 这里设置只有开发环境才注入显示开发者模式
if (process.env.NODE_ENV === 'development') {
menuconfig.push({
label: '开发者设置',
submenu: [{
label: '切换到开发者模式',
accelerator: 'CmdOrCtrl+I',
role: 'toggledevtools'
}]
})
}
// 载入菜单
const menu = Menu.buildFromTemplate(menuconfig)
Menu.setApplicationMenu(menu)
mainWindow.loadURL(winURL)
setIpc.Mainfunc(mainWindow, config.IsUseSysTitle)
upload.Update(mainWindow)
DownloadUpdate.download(mainWindow)
if (process.env.NODE_ENV === 'development') {
mainWindow.webContents.once('dom-ready', () => {
mainWindow.show()
electronDevtoolsInstaller(VUEJS_DEVTOOLS)
.then((name) => console.log(`installed: ${name}`))
.catch(err => console.log('Unable to install `vue-devtools`: \n', err))
loadWindow.destroy()
})
mainWindow.webContents.openDevTools(true)
} else {
mainWindow.webContents.once('dom-ready', () => {
mainWindow.show()
loadWindow.destroy()
})
}
mainWindow.on('closed', () => {
mainWindow = null
})
}
function loadindWindow () {
loadWindow = new BrowserWindow({
width: 400,
height: 600,
frame: false,
backgroundColor: '#222',
transparent: true,
webPreferences: { experimentalFeatures: true }
})
loadWindow.loadURL(loadingURL)
loadWindow.show()
setTimeout(() => {
createMainWindow()
}, 2000)
loadWindow.on('closed', () => {
loadWindow = null
})
}
function initWindow () {
if (config.UseStartupChart) {
return loadindWindow()
} else {
return createMainWindow()
}
}
export default initWindow
<template>
<div id="app">
<router-view></router-view>
<c-header></c-header>
<transition name="fade" mode="out-in">
<router-view></router-view>
</transition>
</div>
</template>
<script>
export default {
}
import CHeader from "./components/title";
export default {
components: { CHeader }
};
</script>
<style>
/* CSS */
/* CSS */
</style>
......
......@@ -22,3 +22,10 @@ export function logout () {
method: 'post'
})
}
export function message () {
return request({
url: '/message',
method: 'get'
})
}
......
<template>
<div id="wrapper">
<img id="logo" src="~@/assets/logo.png" alt="electron-vue" />
<img id="logo" :src="logo" alt="electron-vue" />
<main>
<div class="left-side">
<span class="title">欢迎进入本框架</span>
......@@ -22,15 +22,39 @@
<el-button type="primary" round @click="setdata">写入数据</el-button>
<el-button type="primary" round @click="getdata">读取数据</el-button>
<el-button type="primary" round @click="deledata">清除所有数据</el-button>
<el-button type="primary" round @click="CheckUpdate('one')">检查更新</el-button>
</div>
<div class="doc">
<el-button type="primary" round @click="CheckUpdate('two')">检查更新(第二种方法)</el-button>
<el-button type="primary" round @click="StartServer">启动内置服务端</el-button>
<el-button type="primary" round @click="getMessage">查看消息</el-button>
</div>
</div>
</main>
<el-dialog
title="进度"
:visible.sync="dialogVisible"
:before-close="handleClose"
center
width="14%"
top="45vh"
>
<div class="conten">
<el-progress
type="dashboard"
:percentage="percentage"
:color="colors"
:status="progressStaus"
></el-progress>
</div>
</el-dialog>
</div>
</template>
<script>
import SystemInformation from "./LandingPage/SystemInformation";
import api from "../tools/dialog";
import ipcApi from "../utils/ipcRenderer";
import { message } from "@/api/login";
export default {
name: "landing-page",
components: { SystemInformation },
......@@ -40,12 +64,44 @@ export default {
name: "yyy",
age: "12"
},
textarray: []
logo: require("@/assets/logo.png"),
textarray: [],
percentage: 0,
colors: [
{ color: "#f56c6c", percentage: 20 },
{ color: "#e6a23c", percentage: 40 },
{ color: "#6f7ad3", percentage: 60 },
{ color: "#1989fa", percentage: 80 },
{ color: "#5cb87a", percentage: 100 }
],
dialogVisible: false,
progressStaus: null,
filePath: ""
}),
created() {
console.log(__lib);
},
methods: {
getMessage() {
message().then(res => {
this.$alert(res.data, "提示", {
confirmButtonText: "确定"
});
});
},
StartServer() {
ipcApi.send("statr-server");
ipcApi.on("confirm-start", (event, arg) => {
console.log(arg);
this.$message({
type: "success",
message: arg
});
});
},
// 获取electron方法
open() {
console.log(this.$store);
console.log(this.$electron);
},
// 设置数据库的数据
setdata() {
......@@ -67,28 +123,138 @@ export default {
},
// 清空数据库的数据
deledata() {
// dialog为electron实例,data则是显示需要的参数,fun是需要执行的函数,此选项不是为必选的
const dialog = this.$electron.remote.dialog;
// data则是显示需要的参数
const data = {
title: "清除数据",
buttons: ["OK", "Cancel"],
buttons: ["确定了!", "才不要,我手滑了"],
noLink: true,
message: "此操作会清空本地数据库中的所有数据,是否继续?"
};
const fun = this.$db.deleall({ name: "yyy" });
api.MessageBox(dialog, data, fun).then(res => {
this.getdata();
this.$message({
showClose: true,
message: "成功删除" + res + "条",
type: "success"
});
ipcApi.send("open-messagebox", data);
ipcApi.on("confirm-message", (event, arg) => {
console.log(arg);
if (arg.response === 0) {
this.$db.deleall({ name: "yyy" }).then(res => {
console.log(res);
if (res !== 0) {
this.getdata();
this.$message({
message: "成功删除" + res + "条",
type: "success"
});
} else {
let errormsg = {
title: "错误",
message: "已经没有数据可以被删除!"
};
ipcApi.send("open-errorbox", errormsg);
}
});
}
});
// const data = {
// title:'发生致命错误',
// message:'?'
// }
// api.ErrorMessageBox(dialog,data)
},
CheckUpdate(data) {
switch (data) {
case "one":
const dialog = this.$electron.remote.dialog;
ipcApi.send("check-update");
console.log("启动检查");
ipcApi.on("UpdateMsg", (event, data) => {
console.log(data);
switch (data.state) {
case -1:
const msgdata = {
title: data.msg
};
api.MessageBox(dialog, msgdata);
break;
case 0:
this.$message("正在检查更新");
break;
case 1:
this.$message({
type: "success",
message: "已检查到新版本,开始下载"
});
this.dialogVisible = true;
break;
case 2:
this.$message({ type: "success", message: "无新版本" });
break;
case 3:
this.percentage = data.msg.percent.toFixed(1);
break;
case 4:
this.progressStaus = "success";
this.$alert("更新下载完成!", "提示", {
confirmButtonText: "确定",
callback: action => {
ipcApi.send("confirm-update");
}
});
break;
default:
break;
}
});
break;
case "two":
console.log(111);
ipcApi.send("start-download");
ipcApi.on("confirm-download", (event, arg) => {
if (arg) {
this.dialogVisible = true;
}
});
ipcApi.on("download-progress", (event, arg) => {
this.percentage = Number(arg);
});
ipcApi.on("download-error", (event, arg) => {
if (arg) {
this.progressStaus = "exception";
this.percentage = 40;
this.colors = "#d81e06";
}
});
ipcApi.on("download-paused", (event, arg) => {
if (arg) {
this.progressStaus = "warning";
this.$alert("下载由于未知原因被中断!", "提示", {
confirmButtonText: "重试",
callback: action => {
ipcApi.send("satrt-download");
}
});
}
});
ipcApi.on("download-done", (event, age) => {
this.filePath = age.filePath;
this.progressStaus = "success";
this.$alert("更新下载完成!", "提示", {
confirmButtonText: "确定",
callback: action => {
this.$electron.shell.openItem(this.filePath);
}
});
});
break;
default:
break;
}
},
handleClose() {
this.dialogVisible = false;
}
},
destroyed() {
ipcApi.remove("confirm-message");
ipcApi.remove("download-done");
ipcApi.remove("download-paused");
ipcApi.remove("confirm-download");
ipcApi.remove("download-progress");
ipcApi.remove("download-error");
}
};
</script>
......@@ -105,8 +271,6 @@ body {
}
#wrapper {
background-color: #d1d1d1ab;
height: 93vh;
padding: 60px 80px;
}
......@@ -147,9 +311,14 @@ main > div {
font-size: 18px;
margin-bottom: 10px;
}
.doc {
margin-bottom: 20px;
}
.doc p {
color: black;
margin-bottom: 10px;
}
.conten {
text-align: center;
}
</style>
\ No newline at end of file
......
......@@ -26,6 +26,10 @@
<div class="name">所运行的系统:</div>
<div class="value">{{ platform }}</div>
</div>
<div class="item">
<div class="name">所运行的系统:</div>
<div class="value">{{ arch }}位</div>
</div>
</div>
</div>
</template>
......@@ -39,6 +43,7 @@
node: process.versions.node,
path: this.$route.path,
platform: require('os').platform(),
arch:require('os').arch(),
vue: require('vue/package.json').version
}
},
......
......@@ -15,10 +15,10 @@
:show-file-list="true"
:on-remove="handleRemove"
:on-success="handleSuccess"
:before-upload="beforeUpload"
:on-error="handleError"
:data="picPostData"
class="editor-slide-upload"
action="https://up-z2.qiniup.com/"
action="https://jsonplaceholder.typicode.com/post/"
list-type="picture-card"
:limit="5"
>
......@@ -31,8 +31,7 @@
</template>
<script>
// import { getToken } from 'api/qiniu'
import { checkPic } from "@util/picUtil.js";
export default {
name: "EditorSlideUpload",
......@@ -93,42 +92,8 @@ export default {
}
}
},
beforeUpload(file) {
const _self = this;
const _URL = window.URL || window.webkitURL;
const fileName = file.uid;
this.listObj[fileName] = {};
return new Promise((resolve, reject) => {
let Sync = async () => {
try {
let picKey = await checkPic(file, this.fileList.length, 1);
if (picKey) {
let token = await this.getRequest(
"/qiniu/serveGetQiniuUpToken?key=" + picKey
);
console.log("picKey---", picKey, token);
this.picPostData = token;
const img = new Image();
img.src = _URL.createObjectURL(file);
img.onload = function() {
_self.listObj[fileName] = {
hasSuccess: false,
uid: file.uid,
width: this.width,
height: this.height
};
};
resolve(true);
} else {
reject(false);
this.listObj = {};
}
} catch (error) {
reject(false);
}
};
Sync();
});
handleError(err){
this.alert(err)
}
}
};
......
<!-- -->
<template>
<div class="window-title" v-if="!IsUseSysTitle&&isMac">
<!-- 软件logo预留位置 -->
<div style="-webkit-app-region: drag;" class="logo">
<svg-icon icon-class="electron-logo"></svg-icon>
</div>
<!-- 菜单栏位置 -->
<div></div>
<!-- 中间标题位置 -->
<div style="-webkit-app-region: drag;" class="title"></div>
<div class="controls-container">
<div class="windows-icon-bg" @click="Mini">
<svg-icon icon-class="mini" class-name="icon-size"></svg-icon>
</div>
<div class="windows-icon-bg" @click="MixOrReduction">
<svg-icon v-if="mix" icon-class="reduction" class-name="icon-size"></svg-icon>
<svg-icon v-else icon-class="mix" class-name="icon-size"></svg-icon>
</div>
<div class="windows-icon-bg close-icon" @click="Close">
<svg-icon icon-class="close" class-name="icon-size"></svg-icon>
</div>
</div>
</div>
</template>
<script>
import ipcApi from "@/utils/ipcRenderer";
export default {
data: () => ({
mix: false,
IsUseSysTitle: false,
isMac:process.platform !== 'darwin'
}),
components: {},
created() {
ipcApi.send("IsUseSysTitle");
ipcApi.on("CisUseSysTitle", (event, arg) => (this.IsUseSysTitle = arg));
},
mounted() {},
methods: {
Mini() {
ipcApi.send("windows-mini");
},
MixOrReduction() {
ipcApi.send("window-max");
ipcApi.on("window-confirm", (event, arg) => (this.mix = arg));
},
Close() {
ipcApi.send("window-close");
}
}
};
</script>
<style rel='stylesheet/scss' lang='scss' scoped>
.window-title {
width: 100%;
height: 30px;
line-height: 30px;
background-color: #ffffff;
display: flex;
-webkit-app-region: drag;
position: fixed;
top: 0;
z-index: 99999;
.title {
text-align: center;
}
.logo{
margin-left: 20px;
}
.controls-container {
display: flex;
flex-grow: 0;
flex-shrink: 0;
text-align: center;
position: relative;
z-index: 3000;
-webkit-app-region: no-drag;
height: 100%;
width: 138px;
margin-left: auto;
.windows-icon-bg {
display: inline-block;
-webkit-app-region: no-drag;
height: 100%;
width: 33.34%;
color: rgba(129, 129, 129, 0.6);
.icon-size {
width: 12px;
height: 15px;
}
}
.windows-icon-bg:hover {
background-color: rgba(182, 182, 182, 0.2);
color: #333;
}
.close-icon:hover {
background-color: rgba(232, 17, 35, 0.9);
color: #fff;
}
}
}
</style>
\ No newline at end of file
import Vue from 'vue'
Vue.config.errorHandler = function (err, vm, info) {
Vue.nextTick(() => {
if (process.env.NODE_ENV === 'development') {
console.group('%c >>>>>> 错误信息 >>>>>>', 'color:red')
console.log(`%c ${info}`, 'color:blue')
console.groupEnd()
console.group('%c >>>>>> 发生错误的Vue 实例对象 >>>>>>', 'color:green')
console.log(vm)
console.groupEnd()
console.group('%c >>>>>> 发生错误的原因及位置 >>>>>>', 'color:red')
console.error(err)
console.groupEnd()
}
})
}
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width='11' height='11' viewBox='0 0 11 11' class="icon" xmlns='http://www.w3.org/2000/svg'><path d='M6.279 5.5L11 10.221l-.779.779L5.5 6.279.779 11 0 10.221 4.721 5.5 0 .779.779 0 5.5 4.721 10.221 0 11 .779 6.279 5.5z'/></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1577517047047" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6202" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M512 128q69.675 0 135.51 21.163t115.498 54.997 93.483 74.837 73.685 82.006 51.67 74.837 32.17 54.827L1024 512q-2.347 4.992-6.315 13.483T998.87 560.17t-31.658 51.669-44.331 59.99-56.832 64.34-69.504 60.16-82.347 51.5-94.848 34.687T512 896q-69.675 0-135.51-21.163t-115.498-54.826-93.483-74.326-73.685-81.493-51.67-74.496-32.17-54.997L0 513.707q2.347-4.992 6.315-13.483t18.816-34.816 31.658-51.84 44.331-60.33 56.832-64.683 69.504-60.331 82.347-51.84 94.848-34.816T512 128.085z m0 85.333q-46.677 0-91.648 12.331t-81.152 31.83-70.656 47.146-59.648 54.485-48.853 57.686-37.675 52.821-26.325 43.99q12.33 21.674 26.325 43.52t37.675 52.351 48.853 57.003 59.648 53.845T339.2 767.02t81.152 31.488T512 810.667t91.648-12.331 81.152-31.659 70.656-46.848 59.648-54.186 48.853-57.344 37.675-52.651T927.957 512q-12.33-21.675-26.325-43.648t-37.675-52.65-48.853-57.345-59.648-54.186-70.656-46.848-81.152-31.659T512 213.334z m0 128q70.656 0 120.661 50.006T682.667 512 632.66 632.661 512 682.667 391.339 632.66 341.333 512t50.006-120.661T512 341.333z m0 85.334q-35.328 0-60.33 25.002T426.666 512t25.002 60.33T512 597.334t60.33-25.002T597.334 512t-25.002-60.33T512 426.666z" p-id="6203"></path></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1577518173588" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6318" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M512 128q69.675 0 135.51 21.163t115.498 54.997 93.483 74.837 73.685 82.006 51.67 74.837 32.17 54.827L1024 512q-2.347 4.992-6.315 13.483T998.87 560.17t-31.658 51.669-44.331 59.99-56.832 64.34-69.504 60.16-82.347 51.5-94.848 34.687T512 896q-69.675 0-135.51-21.163t-115.498-54.826-93.483-74.326-73.685-81.493-51.67-74.496-32.17-54.997L0 513.707q2.347-4.992 6.315-13.483t18.816-34.816 31.658-51.84 44.331-60.33 56.832-64.683 69.504-60.331 82.347-51.84 94.848-34.816T512 128.085z m0 85.333q-46.677 0-91.648 12.331t-81.152 31.83-70.656 47.146-59.648 54.485-48.853 57.686-37.675 52.821-26.325 43.99q12.33 21.674 26.325 43.52t37.675 52.351 48.853 57.003 59.648 53.845T339.2 767.02t81.152 31.488T512 810.667t91.648-12.331 81.152-31.659 70.656-46.848 59.648-54.186 48.853-57.344 37.675-52.651T927.957 512q-12.33-21.675-26.325-43.648t-37.675-52.65-48.853-57.345-59.648-54.186-70.656-46.848-81.152-31.659T512 213.334z m0 128q70.656 0 120.661 50.006T682.667 512 632.66 632.661 512 682.667 391.339 632.66 341.333 512t50.006-120.661T512 341.333z m0 85.334q-35.328 0-60.33 25.002T426.666 512t25.002 60.33T512 597.334t60.33-25.002T597.334 512t-25.002-60.33T512 426.666z" p-id="6319"></path></svg>
\ No newline at end of file
......
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width='11' height='11' viewBox='0 0 11 11' class='icon' xmlns='http://www.w3.org/2000/svg'><path d='M11 4.399V5.5H0V4.399h11z'/></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width='11' height='11' viewBox='0 0 11 11' class='icon' xmlns='http://www.w3.org/2000/svg'><path d='M11 0v11H0V0h11zM9.899 1.101H1.1V9.9h8.8V1.1z'/></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width='11' height='11' viewBox='0 0 11 11' class="icon" xmlns='http://www.w3.org/2000/svg'><path d='M11 8.798H8.798V11H0V2.202h2.202V0H11v8.798zm-3.298-5.5h-6.6v6.6h6.6v-6.6zM9.9 1.1H3.298v1.101h5.5v5.5h1.1v-6.6z'/></svg>
\ No newline at end of file
......@@ -62,6 +62,7 @@ export default {
this.timer = setInterval(() => {
this.set_time();
}, 60000);
console.log(this.userImage)
},
methods: {
toggleSideBar() {
......@@ -73,11 +74,11 @@ export default {
message: "退出成功",
type: "success"
});
location.reload(); // 为了重新实例化vue-router对象 避免bug
this.$router.push('/login')
});
},
set_time() {
this.time = format(new Date(), "YYYY/MM/DD HH:mm");
this.time = format(new Date(), "yyyy/MM/dd HH:mm");
}
},
computed: {
......
<template>
<div v-if="!item.hidden&&item.children" class="menu-wrapper">
<div
v-if="!item.hidden&&item.children"
class="menu-wrapper"
:class="collapse?``:`active-menu-wrapper`"
>
<div v-if="item.onlyShowfirst">
<router-link
v-if="OneShowingChild(item.children[0]) && !onlyOneChild.children&&!item.alwaysShow"
......@@ -88,6 +91,10 @@ export default {
basePath: {
type: String,
default: ""
},
collapse: {
type: Boolean,
required: true
}
},
data() {
......@@ -111,8 +118,7 @@ export default {
return false;
},
resolvePath(...paths) {
return this.basePath + "/" +paths[0]
// return path.resolve(this.basePath, ...paths);
return this.basePath + "/" + paths[0];
},
OneShowingChild(children) {
this.onlyOneChild = children;
......@@ -122,20 +128,12 @@ export default {
};
</script>
<style lang="scss" scoped>
@import "@/styles/color.scss";
.menu-wrapper {
/deep/ .el-menu-item,
.el-submenu__title {
height: 46px;
line-height: 46px;
}
/deep/ a {
background-color: #ffc248;
}
/deep/ .el-menu-item.is-active {
margin-left: 8px;
background-color: $Theme-color !important;
}
/deep/ .el-menu-item {
padding: 0 20px 0 12px;
}
......
......@@ -4,13 +4,10 @@
mode="vertical"
:show-timeout="200"
:default-active="$route.path"
background-color="#ffffff"
text-color="#666666"
:collapse="isCollapse"
active-text-color="#ffffff"
>
<Logo :collapse="isCollapse" />
<sidebar-item v-for="route in routes" :key="route.name" :item="route" :base-path="route.path"></sidebar-item>
<sidebar-item v-for="route in routes" :key="route.name" :item="route" :base-path="route.path" :collapse="isCollapse"></sidebar-item>
</el-menu>
</scroll-bar>
</template>
......
......@@ -41,6 +41,7 @@ export default {
}
.sidebar-logo-container {
box-shadow: 2px 0 6px rgba(0,21,41,.15);
position: relative;
width: 100%;
height: 61px;
......@@ -75,6 +76,7 @@ export default {
.collapse {
.sidebar-logo {
margin-right: 0px !important;
margin-left: 0px !important;
}
}
</style>
\ No newline at end of file
......
<template>
<div class="app-wrapper" :class="classObj">
<navbar></navbar>
<div class="container-set">
<sidebar class="sidebar-container"></sidebar>
<div class="main-container">
<app-main></app-main>
<div class="app-wrapper" :class="IsUseSysTitle?'UseSysTitle':'NoUseSysTitle'">
<div :class="classObj">
<navbar></navbar>
<div class="container-set">
<sidebar class="sidebar-container" :class="IsUseSysTitle?'UseSysTitle':'NoUseSysTitle'"></sidebar>
<div class="main-container">
<app-main></app-main>
</div>
</div>
</div>
</div>
......@@ -22,6 +24,9 @@ export default {
Navbar
},
mixins: [ResizeMixin],
data: () => ({
IsUseSysTitle: require("./../../../config").IsUseSysTitle
}),
computed: {
sidebar() {
return this.$store.state.app.sidebar;
......@@ -51,4 +56,10 @@ export default {
padding-top: 62px;
}
}
.UseSysTitle{
top:0px;
}
.NoUseSysTitle{
top:38px
}
</style>
......
......@@ -9,10 +9,13 @@ import db from './api/operationalData'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import './permission'
// 日志
import './error'
import './icons'
import '@/styles/index.scss'
if (!require('../../config').IsUseSysTitle) require('@/styles/custom-title.scss')
if (!process.env.IS_WEB) Vue.use(require('vue-electron'))
Vue.use(ElementUI)
......@@ -21,9 +24,11 @@ Vue.prototype.$db = db
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
const vue = new Vue({
components: { App },
router,
store,
template: '<App/>'
}).$mount('#app')
export default vue
......
/* eslint-disable no-tabs */
import router from './router'
import store from './store'
import NProgress from 'nprogress' // Progress 进度条
import 'nprogress/nprogress.css'// Progress 进度条样式
import { Message } from 'element-ui'
const whiteList = ['/login'] // 不重定向白名单
router.beforeEach((to, from, next) => {
NProgress.start()
if (store.getters.token) {
if (to.path === '/login') {
next({ path: '/' })
NProgress.done() // if current page is dashboard will not trigger afterEach hook, so manually handle it
} else {
if (store.getters.roles.length === 0) {
store.dispatch('GetInfo').then(res => { // 拉取用户信息
......@@ -31,11 +27,8 @@ router.beforeEach((to, from, next) => {
next()
} else {
next('/login')
NProgress.done()
}
}
})
router.afterEach(() => {
NProgress.done() // 结束Progress
})
router.afterEach(() => {})
......
import Layout from '../layout'
import Layout from '@/layout'
const Login = () => import('@/views/login')
const Notfound = () => import('@/views/404')
/**
......@@ -44,12 +44,19 @@ export default [
{
path: '/form',
component: Layout,
meta: { title: '表单', icon: 'form' },
children: [
{
path: 'index',
name: 'Form',
component: () => import('@/views/form/index'),
meta: { title: '表单', icon: 'form' }
},
{
path: 'index2',
name: 'Form2',
component: () => import('@/views/form/index'),
meta: { title: '表单2', icon: 'form' }
}
]
},
......
/**
* 在这里则是state.文件名.状态名
*/
const getters = {
sidebar: state => state.app.sidebar,
device: state => state.app.device,
......
const template = {
state: {},
mutations: {},
actions: {}
}
export default template
$Theme-color:#651FFF;
\ No newline at end of file
......@@ -43,119 +43,3 @@
margin-top: 10px;
}
// 卡片上面的图标和标题样式
.info-set {
display: flex;
margin-bottom: 16px;
line-height: 22px;
.info-icon {
width: 8px;
height: 22px;
background: rgba(58, 127, 159, 1);
border-radius: 4px;
margin-right: 12px;
}
.info-title {
font-size: 16px;
font-weight: bold;
color: rgba(51, 51, 51, 1);
}
}
// 顶部的单选样式
.top-order {
flex: 1;
.order-group {
height: 38px;
display: flex;
align-items: center;
background-color: #3a7f9f;
width: 346px;
justify-content: center;
border-radius: 2px;
}
.order-group /deep/ .el-radio-group /deep/ .el-radio__input.is-checked .el-radio__inner {
border-color: #f2b931;
background: #f2b931;
}
.order-group /deep/ .el-radio-group /deep/ .el-radio__input.is-checked+.el-radio__label {
color: #f2b931;
}
.order-group /deep/ .el-radio__inner {
border: 1px solid #dcdfe6;
border-radius: 100%;
width: 14px;
height: 14px;
position: relative;
cursor: pointer;
display: inline-block;
box-sizing: border-box;
background-color: #3a7f9f;
}
.order-group /deep/ .el-radio {
color: #fff;
}
}
// 活动页顶部按钮
.top-active /deep/ .el-button {
background-color: #3a7f9f;
color: #fff;
height: 38px;
}
.top-active /deep/ .el-button:active {
background-color: #2c637c;
}
// 表格添加阴影
.table-control {
box-shadow: none;
}
// 表格选中颜色样式
.table-control /deep/ .el-checkbox__input.is-checked .el-checkbox__inner {
background-color: #3a7f9f;
}
.table-control /deep/ .el-checkbox__input.is-indeterminate .el-checkbox__inner {
background-color: #3a7f9f;
}
// 底部修改,保存,取消按钮的样式修改
.bottom-button {
width: 100%;
display: flex;
justify-content: flex-end;
}
.bottom-button /deep/ .el-button--primary {
background-color: #3a7f9f;
border-color: #3a7f9f;
height: 38px;
}
.bottom-button /deep/ .el-button--primary:active {
background-color: #255368;
border-color: #255368;
}
.bottom-button /deep/ .el-button--default {
height: 38px;
color: #3a7f9f;
}
.bottom-button /deep/ .el-button--default:hover {
background-color: rgba(58, 127, 159, 0.2);
}
.bottom-button /deep/ .el-button--default:active {
background-color: rgba(43, 94, 117, 0.3);
}
......
// 降低消息高度
// 当启用自定义标题时使用
.el-message {
top: 50px !important;
}
.el-notification {
top: 38px !important;
}
\ No newline at end of file
@import './color.scss';
//to reset element-ui default css
.el-upload {
input[type="file"] {
display: none !important;
}
}
.el-upload {
input[type="file"] {
display: none !important;
}
}
.el-upload__input {
display: none;
}
.el-upload__input {
display: none;
}
//暂时性解决diolag 问题 https://github.com/ElemeFE/element/issues/2461
.el-dialog {
transform: none;
left: 0;
position: relative;
margin: 0 auto;
}
//暂时性解决diolag 问题 https://github.com/ElemeFE/element/issues/2461
.el-dialog {
transform: none;
left: 0;
position: relative;
margin: 0 auto;
}
//element ui upload
.upload-container {
.el-upload {
width: 100%;
.el-upload-dragger {
width: 100%;
height: 200px;
}
}
}
//element ui upload
.upload-container {
.el-upload {
width: 100%;
.el-upload-dragger {
width: 100%;
height: 200px;
}
}
}
// 设置当选中时,popr的背景色被设置为白色的尴尬场景
.el-menu--vertical{
/deep/.el-menu--popup{
/deep/ .el-menu-item.is-active{
background-color: $Theme-color !important;
}
}
}
\ No newline at end of file
......
......@@ -3,17 +3,22 @@
@import './transition.scss';
@import './element-ui.scss';
@import './sidebar.scss';
@import './color.scss';
body {
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
margin: 0;
padding: 0;
}
html {
box-sizing: border-box;
::-webkit-scrollbar {
display: none;
}
}
*,
......@@ -22,7 +27,7 @@ html {
box-sizing: inherit;
}
div:focus{
div:focus {
outline: none;
}
......@@ -51,10 +56,10 @@ a:hover {
}
//main-container全局样式
.app-main{
.app-main {
min-height: 100%
}
.app-container {
padding: 20px;
}
}
\ No newline at end of file
......
......@@ -12,13 +12,12 @@
.horizontal-collapse-transition {
transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
}
transition: width .28s;
width: 256px !important;
height: 100%;
position: fixed;
font-size: 0px;
top: 0;
bottom: 0;
left: 0;
z-index: 1001;
......@@ -30,7 +29,7 @@
}
.svg-icon {
margin-right: 16px;
margin-left: 14px;
}
.el-menu {
......@@ -41,16 +40,16 @@
.hideSidebar {
.sidebar-container {
width: 36px !important;
width: 60px !important;
}
.navbar-header-fixed {
width: calc(100% - 36px);
width: calc(100% - 60px);
;
}
.main-container {
margin-left: 36px;
margin-left: 60px;
}
.submenu-title-noDropdown {
......@@ -84,11 +83,6 @@
.sidebar-container .nest-menu .el-submenu>.el-submenu__title,
.sidebar-container .el-submenu .el-menu-item {
min-width: 180px !important;
background-color: $Theme-color !important;
&:hover {
background-color: $Theme-color !important;
}
}
.el-menu--collapse .el-menu .el-submenu {
......
......@@ -2,4 +2,3 @@
$menuBg:#ffffff;
$subMenuBg:#1f2d3d;
$menuHover:#001528;
$Theme-color:#651FFF;
......
export default {
/**
* @export
* @param {Array} data
* @param {Object} dialog
* @param {function} fun
* @returns
* @feature 消息弹窗通用函数
*/
MessageBox (dialog, data, fun) {
return new Promise((resolve, reject) => {
dialog.showMessageBox({
type: 'info',
title: data.title,
buttons: data.buttons,
message: data.message
}, index => {
if (index === 0) {
let tempfun = async () => {
try {
resolve(await fun)
} catch (error) {
reject(error)
}
}
tempfun()
}
})
})
},
/**
* @export
* @param {Array} data
* @param {Object} dialog
* @returns
* @feature 错误消息弹窗
*/
ErrorMessageBox (dialog, data) {
return dialog.showErrorBox(
data.title,
data.message
)
}
}
/**
* @export
* @Author: Sky
* @Date: 2019-09-29 20:23:16
* @Last Modified by: Sky
* @Last Modified time: 2019-09-29 21:01:24
* @param {Object} option
* @returns
* @feature 对于普通的通知只需要加入传入title,body;而对于需要图标的还需要传入icon,当然它也接受一个图片链接,当用户点击通知之后,会返回一个true
* 由于是一个promise,请使用then接受
**/
export default {
DesktopMsg (option) {
const msgfunc = new window.Notification(option.title, option)
return new Promise((resolve) => {
msgfunc.onclick = () => {
resolve(true)
}
})
}
}
import $electron from 'electron'
export default {
send (data, arg, cb) {
$electron.ipcRenderer.send(data, arg, (event, arg) => cb(event, arg))
},
on (data, arg, cb) {
$electron.ipcRenderer.on(data, arg, (event, arg) => cb(event, arg))
},
remove (data) {
$electron.ipcRenderer.removeAllListeners(data)
}
}
......@@ -9,9 +9,7 @@
</div>
<div class="bullshit">
<div class="bullshit__oops">OOPS!</div>
<div class="bullshit__info">版权所有<a class="link-type" href="https://wallstreetcn.com" target='_blank'>华尔街见闻</a></div>
<div class="bullshit__headline">{{ message }}</div>
<div class="bullshit__info">请检查您输入的网址是否正确,请点击以下按钮返回主页或者发送错误报告</div>
<div class="bullshit__info">您似乎进到了一个次元世界,请点击以下按钮返回主页或者发送错误报告</div>
<a href="/" class="bullshit__return-home">返回首页</a>
</div>
</div>
......@@ -28,11 +26,6 @@ export default {
img_404,
img_404_cloud
}
},
computed: {
message() {
return '特朗普说这个页面你不能进......'
}
}
}
</script>
......
<template>
<div class="app-container">
<el-form ref="form" :model="form" label-width="120px">
<el-form-item label="Activity name">
<el-form-item label="活动名称">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="Activity zone">
<el-select v-model="form.region" placeholder="please select your zone">
<el-option label="Zone one" value="shanghai"></el-option>
<el-option label="Zone two" value="beijing"></el-option>
<el-form-item label="活动地点">
<el-select v-model="form.region" placeholder="请选择活动地点">
<el-option label="上海" value="上海"></el-option>
<el-option label="北京" value="北京"></el-option>
</el-select>
</el-form-item>
<el-form-item label="Activity time">
<el-form-item label="活动时间">
<el-col :span="11">
<el-date-picker type="date" placeholder="Pick a date" v-model="form.date1" style="width: 100%;"></el-date-picker>
<el-date-picker type="date" placeholder="选择时间" v-model="form.date1" style="width: 100%;"></el-date-picker>
</el-col>
<el-col class="line" :span="2">-</el-col>
<el-col :span="11">
<el-time-picker type="fixed-time" placeholder="Pick a time" v-model="form.date2" style="width: 100%;"></el-time-picker>
<el-time-picker
type="fixed-time"
placeholder="选择时间"
v-model="form.date2"
style="width: 100%;"
></el-time-picker>
</el-col>
</el-form-item>
<el-form-item label="Instant delivery">
<el-form-item label="即时交付">
<el-switch v-model="form.delivery"></el-switch>
</el-form-item>
<el-form-item label="Activity type">
<el-form-item label="额外选项">
<el-checkbox-group v-model="form.type">
<el-checkbox label="Online activities" name="type"></el-checkbox>
<el-checkbox label="Promotion activities" name="type"></el-checkbox>
<el-checkbox label="Offline activities" name="type"></el-checkbox>
<el-checkbox label="Simple brand exposure" name="type"></el-checkbox>
<el-checkbox label="在线活动" name="type"></el-checkbox>
<el-checkbox label="促销活动" name="type"></el-checkbox>
<el-checkbox label="线下活动" name="type"></el-checkbox>
<el-checkbox label="发布会活动" name="type"></el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="Resources">
<el-form-item label="资源选项">
<el-radio-group v-model="form.resource">
<el-radio label="Sponsor"></el-radio>
<el-radio label="Venue"></el-radio>
<el-radio label="需要赞助商"></el-radio>
<el-radio label="不需要赞助商"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="Activity form">
<el-input type="textarea" v-model="form.desc"></el-input>
<el-form-item label="活动详情">
<tinymce v-model="form.desc" :height="300" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">Create</el-button>
......@@ -48,37 +53,39 @@
</template>
<script>
import Tinymce from "@/components/Tinymce";
export default {
components: { Tinymce },
data() {
return {
form: {
name: '',
region: '',
date1: '',
date2: '',
name: "",
region: "",
date1: "",
date2: "",
delivery: false,
type: [],
resource: '',
desc: ''
resource: "",
desc: ""
}
}
};
},
methods: {
onSubmit() {
this.$message('submit!')
this.$message("submit!");
},
onCancel() {
this.$message({
message: 'cancel!',
type: 'warning'
})
message: "cancel!",
type: "warning"
});
}
}
}
};
</script>
<style scoped>
.line{
.line {
text-align: center;
}
</style>
......
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
html {
height: 100%;
min-height: 100%;
overflow: hidden;
}
html body {
background-size: 163px;
font: 14px/21px Monaco, sans-serif;
color: #999;
-webkit-font-smoothing: antialiased;
-webkit-text-size-adjust: 100%;
-moz-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
text-size-adjust: 100%;
height: 100%;
min-height: 100%;
margin: 0px;
}
html body h4 {
margin: 0;
}
.scene {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
background: #222;
position: relative;
}
.loader {
position: relative;
width: 15em;
height: 15em;
background: linear-gradient(-225deg, #ff3cac 0%, #562b7c 52%, #2b86c5 100%);
border-radius: 50%;
animation: spin 0.5s linear infinite;
}
span {
position: absolute;
width: 100%;
height: 100%;
border-radius: inherit;
background: inherit;
}
span:nth-child(1) {
filter: blur(5px);
}
span:nth-child(2) {
filter: blur(10px);
}
span:nth-child(3) {
filter: blur(25px);
}
span:nth-child(4) {
filter: blur(50px);
}
span::after {
position: absolute;
content: "";
top: 10px;
left: 10px;
right: 10px;
bottom: 10px;
background: #222;
border-radius: inherit;
}
.text {
position: absolute;
opacity: 0;
animation: breath 3s ease-in-out infinite;
}
@keyframes breath {
from {
opacity: 0.05;
}
50% {
opacity: 1;
}
to {
opacity: 0.05;
}
}
@keyframes spin {
to {
transform: rotate(1turn);
}
}
</style>
</head>
<body>
<div class="scene">
<div class="loader">
<span></span>
<span></span>
<span></span>
<span></span>
</div>
<div class="text">正在准备资源中...</div>
</div>
</body>
</html>
\ No newline at end of file