init
95
.babelrc
Normal file
@ -0,0 +1,95 @@
|
||||
{
|
||||
"comments": false,
|
||||
"env": {
|
||||
"renderer": {
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"modules": false,
|
||||
"useBuiltIns": "entry",
|
||||
"corejs": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
"@vue/babel-preset-jsx"
|
||||
]
|
||||
],
|
||||
"plugins": [
|
||||
"@babel/plugin-syntax-dynamic-import",
|
||||
"@babel/plugin-syntax-import-meta",
|
||||
"@babel/plugin-proposal-class-properties",
|
||||
"@babel/plugin-proposal-json-strings",
|
||||
[
|
||||
"@babel/plugin-proposal-decorators",
|
||||
{
|
||||
"legacy": true
|
||||
}
|
||||
],
|
||||
"@babel/plugin-proposal-function-sent",
|
||||
"@babel/plugin-proposal-export-namespace-from",
|
||||
"@babel/plugin-proposal-numeric-separator",
|
||||
"@babel/plugin-proposal-throw-expressions",
|
||||
"@babel/plugin-proposal-export-default-from",
|
||||
"@babel/plugin-proposal-logical-assignment-operators",
|
||||
"@babel/plugin-proposal-optional-chaining",
|
||||
[
|
||||
"@babel/plugin-proposal-pipeline-operator",
|
||||
{
|
||||
"proposal": "minimal"
|
||||
}
|
||||
],
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator",
|
||||
"@babel/plugin-proposal-do-expressions",
|
||||
"@babel/plugin-proposal-function-bind"
|
||||
]
|
||||
},
|
||||
"web": {
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"modules": false,
|
||||
"useBuiltIns": "entry",
|
||||
"corejs": 3
|
||||
}
|
||||
],
|
||||
[
|
||||
"@vue/babel-preset-jsx"
|
||||
]
|
||||
],
|
||||
"plugins": [
|
||||
"@babel/plugin-syntax-dynamic-import",
|
||||
"@babel/plugin-syntax-import-meta",
|
||||
"@babel/plugin-proposal-class-properties",
|
||||
"@babel/plugin-proposal-json-strings",
|
||||
[
|
||||
"@babel/plugin-proposal-decorators",
|
||||
{
|
||||
"legacy": true
|
||||
}
|
||||
],
|
||||
"@babel/plugin-proposal-function-sent",
|
||||
"@babel/plugin-proposal-export-namespace-from",
|
||||
"@babel/plugin-proposal-numeric-separator",
|
||||
"@babel/plugin-proposal-throw-expressions",
|
||||
"@babel/plugin-proposal-export-default-from",
|
||||
"@babel/plugin-proposal-logical-assignment-operators",
|
||||
"@babel/plugin-proposal-optional-chaining",
|
||||
[
|
||||
"@babel/plugin-proposal-pipeline-operator",
|
||||
{
|
||||
"proposal": "minimal"
|
||||
}
|
||||
],
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator",
|
||||
"@babel/plugin-proposal-do-expressions",
|
||||
"@babel/plugin-proposal-function-bind"
|
||||
]
|
||||
}
|
||||
},
|
||||
"plugins": [
|
||||
"@babel/transform-runtime",
|
||||
"@babel/plugin-syntax-dynamic-import"
|
||||
]
|
||||
}
|
122
.electron-vue/build.js
Normal file
@ -0,0 +1,122 @@
|
||||
'use strict'
|
||||
process.env.NODE_ENV = 'production'
|
||||
const { say } = require('cfonts')
|
||||
const chalk = require('chalk')
|
||||
const del = require('del')
|
||||
const webpack = require('webpack')
|
||||
const { Listr } = require('listr2')
|
||||
|
||||
|
||||
const mainConfig = require('./webpack.main.config')
|
||||
const rendererConfig = require('./webpack.renderer.config')
|
||||
|
||||
const doneLog = chalk.bgGreen.white(' DONE ') + ' '
|
||||
const errorLog = chalk.bgRed.white(' ERROR ') + ' '
|
||||
const okayLog = chalk.bgBlue.white(' OKAY ') + ' '
|
||||
const isCI = process.env.CI || false
|
||||
|
||||
if (process.env.BUILD_TARGET === 'web') web()
|
||||
else build()
|
||||
|
||||
function clean() {
|
||||
del.sync(['dist/electron/*', 'build/*', '!build/icons', '!build/lib', '!build/lib/electron-build.*', '!build/icons/icon.*'])
|
||||
console.log(`\n${doneLog}clear done`)
|
||||
if (process.env.BUILD_TARGET === 'onlyClean') process.exit()
|
||||
}
|
||||
|
||||
function build() {
|
||||
greeting()
|
||||
if (process.env.BUILD_TARGET === 'clean' || process.env.BUILD_TARGET === 'onlyClean') clean()
|
||||
const tasksLister = new Listr([
|
||||
{
|
||||
title: 'building main process',
|
||||
task: async (_, tasks) => {
|
||||
try {
|
||||
await pack(mainConfig)
|
||||
} catch (error) {
|
||||
console.error(`\n${error}\n`)
|
||||
console.log(`\n ${errorLog}failed to build main process`)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "building renderer process",
|
||||
task: async (_, tasks) => {
|
||||
try {
|
||||
await pack(rendererConfig)
|
||||
tasks.output = `${okayLog}take it away ${chalk.yellow('`electron-builder`')}\n`
|
||||
} catch (error) {
|
||||
console.error(`\n${error}\n`)
|
||||
console.log(`\n ${errorLog}failed to build renderer process`)
|
||||
process.exit(1)
|
||||
}
|
||||
},
|
||||
options: { persistentOutput: true }
|
||||
}
|
||||
], {
|
||||
exitOnError: true
|
||||
})
|
||||
tasksLister.run()
|
||||
}
|
||||
|
||||
function pack(config) {
|
||||
return new Promise((resolve, reject) => {
|
||||
config.mode = 'production'
|
||||
webpack(config, (err, stats) => {
|
||||
if (err) reject(err.stack || err)
|
||||
else if (stats.hasErrors()) {
|
||||
let err = ''
|
||||
|
||||
stats.toString({
|
||||
chunks: false,
|
||||
colors: true
|
||||
})
|
||||
.split(/\r?\n/)
|
||||
.forEach(line => {
|
||||
err += ` ${line}\n`
|
||||
})
|
||||
|
||||
reject(err)
|
||||
} else {
|
||||
resolve(stats.toString({
|
||||
chunks: false,
|
||||
colors: true
|
||||
}))
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function web() {
|
||||
del.sync(['dist/web/*', '!.gitkeep'])
|
||||
rendererConfig.mode = 'production'
|
||||
webpack(rendererConfig, (err, stats) => {
|
||||
if (err || stats.hasErrors()) console.log(err)
|
||||
|
||||
console.log(stats.toString({
|
||||
chunks: false,
|
||||
colors: true
|
||||
}))
|
||||
|
||||
process.exit()
|
||||
})
|
||||
}
|
||||
|
||||
function greeting() {
|
||||
const cols = process.stdout.columns
|
||||
let text = ''
|
||||
|
||||
if (cols > 85) text = `let's-build`
|
||||
else if (cols > 60) text = `let's-|build`
|
||||
else text = false
|
||||
|
||||
if (text && !isCI) {
|
||||
say(text, {
|
||||
colors: ['yellow'],
|
||||
font: 'simple3d',
|
||||
space: false
|
||||
})
|
||||
} else console.log(chalk.yellow.bold(`\n let's-build`))
|
||||
console.log()
|
||||
}
|
210
.electron-vue/dev-runner.js
Normal file
@ -0,0 +1,210 @@
|
||||
'use strict'
|
||||
|
||||
process.env.NODE_ENV = 'development'
|
||||
|
||||
const chalk = require('chalk')
|
||||
const electron = require('electron')
|
||||
const path = require('path')
|
||||
const { say } = require('cfonts')
|
||||
const { spawn } = require('child_process')
|
||||
const config = require('../config')
|
||||
const webpack = require('webpack')
|
||||
const WebpackDevServer = require('webpack-dev-server')
|
||||
const Portfinder = require("portfinder")
|
||||
|
||||
const mainConfig = require('./webpack.main.config')
|
||||
const rendererConfig = require('./webpack.renderer.config')
|
||||
|
||||
let electronProcess = null
|
||||
let manualRestart = false
|
||||
|
||||
function logStats(proc, data) {
|
||||
let log = ''
|
||||
|
||||
log += chalk.yellow.bold(`┏ ${proc} ${config.dev.chineseLog ? '编译过程' : 'Process'} ${new Array((19 - proc.length) + 1).join('-')}`)
|
||||
log += '\n\n'
|
||||
|
||||
if (typeof data === 'object') {
|
||||
data.toString({
|
||||
colors: true,
|
||||
chunks: false
|
||||
}).split(/\r?\n/).forEach(line => {
|
||||
log += ' ' + line + '\n'
|
||||
})
|
||||
} else {
|
||||
log += ` ${data}\n`
|
||||
}
|
||||
|
||||
log += '\n' + chalk.yellow.bold(`┗ ${new Array(28 + 1).join('-')}`) + '\n'
|
||||
console.log(log)
|
||||
}
|
||||
|
||||
function removeJunk(chunk) {
|
||||
if (config.dev.removeElectronJunk) {
|
||||
// Example: 2018-08-10 22:48:42.866 Electron[90311:4883863] *** WARNING: Textured window <AtomNSWindow: 0x7fb75f68a770>
|
||||
if (/\d+-\d+-\d+ \d+:\d+:\d+\.\d+ Electron(?: Helper)?\[\d+:\d+] /.test(chunk)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Example: [90789:0810/225804.894349:ERROR:CONSOLE(105)] "Uncaught (in promise) Error: Could not instantiate: ProductRegistryImpl.Registry", source: chrome-devtools://devtools/bundled/inspector.js (105)
|
||||
if (/\[\d+:\d+\/|\d+\.\d+:ERROR:CONSOLE\(\d+\)\]/.test(chunk)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Example: ALSA lib confmisc.c:767:(parse_card) cannot find card '0'
|
||||
if (/ALSA lib [a-z]+\.c:\d+:\([a-z_]+\)/.test(chunk)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
function startRenderer() {
|
||||
return new Promise((resolve, reject) => {
|
||||
rendererConfig.mode = 'development'
|
||||
Portfinder.basePort = config.dev.port || 9080
|
||||
Portfinder.getPort((err, port) => {
|
||||
if (err) {
|
||||
reject("PortError:" + err)
|
||||
} else {
|
||||
const compiler = webpack(rendererConfig)
|
||||
|
||||
compiler.hooks.done.tap('done', stats => {
|
||||
logStats('Renderer', stats)
|
||||
})
|
||||
|
||||
const server = new WebpackDevServer(
|
||||
{
|
||||
port,
|
||||
static: {
|
||||
directory: path.join(__dirname, '..', 'static'),
|
||||
publicPath: '/static/',
|
||||
}
|
||||
},
|
||||
compiler
|
||||
)
|
||||
|
||||
process.env.PORT = port
|
||||
server.start().then(() => {
|
||||
resolve()
|
||||
})
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
function startMain() {
|
||||
return new Promise((resolve) => {
|
||||
mainConfig.mode = 'development'
|
||||
const compiler = webpack(mainConfig)
|
||||
|
||||
compiler.hooks.watchRun.tapAsync('watch-run', (compilation, done) => {
|
||||
logStats(`${config.dev.chineseLog ? '主进程' : 'Main'}`, chalk.white.bold(`${config.dev.chineseLog ? '正在处理资源文件...' : 'compiling...'}`))
|
||||
done()
|
||||
})
|
||||
|
||||
compiler.watch({}, (err, stats) => {
|
||||
if (err) {
|
||||
console.log(err)
|
||||
return
|
||||
}
|
||||
|
||||
logStats(`${config.dev.chineseLog ? '主进程' : 'Main'}`, stats)
|
||||
|
||||
if (electronProcess && electronProcess.kill) {
|
||||
manualRestart = true
|
||||
process.kill(electronProcess.pid)
|
||||
electronProcess = null
|
||||
startElectron()
|
||||
|
||||
setTimeout(() => {
|
||||
manualRestart = false
|
||||
}, 5000)
|
||||
}
|
||||
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function startElectron() {
|
||||
var args = [
|
||||
'--inspect=5858',
|
||||
path.join(__dirname, '../dist/electron/main.js')
|
||||
]
|
||||
|
||||
// detect yarn or npm and process commandline args accordingly
|
||||
if (process.env.npm_execpath.endsWith('yarn.js')) {
|
||||
args = args.concat(process.argv.slice(3))
|
||||
} else if (process.env.npm_execpath.endsWith('npm-cli.js')) {
|
||||
args = args.concat(process.argv.slice(2))
|
||||
}
|
||||
|
||||
electronProcess = spawn(electron, args)
|
||||
|
||||
electronProcess.stdout.on('data', data => {
|
||||
electronLog(removeJunk(data), 'blue')
|
||||
})
|
||||
electronProcess.stderr.on('data', data => {
|
||||
electronLog(removeJunk(data), 'red')
|
||||
})
|
||||
|
||||
electronProcess.on('close', () => {
|
||||
if (!manualRestart) process.exit()
|
||||
})
|
||||
}
|
||||
|
||||
function electronLog(data, color) {
|
||||
if (data) {
|
||||
let log = ''
|
||||
data = data.toString().split(/\r?\n/)
|
||||
data.forEach(line => {
|
||||
log += ` ${line}\n`
|
||||
})
|
||||
console.log(
|
||||
chalk[color].bold(`┏ ${config.dev.chineseLog ? '主程序日志' : 'Electron'} -------------------`) +
|
||||
'\n\n' +
|
||||
log +
|
||||
chalk[color].bold('┗ ----------------------------') +
|
||||
'\n'
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function greeting() {
|
||||
const cols = process.stdout.columns
|
||||
let text = ''
|
||||
|
||||
if (cols > 104) text = 'electron-vue'
|
||||
else if (cols > 76) text = 'electron-|vue'
|
||||
else text = false
|
||||
|
||||
if (text) {
|
||||
say(text, {
|
||||
colors: ['yellow'],
|
||||
font: 'simple3d',
|
||||
space: false
|
||||
})
|
||||
} else console.log(chalk.yellow.bold('\n electron-vue'))
|
||||
console.log(chalk.blue(`${config.dev.chineseLog ? ' 准备启动...' : ' getting ready...'}`) + '\n')
|
||||
}
|
||||
|
||||
async function init() {
|
||||
greeting()
|
||||
|
||||
try {
|
||||
await startRenderer()
|
||||
await startMain()
|
||||
await startElectron()
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
init()
|
122
.electron-vue/hot-updater.js
Normal file
@ -0,0 +1,122 @@
|
||||
/**
|
||||
* power by biuuu
|
||||
*/
|
||||
|
||||
const chalk = require("chalk");
|
||||
const { join } = require('path')
|
||||
const crypto = require('crypto')
|
||||
const AdmZip = require('adm-zip')
|
||||
const packageFile = require('../package.json')
|
||||
const { build } = require("../config/index")
|
||||
const { platform } = require("os")
|
||||
const { ensureDir, emptyDir, copy, outputJSON, remove, stat, readFile } = require("fs-extra");
|
||||
|
||||
const platformName = platform().includes('win32') ? 'win' : platform().includes('darwin') ? 'mac' : 'linux'
|
||||
const buildPath = join('.', 'build', `${platformName === 'mac' ? 'mac' : platformName + '-unpacked'}`)
|
||||
|
||||
const hash = (data, type = 'sha256') => {
|
||||
const hmac = crypto.createHmac(type, 'Sky')
|
||||
hmac.update(data)
|
||||
return hmac.digest('hex')
|
||||
}
|
||||
|
||||
const createZip = (filePath, dest) => {
|
||||
const zip = new AdmZip()
|
||||
zip.addLocalFolder(filePath)
|
||||
zip.toBuffer()
|
||||
zip.writeZip(dest)
|
||||
}
|
||||
|
||||
const start = async () => {
|
||||
console.log(chalk.green.bold(`\n Start packing`))
|
||||
|
||||
if (packageFile.build.asar) {
|
||||
console.log(
|
||||
"\n" +
|
||||
chalk.bgRed.white(" ERROR ") +
|
||||
" " +
|
||||
chalk.red("Please make sure the build.asar option in the Package.json file is set to false") +
|
||||
"\n"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (build.hotPublishConfigName === '') {
|
||||
console.log(
|
||||
"\n" +
|
||||
chalk.bgRed.white(" ERROR ") +
|
||||
" " +
|
||||
chalk.red("HotPublishConfigName is not set, which will cause the update to fail, please set it in the config/index.js \n")
|
||||
+ chalk.red.bold(`\n Packing failed \n`)
|
||||
);
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
stat(join(buildPath, 'resources', 'app'), async (err, stats) => {
|
||||
if (err) {
|
||||
console.log(
|
||||
"\n" +
|
||||
chalk.bgRed.white(" ERROR ") +
|
||||
" " +
|
||||
chalk.red("No resource files were found, please execute this command after the build command") +
|
||||
"\n"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const packResourcesPath = join('.', 'build', 'resources', 'dist');
|
||||
const packPackagePath = join('.', 'build', 'resources');
|
||||
const resourcesPath = join('.', 'dist');
|
||||
const appPath = join('.', 'build', 'resources');
|
||||
const name = "app.zip";
|
||||
const outputPath = join('.', 'build', 'update');
|
||||
const zipPath = join(outputPath, name);
|
||||
|
||||
await ensureDir(packResourcesPath);
|
||||
await emptyDir(packResourcesPath);
|
||||
await copy(resourcesPath, packResourcesPath);
|
||||
await outputJSON(join(packPackagePath, "package.json"), {
|
||||
name: packageFile.name,
|
||||
productName: packageFile.productName,
|
||||
version: packageFile.version,
|
||||
private: packageFile.private,
|
||||
description: packageFile.description,
|
||||
main: packageFile.main,
|
||||
author: packageFile.author,
|
||||
dependencies: packageFile.dependencies
|
||||
});
|
||||
await ensureDir(outputPath);
|
||||
await emptyDir(outputPath);
|
||||
createZip(appPath, zipPath);
|
||||
const buffer = await readFile(zipPath);
|
||||
const sha256 = hash(buffer);
|
||||
const hashName = sha256.slice(7, 12);
|
||||
await copy(zipPath, join(outputPath, `${hashName}.zip`));
|
||||
await remove(zipPath);
|
||||
await remove(appPath)
|
||||
await outputJSON(join(outputPath, `${build.hotPublishConfigName}.json`),
|
||||
{
|
||||
version: packageFile.version,
|
||||
name: `${hashName}.zip`,
|
||||
hash: sha256
|
||||
}
|
||||
);
|
||||
console.log(
|
||||
"\n" + chalk.bgGreen.white(" DONE ") + " " + "The resource file is packaged!\n"
|
||||
);
|
||||
console.log("File location: " + chalk.green(outputPath) + "\n");
|
||||
} catch (error) {
|
||||
console.log(
|
||||
"\n" +
|
||||
chalk.bgRed.white(" ERROR ") +
|
||||
" " +
|
||||
chalk.red(error.message || error) +
|
||||
"\n"
|
||||
);
|
||||
process.exit(1)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
start()
|
101
.electron-vue/utils.js
Normal file
@ -0,0 +1,101 @@
|
||||
'use strict'
|
||||
const MiniCssPlugin = require('mini-css-extract-plugin');
|
||||
const dotenv = require('dotenv')
|
||||
const { join } = require("path")
|
||||
const argv = require('minimist')(process.argv.slice(2));
|
||||
const rootResolve = (...pathSegments) => join(__dirname, '..', ...pathSegments)
|
||||
|
||||
function getEnv() {
|
||||
return argv['m']
|
||||
}
|
||||
function getEnvPath() {
|
||||
if (String(typeof getEnv()) === 'boolean' || String(typeof getEnv()) === 'undefined') {
|
||||
return rootResolve('env/.env')
|
||||
}
|
||||
return rootResolve(`env/${getEnv()}.env`)
|
||||
}
|
||||
function getConfig() {
|
||||
return dotenv.config({ path: getEnvPath() }).parsed
|
||||
}
|
||||
|
||||
// 获取环境
|
||||
exports.getEnv = getEnv()
|
||||
// 获取配置
|
||||
exports.getConfig = getConfig()
|
||||
|
||||
exports.cssLoaders = function (options) {
|
||||
options = options || {}
|
||||
const esbuildCss = {
|
||||
loader: 'esbuild-loader',
|
||||
options: {
|
||||
loader: 'css',
|
||||
minify: options.minifyCss
|
||||
}
|
||||
}
|
||||
|
||||
const cssLoader = {
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
sourceMap: options.sourceMap,
|
||||
esModule: false
|
||||
}
|
||||
}
|
||||
|
||||
const postcssLoader = {
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
sourceMap: options.sourceMap
|
||||
}
|
||||
}
|
||||
|
||||
// 这里就是生成loader和其对应的配置
|
||||
function generateLoaders(loader, loaderOptions) {
|
||||
const loaders = [cssLoader, postcssLoader, esbuildCss]
|
||||
|
||||
if (loader) {
|
||||
loaders.push({
|
||||
loader: loader + '-loader',
|
||||
options: Object.assign({}, loaderOptions, {
|
||||
sourceMap: options.sourceMap
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 当配置信息中开启此项时,启用css分离压缩
|
||||
// 这一项在生产环境时,是默认开启的
|
||||
if (options.extract) {
|
||||
return [MiniCssPlugin.loader].concat(loaders)
|
||||
} else {
|
||||
// 如果不开启则让vue-style-loader来处理
|
||||
return ['vue-style-loader'].concat(loaders)
|
||||
}
|
||||
}
|
||||
|
||||
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
|
||||
return {
|
||||
css: generateLoaders(),
|
||||
postcss: generateLoaders(),
|
||||
less: generateLoaders('less'),
|
||||
sass: generateLoaders('sass', { indentedSyntax: true }),
|
||||
scss: generateLoaders('sass'),
|
||||
stylus: generateLoaders('stylus'),
|
||||
styl: generateLoaders('stylus')
|
||||
}
|
||||
}
|
||||
|
||||
// 根据上面的函数遍历出来的各个css预处理器的loader进行最后的拼装
|
||||
exports.styleLoaders = function (options) {
|
||||
const output = []
|
||||
const loaders = exports.cssLoaders(options)
|
||||
|
||||
|
||||
for (const extension in loaders) {
|
||||
const loader = loaders[extension]
|
||||
output.push({
|
||||
test: new RegExp('\\.' + extension + '$'),
|
||||
use: loader
|
||||
})
|
||||
}
|
||||
|
||||
return output
|
||||
}
|
99
.electron-vue/webpack.main.config.js
Normal file
@ -0,0 +1,99 @@
|
||||
'use strict'
|
||||
|
||||
process.env.BABEL_ENV = 'main'
|
||||
|
||||
const path = require('path')
|
||||
const { dependencies } = require('../package.json')
|
||||
const webpack = require('webpack')
|
||||
const TerserPlugin = require('terser-webpack-plugin')
|
||||
const config = require('../config')
|
||||
const { getConfig } = require("./utils")
|
||||
|
||||
function resolve(dir) {
|
||||
return path.join(__dirname, '..', dir)
|
||||
}
|
||||
|
||||
let mainConfig = {
|
||||
infrastructureLogging: {
|
||||
level: 'warn'
|
||||
},
|
||||
entry: {
|
||||
main: path.join(__dirname, '../src/main/index.js')
|
||||
},
|
||||
externals: [
|
||||
...Object.keys(dependencies || {})
|
||||
],
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'esbuild-loader'
|
||||
},
|
||||
{
|
||||
test: /\.node$/,
|
||||
use: 'node-loader'
|
||||
}
|
||||
]
|
||||
},
|
||||
node: {
|
||||
__dirname: process.env.NODE_ENV !== 'production',
|
||||
__filename: process.env.NODE_ENV !== 'production'
|
||||
},
|
||||
output: {
|
||||
filename: '[name].js',
|
||||
libraryTarget: 'commonjs2',
|
||||
path: path.join(__dirname, '../dist/electron')
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.userConfig':JSON.stringify(getConfig)
|
||||
})
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@config': resolve('config'),
|
||||
},
|
||||
extensions: ['.js', '.json', '.node']
|
||||
},
|
||||
target: 'electron-main',
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust mainConfig for development settings
|
||||
*/
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
mainConfig.plugins.push(
|
||||
new webpack.DefinePlugin({
|
||||
'__static': `"${path.join(__dirname, '../static').replace(/\\/g, '\\\\')}"`,
|
||||
'process.env.libPath': `"${path.join(__dirname, `../${config.DllFolder}`).replace(/\\/g, '\\\\')}"`
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust mainConfig for production settings
|
||||
*/
|
||||
if (process.env.NODE_ENV === 'production' && config.build.cleanConsole) {
|
||||
mainConfig.optimization = {
|
||||
minimize: true,
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
terserOptions: {
|
||||
compress: {
|
||||
drop_console: true,
|
||||
drop_debugger: true,
|
||||
pure_funcs: ["console.log", "console.warn"]
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
]
|
||||
}
|
||||
mainConfig.plugins.push(
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': '"production"'
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
module.exports = mainConfig
|
219
.electron-vue/webpack.renderer.config.js
Normal file
@ -0,0 +1,219 @@
|
||||
'use strict'
|
||||
|
||||
const IsWeb = process.env.BUILD_TARGET === 'web'
|
||||
process.env.BABEL_ENV = IsWeb ? 'web' : 'renderer'
|
||||
|
||||
const path = require('path')
|
||||
const { dependencies } = require('../package.json')
|
||||
const webpack = require('webpack')
|
||||
const config = require('../config')
|
||||
const { styleLoaders } = require('./utils')
|
||||
|
||||
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 ESLintPlugin = require('eslint-webpack-plugin');
|
||||
const { VueLoaderPlugin } = require('vue-loader')
|
||||
const { getConfig } = require("./utils")
|
||||
|
||||
function resolve(dir) {
|
||||
return path.join(__dirname, '..', dir)
|
||||
}
|
||||
/**
|
||||
* List of node_modules to include in webpack bundle
|
||||
*
|
||||
* Required for specific packages like Vue UI libraries
|
||||
* that provide pure *.vue files that need compiling
|
||||
* https://simulatedgreg.gitbooks.io/electron-vue/content/en/webpack-configurations.html#white-listing-externals
|
||||
*/
|
||||
|
||||
let rendererConfig = {
|
||||
entry: IsWeb ? { web: path.join(__dirname, '../src/renderer/main.js') } : { renderer: resolve('src/renderer/main.js') },
|
||||
infrastructureLogging: { level: 'warn' },
|
||||
stats: 'none',
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.vue$/,
|
||||
loader: "vue-loader",
|
||||
options: {
|
||||
babelParserPlugins: [
|
||||
'jsx',
|
||||
'classProperties',
|
||||
'decorators-legacy'
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.jsx$/,
|
||||
loader: 'babel-loader',
|
||||
},
|
||||
{
|
||||
test: /\.html$/,
|
||||
use: 'vue-html-loader'
|
||||
},
|
||||
{
|
||||
test: /\.svg$/,
|
||||
loader: 'svg-sprite-loader',
|
||||
include: [resolve('src/renderer/icons')],
|
||||
options: {
|
||||
symbolId: 'icon-[name]'
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g|gif)(\?.*)?$/,
|
||||
type: "asset/resource",
|
||||
generator: {
|
||||
filename: 'imgs/[name]--[hash].[ext]'
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
|
||||
type: "asset/resource",
|
||||
generator: {
|
||||
filename: 'media/[name]--[hash].[ext]'
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
|
||||
type: "asset/resource",
|
||||
generator: {
|
||||
filename: 'fonts/[name]--[hash].[ext]'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
node: {
|
||||
__dirname: process.env.NODE_ENV !== 'production',
|
||||
__filename: process.env.NODE_ENV !== 'production'
|
||||
},
|
||||
plugins: [
|
||||
new VueLoaderPlugin(),
|
||||
new MiniCssExtractPlugin(),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.userConfig': JSON.stringify(getConfig),
|
||||
'process.env.IS_WEB': IsWeb
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'index.html',
|
||||
template: resolve('src/index.ejs'),
|
||||
minify: {
|
||||
collapseWhitespace: true,
|
||||
removeAttributeQuotes: true,
|
||||
removeComments: true,
|
||||
minifyJS: true,
|
||||
minifyCSS: true
|
||||
},
|
||||
templateParameters(compilation, assets, options) {
|
||||
return {
|
||||
compilation: compilation,
|
||||
webpack: compilation.getStats().toJson(),
|
||||
webpackConfig: compilation.options,
|
||||
htmlWebpackPlugin: {
|
||||
files: assets,
|
||||
options: options
|
||||
},
|
||||
process,
|
||||
};
|
||||
},
|
||||
nodeModules: false
|
||||
}),
|
||||
],
|
||||
output: {
|
||||
filename: '[name].js',
|
||||
path: IsWeb ? path.join(__dirname, '../dist/web') : path.join(__dirname, '../dist/electron')
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': resolve('src/renderer'),
|
||||
'vue$': 'vue/dist/vue.esm.js'
|
||||
},
|
||||
extensions: ['.js', '.vue', '.json', '.css', '.node']
|
||||
},
|
||||
target: IsWeb ? 'web' : 'electron-renderer'
|
||||
}
|
||||
// 将css相关得loader抽取出来
|
||||
rendererConfig.module.rules = rendererConfig.module.rules.concat(styleLoaders({ sourceMap: process.env.NODE_ENV !== 'production' ? config.dev.cssSourceMap : false, extract: IsWeb, minifyCss: process.env.NODE_ENV === 'production' }));
|
||||
(IsWeb || config.UseJsx) ? rendererConfig.module.rules.push({ test: /\.m?[jt]sx$/, use: [{ loader: 'babel-loader', options: { cacheDirectory: true } }] }) : rendererConfig.module.rules.push({ test: /\.m?[jt]s$/, loader: 'esbuild-loader', options: { loader: 'ts', } })
|
||||
|
||||
/**
|
||||
* Adjust rendererConfig for development settings
|
||||
*/
|
||||
if (process.env.NODE_ENV !== 'production' && !IsWeb) {
|
||||
rendererConfig.plugins.push(
|
||||
new webpack.DefinePlugin({
|
||||
__lib: `"${path.join(__dirname, `../${config.DllFolder}`).replace(/\\/g, '\\\\')}"`
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust rendererConfig for production settings
|
||||
*/
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
|
||||
rendererConfig.plugins.push(
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [
|
||||
{
|
||||
from: path.join(__dirname, '../static'),
|
||||
to: path.join(__dirname, '../dist/electron/static'),
|
||||
globOptions: {
|
||||
ignore: ['.*']
|
||||
}
|
||||
}
|
||||
]
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': '"production"',
|
||||
}),
|
||||
new webpack.LoaderOptionsPlugin({
|
||||
minimize: true
|
||||
})
|
||||
)
|
||||
rendererConfig.optimization = {
|
||||
minimize: true,
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
terserOptions: {
|
||||
compress: {
|
||||
drop_console: true,
|
||||
drop_debugger: true,
|
||||
pure_funcs: ["console.log", "console.warn"]
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
]
|
||||
}
|
||||
rendererConfig.optimization.splitChunks = {
|
||||
chunks: "async",
|
||||
cacheGroups: {
|
||||
vendor: { // 将第三方模块提取出来
|
||||
minSize: 30000,
|
||||
minChunks: 1,
|
||||
test: /node_modules/,
|
||||
chunks: 'initial',
|
||||
name: 'vendor',
|
||||
priority: 1
|
||||
},
|
||||
commons: {
|
||||
test: /[\\/]src[\\/]common[\\/]/,
|
||||
name: 'commons',
|
||||
minSize: 30000,
|
||||
minChunks: 3,
|
||||
chunks: 'initial',
|
||||
priority: -1,
|
||||
reuseExistingChunk: true // 这个配置允许我们使用已经存在的代码块
|
||||
}
|
||||
}
|
||||
}
|
||||
rendererConfig.optimization.runtimeChunk = { name: 'runtime' }
|
||||
} else {
|
||||
rendererConfig.devtool = 'eval-source-map'
|
||||
// eslint
|
||||
// rendererConfig.plugins.push(new ESLintPlugin(config.dev.ESLintoptions))
|
||||
}
|
||||
|
||||
module.exports = rendererConfig
|
3
.eslintignore
Normal file
@ -0,0 +1,3 @@
|
||||
test/unit/coverage/**
|
||||
test/unit/*.js
|
||||
test/e2e/*.js
|
27
.eslintrc.js
Normal file
@ -0,0 +1,27 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
parser: 'babel-eslint',
|
||||
parserOptions: {
|
||||
sourceType: 'module'
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
node: true
|
||||
},
|
||||
extends: 'standard',
|
||||
globals: {
|
||||
__static: true,
|
||||
__lib: true
|
||||
},
|
||||
plugins: [
|
||||
'html'
|
||||
],
|
||||
'rules': {
|
||||
// allow paren-less arrow functions
|
||||
'arrow-parens': 0,
|
||||
// allow async-await
|
||||
'generator-star-spacing': 0,
|
||||
// allow debugger during development
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0
|
||||
}
|
||||
}
|
17
.gitignore
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
.DS_Store
|
||||
node_modules/
|
||||
/dist/
|
||||
/build/
|
||||
build/win-unpacked/
|
||||
build/win-ia32-unpacked/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
3
.npmrc
Normal file
@ -0,0 +1,3 @@
|
||||
registry = https://registry.npmmirror.com/
|
||||
sqlite3_binary_host_mirror = https://foxgis.oss-cn-shanghai.aliyuncs.com/
|
||||
electron_mirror = https://npmmirror.com/mirrors/electron/
|
5
.postcssrc.js
Normal file
@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
autoprefixer: {},
|
||||
}
|
||||
}
|
12
config/index.js
Normal file
@ -0,0 +1,12 @@
|
||||
module.exports = {
|
||||
build: {
|
||||
cleanConsole: true,
|
||||
},
|
||||
dev: {
|
||||
removeElectronJunk: true,
|
||||
chineseLog: false,
|
||||
port: 8088
|
||||
},
|
||||
DllFolder: '',
|
||||
UseJsx: true
|
||||
}
|
4
env/.env
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
API_HOST = 'https://mc.keyelement.cn/api/'
|
||||
# API_HOST = 'http://127.0.0.1:8080/'
|
||||
NODE_ENV = 'development'
|
||||
SYSTEM_NAME = '会员收银系统'
|
2
env/sit.env
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
API_HOST = 'http://127.0.0.1:25565'
|
||||
NODE_ENV = 'sit'
|
157
package.json
Normal file
@ -0,0 +1,157 @@
|
||||
{
|
||||
"name": "membercashier",
|
||||
"version": "1.2.0",
|
||||
"author": "成都关键元素科技有限公司",
|
||||
"description": "成都关键元素科技有限公司 - 会员管理收银系统",
|
||||
"license": "MIT",
|
||||
"main": "./dist/electron/main.js",
|
||||
"scripts": {
|
||||
"dev": "cross-env TERGET_ENV=development node .electron-vue/dev-runner.js",
|
||||
"build": "cross-env BUILD_TARGET=clean node .electron-vue/build.js && electron-builder",
|
||||
"build:win32": "cross-env BUILD_TARGET=clean node .electron-vue/build.js && electron-builder --win --ia32",
|
||||
"build:win64": "cross-env BUILD_TARGET=clean node .electron-vue/build.js && electron-builder --win --x64",
|
||||
"build:mac": "cross-env BUILD_TARGET=clean node .electron-vue/build.js && electron-builder --mac",
|
||||
"build:dir": "cross-env BUILD_TARGET=clean node .electron-vue/build.js && electron-builder --dir",
|
||||
"build:clean": "cross-env BUILD_TARGET=onlyClean node .electron-vue/build.js",
|
||||
"build:web": "cross-env BUILD_TARGET=web node .electron-vue/build.js",
|
||||
"pack:resources": "node .electron-vue/hot-updater.js",
|
||||
"update:serve": "node server/index.js",
|
||||
"dep:upgrade": "yarn upgrade-interactive --latest",
|
||||
"postinstall": "electron-builder install-app-deps"
|
||||
},
|
||||
"build": {
|
||||
"asar": false,
|
||||
"extraFiles": [],
|
||||
"publish": [
|
||||
{
|
||||
"provider": "generic",
|
||||
"url": "http://mc.keyelement.cn"
|
||||
}
|
||||
],
|
||||
"productName": "会员收银系统",
|
||||
"appId": "com.keyelement.membercashier",
|
||||
"directories": {
|
||||
"output": "build"
|
||||
},
|
||||
"files": [
|
||||
"dist/electron/**/*"
|
||||
],
|
||||
"dmg": {
|
||||
"contents": [
|
||||
{
|
||||
"x": 410,
|
||||
"y": 150,
|
||||
"type": "link",
|
||||
"path": "/Applications"
|
||||
},
|
||||
{
|
||||
"x": 130,
|
||||
"y": 150,
|
||||
"type": "file"
|
||||
}
|
||||
]
|
||||
},
|
||||
"mac": {
|
||||
"icon": "public/icons/icon.icns"
|
||||
},
|
||||
"win": {
|
||||
"icon": "public/icons/icon.ico",
|
||||
"target": "nsis"
|
||||
},
|
||||
"linux": {
|
||||
"target": "deb",
|
||||
"icon": "public/icons"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.4.0",
|
||||
"clipboard": "2.0.8",
|
||||
"electron-updater": "^5.3.0",
|
||||
"express": "4.18.2",
|
||||
"fs-extra": "^11.1.0",
|
||||
"vue-print-nb": "^1.7.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.22.5",
|
||||
"@babel/eslint-parser": "^7.22.5",
|
||||
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
||||
"@babel/plugin-proposal-decorators": "^7.22.5",
|
||||
"@babel/plugin-proposal-do-expressions": "^7.22.5",
|
||||
"@babel/plugin-proposal-export-default-from": "^7.22.5",
|
||||
"@babel/plugin-proposal-export-namespace-from": "^7.18.9",
|
||||
"@babel/plugin-proposal-function-bind": "^7.22.5",
|
||||
"@babel/plugin-proposal-function-sent": "^7.22.5",
|
||||
"@babel/plugin-proposal-json-strings": "^7.18.6",
|
||||
"@babel/plugin-proposal-logical-assignment-operators": "^7.20.7",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6",
|
||||
"@babel/plugin-proposal-numeric-separator": "^7.18.6",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.21.0",
|
||||
"@babel/plugin-proposal-pipeline-operator": "^7.22.5",
|
||||
"@babel/plugin-proposal-throw-expressions": "^7.22.5",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||
"@babel/plugin-syntax-import-meta": "^7.10.4",
|
||||
"@babel/plugin-transform-runtime": "^7.22.5",
|
||||
"@babel/preset-env": "^7.22.5",
|
||||
"@babel/register": "^7.22.5",
|
||||
"@babel/runtime": "^7.22.5",
|
||||
"@types/fs-extra": "^11.0.1",
|
||||
"@types/node": "^18.14.5",
|
||||
"@vue/babel-helper-vue-jsx-merge-props": "^1.4.0",
|
||||
"@vue/babel-preset-jsx": "^1.4.0",
|
||||
"adm-zip": "^0.5.10",
|
||||
"autoprefixer": "^10.4.14",
|
||||
"babel-loader": "^9.1.2",
|
||||
"cfonts": "^2.10.0",
|
||||
"chalk": "^4.1.2",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"core-js": "^3.31.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"css-loader": "^6.8.1",
|
||||
"date-fns": "^2.30.0",
|
||||
"del": "^6.1.1",
|
||||
"dotenv": "^16.1.4",
|
||||
"electron": "^24.8.1",
|
||||
"electron-builder": "^24.4.0",
|
||||
"electron-devtools-installer": "^3.2.0",
|
||||
"element-ui": "^2.15.13",
|
||||
"esbuild-loader": "^3.0.1",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-config-standard": "^14.1.1",
|
||||
"eslint-friendly-formatter": "^4.0.1",
|
||||
"eslint-plugin-html": "^6.2.0",
|
||||
"eslint-plugin-import": "^2.25.4",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^4.3.1",
|
||||
"eslint-plugin-standard": "^5.0.0",
|
||||
"eslint-webpack-plugin": "^3.2.0",
|
||||
"extract-zip": "^2.0.1",
|
||||
"html-webpack-plugin": "^5.5.3",
|
||||
"listr2": "^5.0.7",
|
||||
"mini-css-extract-plugin": "2.7.6",
|
||||
"minimist": "^1.2.8",
|
||||
"node-loader": "^2.0.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^2.0.33",
|
||||
"portfinder": "^1.0.32",
|
||||
"postcss": "^8.4.24",
|
||||
"postcss-loader": "^7.3.3",
|
||||
"sass": "^1.63.4",
|
||||
"sass-loader": "^13.3.2",
|
||||
"style-loader": "^3.3.3",
|
||||
"svg-sprite-loader": "^6.0.11",
|
||||
"terser-webpack-plugin": "^5.3.9",
|
||||
"vue": "^2.7.14",
|
||||
"vue-devtools": "^5.1.4",
|
||||
"vue-html-loader": "^1.2.4",
|
||||
"vue-i18n": "^8.27.1",
|
||||
"vue-loader": "15.10.1",
|
||||
"vue-router": "^3.6.5",
|
||||
"vue-style-loader": "^4.1.3",
|
||||
"vue-template-compiler": "^2.7.14",
|
||||
"webpack": "^5.87.0",
|
||||
"webpack-cli": "^5.1.4",
|
||||
"webpack-dev-server": "^4.15.1",
|
||||
"webpack-hot-middleware": "^2.25.3",
|
||||
"webpack-merge": "^5.9.0"
|
||||
}
|
||||
}
|
BIN
public/icons/256x256.png
Normal file
After Width: | Height: | Size: 9.1 KiB |
BIN
public/icons/icon.icns
Normal file
BIN
public/icons/icon.ico
Normal file
After Width: | Height: | Size: 353 KiB |
12
server/index.js
Normal file
@ -0,0 +1,12 @@
|
||||
const express = require('express')
|
||||
const path = require('path')
|
||||
const app = express()
|
||||
|
||||
app.use(express.static(path.join(__dirname, './client')))
|
||||
|
||||
const server = app.listen(25565, function () {
|
||||
const host = server.address().address
|
||||
const port = server.address().port
|
||||
|
||||
console.log('服务启动', host, port)
|
||||
})
|
32
src/index.ejs
Normal file
@ -0,0 +1,32 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>会员收银系统</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 -->
|
||||
<% if (!process.browser) { %>
|
||||
<script>
|
||||
if (process.env.NODE_ENV !== 'development') {
|
||||
window.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
|
||||
} else {
|
||||
window.__static = `http://localhost:${process.env.PORT}/static`
|
||||
}
|
||||
if (process.env.NODE_ENV !== 'development') window.__lib = process.env.libPath
|
||||
</script>
|
||||
<% } %>
|
||||
|
||||
<!-- webpack builds are automatically injected -->
|
||||
</body>
|
||||
|
||||
</html>
|
12
src/main/config/DisableButton.js
Normal file
@ -0,0 +1,12 @@
|
||||
import { globalShortcut } from 'electron'
|
||||
import { DisableF12 } from "./const"
|
||||
|
||||
export default {
|
||||
Disablef12() {
|
||||
if (process.env.NODE_ENV === 'production' && DisableF12) {
|
||||
globalShortcut.register('f12', () => {
|
||||
console.log('用户试图启动控制台')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
17
src/main/config/StaticPath.js
Normal file
@ -0,0 +1,17 @@
|
||||
// 这里定义了静态文件路径的位置
|
||||
import path from 'path'
|
||||
import { DllFolder } from '@config/index'
|
||||
|
||||
/**
|
||||
* 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, '\\\\')
|
||||
process.env.libPath = path.join(__dirname, '..', '..', '..', '..', `${DllFolder}`).replace(/\\/g, '\\\\')
|
||||
}
|
||||
|
||||
export const winURL = process.env.NODE_ENV === 'development' ? `http://localhost:${process.env.PORT}` : `file://${__dirname}/index.html`
|
||||
export const loadingURL = process.env.NODE_ENV === 'development' ? `http://localhost:${process.env.PORT}/static/loader.html` : `file://${__static}/loader.html`
|
||||
export const libPath = process.env.libPath
|
7
src/main/config/const.js
Normal file
@ -0,0 +1,7 @@
|
||||
export const UseStartupChart = true
|
||||
export const IsUseSysTitle = false
|
||||
export const BuiltInServerPort = 25565
|
||||
export const hotPublishUrl = ""
|
||||
export const hotPublishConfigName = "update-config"
|
||||
export const openDevTools = false
|
||||
export const DisableF12 = true
|
6
src/main/config/hotPublish.js
Normal file
@ -0,0 +1,6 @@
|
||||
import { hotPublishUrl, hotPublishConfigName } from './const'
|
||||
|
||||
export const hotPublishConfig = {
|
||||
url: hotPublishUrl,
|
||||
configName: hotPublishConfigName
|
||||
}
|
68
src/main/config/menu.js
Normal file
@ -0,0 +1,68 @@
|
||||
// 这里是定义菜单的地方,详情请查看 https://electronjs.org/docs/api/menu
|
||||
const { dialog } = require('electron')
|
||||
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: '编辑',
|
||||
submenu: [{
|
||||
label: '撤销',
|
||||
accelerator: 'CmdOrCtrl+Z',
|
||||
role: 'undo'
|
||||
},
|
||||
{
|
||||
label: '重做',
|
||||
accelerator: 'Shift+CmdOrCtrl+Z',
|
||||
role: 'redo'
|
||||
},
|
||||
{
|
||||
label: '剪切',
|
||||
accelerator: 'CmdOrCtrl+X',
|
||||
role: 'cut'
|
||||
},
|
||||
{
|
||||
label: '复制',
|
||||
accelerator: 'CmdOrCtrl+C',
|
||||
role: 'copy'
|
||||
},
|
||||
{
|
||||
label: '粘贴',
|
||||
accelerator: 'CmdOrCtrl+V',
|
||||
role: 'paste'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
label: '帮助',
|
||||
submenu: [{
|
||||
label: '关于',
|
||||
role: 'about',
|
||||
click: function () {
|
||||
info()
|
||||
}
|
||||
}]
|
||||
}]
|
||||
function info() {
|
||||
dialog.showMessageBox({
|
||||
title: '关于',
|
||||
type: 'info',
|
||||
message: '会员收银系统',
|
||||
detail: `版本信息:${version}\n引擎版本:${process.versions.v8}\n当前系统:${os.type()} ${os.arch()} ${os.release()}`,
|
||||
noLink: true,
|
||||
buttons: ['查看官网', '确定']
|
||||
})
|
||||
}
|
||||
export default menu
|
41
src/main/index.js
Normal file
@ -0,0 +1,41 @@
|
||||
'use strict'
|
||||
|
||||
import { app } from 'electron'
|
||||
import initWindow from './services/windowManager'
|
||||
import DisableButton from './config/DisableButton'
|
||||
import electronDevtoolsInstaller, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
|
||||
|
||||
function onAppReady () {
|
||||
initWindow()
|
||||
DisableButton.Disablef12()
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
electronDevtoolsInstaller(VUEJS_DEVTOOLS)
|
||||
.then((name) => console.log(`installed: ${name}`))
|
||||
.catch(err => console.log('Unable to install `vue-devtools`: \n', err))
|
||||
}
|
||||
}
|
||||
// 禁止程序多开,此处需要单例锁的同学打开注释即可
|
||||
const gotTheLock = app.requestSingleInstanceLock()
|
||||
if(!gotTheLock){
|
||||
app.quit()
|
||||
}
|
||||
app.isReady() ? onAppReady() : app.on('ready', onAppReady)
|
||||
// 解决9.x跨域异常问题
|
||||
app.commandLine.appendSwitch('disable-features', 'OutOfBlinkCors')
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
// 所有平台均为所有窗口关闭就退出软件
|
||||
app.quit()
|
||||
})
|
||||
app.on('browser-window-created', () => {
|
||||
console.log('window-created')
|
||||
})
|
||||
|
||||
if (process.defaultApp) {
|
||||
if (process.argv.length >= 2) {
|
||||
app.removeAsDefaultProtocolClient('electron-vue-template')
|
||||
console.log('框架特殊性开发环境下无法使用')
|
||||
}
|
||||
} else {
|
||||
app.setAsDefaultProtocolClient('electron-vue-template')
|
||||
}
|
44
src/main/server/index.js
Normal file
@ -0,0 +1,44 @@
|
||||
/* eslint-disable prefer-promise-reject-errors */
|
||||
import app from './server'
|
||||
import http from 'http'
|
||||
import config from '@config'
|
||||
const port = config.BuiltInServerPort
|
||||
var server = null
|
||||
app.set('port', port)
|
||||
|
||||
export default {
|
||||
StatrServer () {
|
||||
return new Promise((resolve, reject) => {
|
||||
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('服务端运行中')
|
||||
})
|
||||
})
|
||||
},
|
||||
StopServer () {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (server) {
|
||||
server.close()
|
||||
server.on('close', () => {
|
||||
server = null
|
||||
resolve(1)
|
||||
})
|
||||
} else {
|
||||
reject('服务端尚未开启')
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
14
src/main/server/server.js
Normal file
@ -0,0 +1,14 @@
|
||||
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
|
91
src/main/services/HotUpdater.js
Normal file
@ -0,0 +1,91 @@
|
||||
/**
|
||||
* power by biuuu
|
||||
*/
|
||||
|
||||
import { emptyDir, createWriteStream, readFile, copy, remove } from 'fs-extra'
|
||||
import { join, resolve } from 'path'
|
||||
import { promisify } from 'util'
|
||||
import { pipeline } from 'stream'
|
||||
import { app } from 'electron'
|
||||
import { gt } from 'semver'
|
||||
import { createHmac } from 'crypto'
|
||||
import extract from 'extract-zip'
|
||||
import { version } from '../../../package.json'
|
||||
import { hotPublishConfig } from '../config/hotPublish'
|
||||
import axios from 'axios'
|
||||
|
||||
const streamPipeline = promisify(pipeline)
|
||||
const appPath = app.getAppPath()
|
||||
const updatePath = resolve(appPath, '..', '..', 'update')
|
||||
const request = axios.create()
|
||||
|
||||
/**
|
||||
* @param data 文件流
|
||||
* @param type 类型,默认sha256
|
||||
* @param key 密钥,用于匹配计算结果
|
||||
* @returns {string} 计算结果
|
||||
* @author umbrella22
|
||||
* @date 2021-03-05
|
||||
*/
|
||||
function hash(data, type = 'sha256', key = 'Sky') {
|
||||
const hmac = createHmac(type, key)
|
||||
hmac.update(data)
|
||||
return hmac.digest('hex')
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param url 下载地址
|
||||
* @param filePath 文件存放地址
|
||||
* @returns {void}
|
||||
* @author umbrella22
|
||||
* @date 2021-03-05
|
||||
*/
|
||||
async function download(url, filePath) {
|
||||
const res = await request({ url, responseType: "stream" })
|
||||
await streamPipeline(res.data, createWriteStream(filePath))
|
||||
}
|
||||
|
||||
const updateInfo = {
|
||||
status: 'init',
|
||||
message: ''
|
||||
}
|
||||
|
||||
/**
|
||||
* @param windows 指主窗口
|
||||
* @returns {void}
|
||||
* @author umbrella22
|
||||
* @date 2021-03-05
|
||||
*/
|
||||
export const updater = async (windows) => {
|
||||
try {
|
||||
const res = await request({ url: `${hotPublishConfig.url}/${hotPublishConfig.configName}.json?time=${new Date().getTime()}`, })
|
||||
if (gt(res.data.version, version)) {
|
||||
await emptyDir(updatePath)
|
||||
const filePath = join(updatePath, res.data.name)
|
||||
updateInfo.status = 'downloading'
|
||||
if (windows) windows.webContents.send('hot-update-status', updateInfo);
|
||||
await download(`${hotPublishConfig.url}/${res.data.name}`, filePath);
|
||||
const buffer = await readFile(filePath)
|
||||
const sha256 = hash(buffer)
|
||||
if (sha256 !== res.data.hash) throw new Error('sha256 error')
|
||||
const appPathTemp = join(updatePath, 'temp')
|
||||
await extract(filePath, { dir: appPathTemp })
|
||||
updateInfo.status = 'moving'
|
||||
if (windows) windows.webContents.send('hot-update-status', updateInfo);
|
||||
await remove(join(`${appPath}`, 'dist'));
|
||||
await remove(join(`${appPath}`, 'package.json'));
|
||||
await copy(appPathTemp, appPath)
|
||||
updateInfo.status = 'finished'
|
||||
if (windows) windows.webContents.send('hot-update-status', updateInfo);
|
||||
}
|
||||
|
||||
|
||||
} catch (error) {
|
||||
updateInfo.status = 'failed'
|
||||
updateInfo.message = error
|
||||
if (windows) windows.webContents.send('hot-update-status', updateInfo)
|
||||
}
|
||||
}
|
||||
|
||||
export const getUpdateInfo = () => updateInfo
|
76
src/main/services/checkupdate.js
Normal file
@ -0,0 +1,76 @@
|
||||
import { autoUpdater } from 'electron-updater'
|
||||
/**
|
||||
* -1 检查更新失败 0 正在检查更新 1 检测到新版本,准备下载 2 未检测到新版本 3 下载中 4 下载完成
|
||||
**/
|
||||
class Update {
|
||||
mainWindow
|
||||
constructor() {
|
||||
autoUpdater.setFeedURL('https://mc.keyelement.cn/downloads/')
|
||||
|
||||
// 当更新发生错误的时候触发。
|
||||
autoUpdater.on('error', (err) => {
|
||||
console.log('更新出现错误', err.message)
|
||||
if (err.message.includes('sha512 checksum mismatch')) {
|
||||
this.Message(this.mainWindow, -1, 'sha512校验失败')
|
||||
} else {
|
||||
this.Message(this.mainWindow, -1, '错误信息请看主进程控制台')
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
// 当开始检查更新的时候触发
|
||||
autoUpdater.on('checking-for-update', (event, arg) => {
|
||||
console.log('开始检查更新')
|
||||
this.Message(this.mainWindow, 0)
|
||||
})
|
||||
|
||||
// 发现可更新数据时
|
||||
autoUpdater.on('update-available', (event, arg) => {
|
||||
console.log('有更新')
|
||||
this.Message(this.mainWindow, 1)
|
||||
})
|
||||
|
||||
// 没有可更新数据时
|
||||
autoUpdater.on('update-not-available', (event, arg) => {
|
||||
console.log('没有更新')
|
||||
this.Message(this.mainWindow, 2)
|
||||
})
|
||||
|
||||
// 下载监听
|
||||
autoUpdater.on('download-progress', (progressObj) => {
|
||||
this.Message(this.mainWindow, 3, progressObj)
|
||||
})
|
||||
|
||||
// 下载完成
|
||||
autoUpdater.on('update-downloaded', () => {
|
||||
console.log('done')
|
||||
this.Message(this.mainWindow, 4)
|
||||
})
|
||||
}
|
||||
// 负责向渲染进程发送信息
|
||||
Message(mainWindow, type, data) {
|
||||
console.log('发送消息')
|
||||
const senddata = {
|
||||
state: type,
|
||||
msg: data || ''
|
||||
}
|
||||
mainWindow.webContents.send('update-msg', senddata)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 执行自动更新检查
|
||||
checkUpdate(mainWindow) {
|
||||
this.mainWindow = mainWindow
|
||||
autoUpdater.checkForUpdates().catch(err => {
|
||||
console.log('网络连接问题', err)
|
||||
})
|
||||
}
|
||||
|
||||
// 退出并安装
|
||||
quitInstall() {
|
||||
autoUpdater.quitAndInstall()
|
||||
}
|
||||
}
|
||||
|
||||
export default Update
|
63
src/main/services/downloadFile.js
Normal file
@ -0,0 +1,63 @@
|
||||
/* eslint-disable no-case-declarations */
|
||||
import { app, 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, downloadUrL) {
|
||||
mainWindow.webContents.downloadURL(downloadUrL || defaultDownloadUrL)
|
||||
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
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
186
src/main/services/ipcMain.js
Normal file
@ -0,0 +1,186 @@
|
||||
import { ipcMain, dialog, BrowserWindow } from 'electron'
|
||||
import Server from '../server/index'
|
||||
import { winURL } from '../config/StaticPath'
|
||||
import downloadFile from './downloadFile'
|
||||
import Update from './checkupdate'
|
||||
import { updater } from './HotUpdater'
|
||||
|
||||
export default {
|
||||
Mainfunc(IsUseSysTitle) {
|
||||
const allUpdater = new Update();
|
||||
ipcMain.handle('IsUseSysTitle', async () => {
|
||||
return IsUseSysTitle
|
||||
})
|
||||
ipcMain.handle('windows-mini', (event, args) => {
|
||||
BrowserWindow.fromWebContents(event.sender)?.minimize()
|
||||
})
|
||||
ipcMain.handle('window-max', async (event, args) => {
|
||||
if (BrowserWindow.fromWebContents(event.sender)?.isMaximized()) {
|
||||
BrowserWindow.fromWebContents(event.sender)?.unmaximize()
|
||||
return { status: false }
|
||||
} else {
|
||||
BrowserWindow.fromWebContents(event.sender)?.maximize()
|
||||
return { status: true }
|
||||
}
|
||||
})
|
||||
ipcMain.handle('window-close', (event, args) => {
|
||||
BrowserWindow.fromWebContents(event.sender)?.close()
|
||||
})
|
||||
ipcMain.handle('start-download', (event, msg) => {
|
||||
downloadFile.download(BrowserWindow.fromWebContents(event.sender), msg.downloadUrL)
|
||||
})
|
||||
ipcMain.handle('check-update', (event, args) => {
|
||||
allUpdater.checkUpdate(BrowserWindow.fromWebContents(event.sender))
|
||||
})
|
||||
ipcMain.handle('confirm-update', () => {
|
||||
allUpdater.quitInstall()
|
||||
})
|
||||
ipcMain.handle('hot-update', (event, arg) => {
|
||||
updater(BrowserWindow.fromWebContents(event.sender))
|
||||
})
|
||||
ipcMain.handle('open-messagebox', async (event, arg) => {
|
||||
const res = await dialog.showMessageBox(BrowserWindow.fromWebContents(event.sender), {
|
||||
type: arg.type || 'info',
|
||||
title: arg.title || '',
|
||||
buttons: arg.buttons || [],
|
||||
message: arg.message || '',
|
||||
noLink: arg.noLink || true
|
||||
})
|
||||
return res
|
||||
})
|
||||
ipcMain.handle('open-errorbox', (event, arg) => {
|
||||
dialog.showErrorBox(
|
||||
arg.title,
|
||||
arg.message
|
||||
)
|
||||
})
|
||||
ipcMain.handle('statr-server', async () => {
|
||||
try {
|
||||
const serveStatus = await Server.StatrServer()
|
||||
return serveStatus
|
||||
} catch (error) {
|
||||
dialog.showErrorBox(
|
||||
'错误',
|
||||
error
|
||||
)
|
||||
}
|
||||
})
|
||||
ipcMain.handle('stop-server', async (event, arg) => {
|
||||
try {
|
||||
const serveStatus = await Server.StopServer()
|
||||
return serveStatus
|
||||
} catch (error) {
|
||||
dialog.showErrorBox(
|
||||
'错误',
|
||||
error
|
||||
)
|
||||
}
|
||||
})
|
||||
let childWin = null;
|
||||
let cidArray = [];
|
||||
ipcMain.handle('open-win', (event, arg) => {
|
||||
let cidJson = { id: null, url: '' }
|
||||
let data = cidArray.filter((currentValue) => {
|
||||
if (currentValue.url === arg.url) {
|
||||
return currentValue
|
||||
}
|
||||
})
|
||||
if (data.length > 0) {
|
||||
//获取当前窗口
|
||||
let currentWindow = BrowserWindow.fromId(data[0].id)
|
||||
//聚焦窗口
|
||||
currentWindow.focus();
|
||||
} else {
|
||||
//获取主窗口ID
|
||||
let parentID = event.sender.id
|
||||
//创建窗口
|
||||
childWin = new BrowserWindow({
|
||||
width: arg?.width || 842,
|
||||
height: arg?.height || 595,
|
||||
//width 和 height 将设置为 web 页面的尺寸(译注: 不包含边框), 这意味着窗口的实际尺寸将包括窗口边框的大小,稍微会大一点。
|
||||
useContentSize: true,
|
||||
//自动隐藏菜单栏,除非按了Alt键。
|
||||
autoHideMenuBar: true,
|
||||
//窗口大小是否可调整
|
||||
resizable: arg?.resizable ?? false,
|
||||
//窗口的最小高度
|
||||
minWidth: arg?.minWidth || 842,
|
||||
show: arg?.show ?? false,
|
||||
//窗口透明度
|
||||
opacity: arg?.opacity || 1.0,
|
||||
//当前窗口的父窗口ID
|
||||
parent: parentID,
|
||||
frame: IsUseSysTitle,
|
||||
icon: '',
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
webSecurity: true,
|
||||
//使用webview标签 必须开启
|
||||
webviewTag: arg?.webview ?? false,
|
||||
// 如果是开发模式可以使用devTools
|
||||
devTools: process.env.NODE_ENV === 'development',
|
||||
// 在macos中启用橡皮动画
|
||||
scrollBounce: process.platform === 'darwin',
|
||||
// 临时修复打开新窗口报错
|
||||
contextIsolation: false
|
||||
}
|
||||
})
|
||||
childWin.loadURL(winURL + `#${arg.url}`)
|
||||
cidJson.id = childWin?.id
|
||||
cidJson.url = arg.url
|
||||
cidArray.push(cidJson)
|
||||
childWin.webContents.once('dom-ready', () => {
|
||||
childWin.show()
|
||||
childWin.webContents.send('send-data', arg.sendData)
|
||||
if (arg.IsPay) {
|
||||
// 检查支付时候自动关闭小窗口
|
||||
const testUrl = setInterval(() => {
|
||||
const Url = childWin.webContents.getURL()
|
||||
if (Url.includes(arg.PayUrl)) {
|
||||
childWin.close()
|
||||
}
|
||||
}, 1200)
|
||||
childWin.on('close', () => {
|
||||
clearInterval(testUrl)
|
||||
})
|
||||
}
|
||||
})
|
||||
childWin.on('closed', () => {
|
||||
childWin = null
|
||||
let index = cidArray.indexOf(cidJson)
|
||||
if (index > -1) {
|
||||
cidArray.splice(index, 1);
|
||||
}
|
||||
})
|
||||
}
|
||||
childWin.on('maximize', () => {
|
||||
if (cidJson.id != null) {
|
||||
BrowserWindow.fromId(cidJson.id).webContents.send("w-max", true)
|
||||
}
|
||||
})
|
||||
childWin.on('unmaximize', () => {
|
||||
if (cidJson.id != null) {
|
||||
BrowserWindow.fromId(cidJson.id).webContents.send("w-max", false)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
ipcMain.handle('getPrintList', async () => {
|
||||
try {
|
||||
const currentWindow = BrowserWindow.getFocusedWindow();
|
||||
const list = await currentWindow.webContents.getPrintersAsync()
|
||||
return list
|
||||
} catch (error) {
|
||||
console.log('error', error)
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on('handle_print', (e, { htmlText, deviceName }) => {
|
||||
let printWindow = new BrowserWindow({ show: false, width: 1920, height: 1080, contextIsolation: false, enableRemoteModule: true, nodeIntegration: true, webSecurity: false })
|
||||
printWindow.loadURL('data:text/html,' + encodeURIComponent(htmlText))
|
||||
printWindow.webContents.print({ deviceName, silent: true })
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
}
|
103
src/main/services/windowManager.js
Normal file
@ -0,0 +1,103 @@
|
||||
import { BrowserWindow, Menu, app, globalShortcut } from 'electron'
|
||||
import { platform } from "os"
|
||||
import menuconfig from '../config/menu'
|
||||
import { openDevTools, IsUseSysTitle, UseStartupChart } from '../config/const'
|
||||
import setIpc from './ipcMain'
|
||||
import { winURL, loadingURL } from '../config/StaticPath'
|
||||
|
||||
var loadWindow = null
|
||||
var mainWindow = null
|
||||
setIpc.Mainfunc(IsUseSysTitle)
|
||||
|
||||
function createMainWindow() {
|
||||
/**
|
||||
* Initial window options
|
||||
*/
|
||||
mainWindow = new BrowserWindow({
|
||||
height: 800,
|
||||
useContentSize: true,
|
||||
width: 1700,
|
||||
color: "#ffffff",
|
||||
backgroundColor: "#ffffff",
|
||||
minWidth: 1000,
|
||||
show: false,
|
||||
frame: IsUseSysTitle,
|
||||
icon: '',
|
||||
titleBarStyle: platform().includes('win32') ? 'default' : 'hidden',
|
||||
webPreferences: {
|
||||
contextIsolation: false,
|
||||
nodeIntegration: true,
|
||||
webSecurity: true,
|
||||
// 如果是开发模式可以使用devTools
|
||||
devTools: process.env.NODE_ENV === 'development' || openDevTools,
|
||||
// devTools: true,
|
||||
// 在macos中启用橡皮动画
|
||||
scrollBounce: process.platform === 'darwin'
|
||||
}
|
||||
})
|
||||
|
||||
// 开发工具快捷键
|
||||
globalShortcut.register('ctrl+shift+i', () => {
|
||||
const foucsedWin = BrowserWindow.getFocusedWindow()
|
||||
if (foucsedWin) {
|
||||
foucsedWin.webContents.openDevTools()
|
||||
}
|
||||
})
|
||||
|
||||
// 载入菜单
|
||||
const menu = Menu.buildFromTemplate(menuconfig)
|
||||
Menu.setApplicationMenu(menu)
|
||||
mainWindow.loadURL(winURL)
|
||||
|
||||
mainWindow.webContents.once('dom-ready', () => {
|
||||
mainWindow.show()
|
||||
if (process.env.NODE_ENV === 'development' || openDevTools) mainWindow.webContents.openDevTools(true)
|
||||
if (UseStartupChart) loadWindow.destroy()
|
||||
})
|
||||
mainWindow.on('maximize', () => {
|
||||
mainWindow.webContents.send("w-max", true)
|
||||
})
|
||||
mainWindow.on('unmaximize', () => {
|
||||
mainWindow.webContents.send("w-max", false)
|
||||
})
|
||||
mainWindow.on('closed', () => {
|
||||
mainWindow = null
|
||||
app.quit();
|
||||
})
|
||||
}
|
||||
|
||||
function loadingWindow() {
|
||||
loadWindow = new BrowserWindow({
|
||||
width: 400,
|
||||
height: 600,
|
||||
frame: false,
|
||||
backgroundColor: '#fff',
|
||||
color: '#fff',
|
||||
skipTaskbar: true,
|
||||
transparent: true,
|
||||
resizable: false,
|
||||
icon: '',
|
||||
webPreferences: { experimentalFeatures: true }
|
||||
})
|
||||
|
||||
loadWindow.loadURL(loadingURL)
|
||||
|
||||
loadWindow.show()
|
||||
|
||||
setTimeout(() => {
|
||||
createMainWindow()
|
||||
}, 2000)
|
||||
|
||||
loadWindow.on('closed', () => {
|
||||
loadWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
function initWindow() {
|
||||
if (UseStartupChart) {
|
||||
return loadingWindow()
|
||||
} else {
|
||||
return createMainWindow()
|
||||
}
|
||||
}
|
||||
export default initWindow
|
17
src/renderer/App.vue
Normal file
@ -0,0 +1,17 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<c-header></c-header>
|
||||
<transition name="fade" mode="out-in">
|
||||
<router-view></router-view>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import CHeader from "./components/title";
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* CSS */
|
||||
</style>
|
58
src/renderer/api/balance.js
Normal file
@ -0,0 +1,58 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 分页查询余额明细列表
|
||||
export function getBalanceList(query) {
|
||||
return request({
|
||||
url: 'backendApi/balance/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询明细详情
|
||||
export function getBalanceInfo(memberId) {
|
||||
return request({
|
||||
url: 'backendApi/balance/info/' + memberId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 更新状态
|
||||
export function updateBalanceStatus(id, status) {
|
||||
const data = {
|
||||
id,
|
||||
status
|
||||
}
|
||||
return request({
|
||||
url: 'backendApi/balance/updateStatus',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 获取配置信息
|
||||
export function getSettingInfo() {
|
||||
return request({
|
||||
url: 'backendApi/balance/setting',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 保存配置
|
||||
export function saveSetting(data) {
|
||||
return request({
|
||||
url: 'backendApi/balance/saveSetting',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 确定充值
|
||||
export function doRecharge(data) {
|
||||
return request({
|
||||
url: 'backendApi/balance/doRecharge',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
133
src/renderer/api/cashier.js
Normal file
@ -0,0 +1,133 @@
|
||||
import request from '@/utils/request'
|
||||
import exp from 'constants'
|
||||
|
||||
// 初始化数据
|
||||
export function init(userId, cateId, page, pageSize) {
|
||||
return request({
|
||||
url: 'backendApi/cashier/init/' + userId,
|
||||
method: 'get',
|
||||
params: { cateId: cateId, page: page, pageSize: pageSize }
|
||||
})
|
||||
}
|
||||
|
||||
// 查询商品详情
|
||||
export function getGoodsInfo(goodsId) {
|
||||
return request({
|
||||
url: 'backendApi/cashier/getGoodsInfo/' + goodsId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询商品
|
||||
export function searchGoods(data) {
|
||||
return request({
|
||||
url: 'backendApi/cashier/searchGoods',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 查询会员信息
|
||||
export function getMemberInfo(data) {
|
||||
return request({
|
||||
url: 'backendApi/cashier/getMemberInfo',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 查询会员信息
|
||||
export function getMemberInfoById(userId) {
|
||||
return request({
|
||||
url: 'backendApi/cashier/getMemberInfoById/' + userId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 获取购物车列表
|
||||
export function getCartList(data) {
|
||||
return request({
|
||||
url: 'clientApi/cart/list',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 保存购物车
|
||||
export function saveCart(data) {
|
||||
return request({
|
||||
url: 'clientApi/cart/save',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除购物车
|
||||
export function removeFromCart(data) {
|
||||
return request({
|
||||
url: 'clientApi/cart/clear',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 提交结算
|
||||
export function submitSettlement(data) {
|
||||
return request({
|
||||
url: 'clientApi/settlement/submit',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 发起支付
|
||||
export function doPay(params) {
|
||||
return request({
|
||||
url: 'clientApi/pay/doPay',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
// 获取订单列表
|
||||
export function getOrderList(data) {
|
||||
return request({
|
||||
url: 'backendApi/order/latest',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 执行挂单
|
||||
export function doHangUp(data) {
|
||||
return request({
|
||||
url: 'backendApi/cashier/doHangUp',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 获取挂单
|
||||
export function getHangUpList() {
|
||||
return request({
|
||||
url: 'backendApi/cashier/getHangUpList',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 删除挂单
|
||||
export function removeHangUp(data) {
|
||||
return request({
|
||||
url: 'clientApi/cart/clear',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 获取用户资源信息
|
||||
export function asset(userId){
|
||||
return request({
|
||||
url: 'clientApi/user/asset/'+userId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
75
src/renderer/api/coupon.js
Normal file
@ -0,0 +1,75 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 分页查询卡券列表
|
||||
export function getCouponList(query) {
|
||||
return request({
|
||||
url: 'backendApi/coupon/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询卡券信息
|
||||
export function getCouponInfo(id) {
|
||||
return request({
|
||||
url: 'backendApi/coupon/info/' + id,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 更新状态
|
||||
export function updateCouponStatus(id, status) {
|
||||
const data = {
|
||||
id,
|
||||
status
|
||||
}
|
||||
return request({
|
||||
url: 'backendApi/coupon/updateStatus',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除卡券
|
||||
export function deleteCoupon(id) {
|
||||
return request({
|
||||
url: 'backendApi/coupon/delete/' + id,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 保存卡券
|
||||
export function saveCoupon(data) {
|
||||
return request({
|
||||
url: 'backendApi/coupon/save',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 查询卡券核销信息
|
||||
export function getConfirmInfo(data) {
|
||||
return request({
|
||||
url: 'backendApi/doConfirm/info',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 执行核销
|
||||
export function doConfirm(data) {
|
||||
return request({
|
||||
url: 'backendApi/doConfirm/doConfirm',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 发放卡券
|
||||
export function sendCoupon(params) {
|
||||
return request({
|
||||
url: 'backendApi/coupon/sendCoupon',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
76
src/renderer/api/goods.js
Normal file
@ -0,0 +1,76 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 分页查询商品列表
|
||||
export function getGoodsList(query) {
|
||||
return request({
|
||||
url: 'backendApi/goods/goods/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询商品详情
|
||||
export function getGoodsInfo(goodsId) {
|
||||
return request({
|
||||
url: 'backendApi/goods/goods/info/' + goodsId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 更新状态
|
||||
export function updateGoodsStatus(id, status) {
|
||||
const data = {
|
||||
id,
|
||||
status
|
||||
}
|
||||
return request({
|
||||
url: 'backendApi/goods/goods/updateStatus',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 保存分类数据
|
||||
export function saveGoods(data) {
|
||||
return request({
|
||||
url: 'backendApi/goods/goods/save',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 保存商品规格名称
|
||||
export function saveSpecName(data) {
|
||||
return request({
|
||||
url: 'backendApi/goods/goods/saveSpecName',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 保存商品规格值
|
||||
export function saveSpecValue(data) {
|
||||
return request({
|
||||
url: 'backendApi/goods/goods/saveSpecValue',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除商品规格
|
||||
export function deleteSpec(query) {
|
||||
return request({
|
||||
url: 'backendApi/goods/goods/deleteSpec',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 删除商品规格值
|
||||
export function deleteSpecValue(query) {
|
||||
return request({
|
||||
url: 'backendApi/goods/goods/deleteSpecValue',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
14
src/renderer/api/location.js
Normal file
@ -0,0 +1,14 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 分页查询
|
||||
export function getStoreLocationList() {
|
||||
return request({
|
||||
url: 'backendApi/storeLocation/list',
|
||||
method: 'get',
|
||||
params: {
|
||||
page: 1,
|
||||
pageSize: 100,
|
||||
status: 'A'
|
||||
}
|
||||
})
|
||||
}
|
51
src/renderer/api/login.js
Normal file
@ -0,0 +1,51 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 登录方法
|
||||
export function login(username, password, captchaCode, uuid) {
|
||||
const data = {
|
||||
username,
|
||||
password,
|
||||
captchaCode,
|
||||
uuid
|
||||
}
|
||||
return request({
|
||||
url: 'backendApi/login/doClientLogin',
|
||||
headers: {
|
||||
isToken: false
|
||||
},
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 获取用户详细信息
|
||||
export function getInfo() {
|
||||
return request({
|
||||
url: 'backendApi/login/getInfo',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 退出方法
|
||||
export function logout() {
|
||||
return request({
|
||||
url: 'backendApi/login/logout',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
// 获取验证码
|
||||
export function getCodeImg() {
|
||||
return request({
|
||||
url: 'clientApi/captcha/getCode',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 系统消息
|
||||
export function message () {
|
||||
return request({
|
||||
url: 'clientApi/captcha/message',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
75
src/renderer/api/member.js
Normal file
@ -0,0 +1,75 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 分页查询会员列表
|
||||
export function getMemberList(query) {
|
||||
return request({
|
||||
url: 'backendApi/member/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询会员信息
|
||||
export function getMemberInfo(memberId) {
|
||||
return request({
|
||||
url: 'backendApi/member/info/' + memberId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询会员设置
|
||||
export function getMemberSetting() {
|
||||
return request({
|
||||
url: 'backendApi/member/setting',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 保存会员设置
|
||||
export function saveSetting(data) {
|
||||
return request({
|
||||
url: 'backendApi/member/saveSetting',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 更新会员状态
|
||||
export function updateMemberStatus(userId, status) {
|
||||
const data = {
|
||||
userId,
|
||||
status
|
||||
}
|
||||
return request({
|
||||
url: 'backendApi/member/updateStatus',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除会员信息
|
||||
export function deleteMember(memberId) {
|
||||
return request({
|
||||
url: 'backendApi/member/delete/' + memberId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 保存数据
|
||||
export function saveMember(data) {
|
||||
return request({
|
||||
url: 'backendApi/member/save',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 验证用户密码
|
||||
export function checkPwd(userId, password){
|
||||
return request({
|
||||
url: 'backendApi/member/checkPwd',
|
||||
method: 'post',
|
||||
data: {userId, password}
|
||||
})
|
||||
}
|
||||
|
83
src/renderer/api/order.js
Normal file
@ -0,0 +1,83 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 分页查询订单列表
|
||||
export function getOrderList(data) {
|
||||
return request({
|
||||
url: 'backendApi/order/list',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 查询订单信息
|
||||
export function getOrderInfo(orderId) {
|
||||
return request({
|
||||
url: 'backendApi/order/info/' + orderId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 更新订单状态
|
||||
export function updateOrderStatus(orderId, status) {
|
||||
const data = {
|
||||
orderId,
|
||||
status
|
||||
}
|
||||
return request({
|
||||
url: 'backendApi/order/updateStatus',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除订单
|
||||
export function deleteOrder(orderId) {
|
||||
return request({
|
||||
url: 'backendApi/order/delete/' + orderId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 保存订单数据
|
||||
export function saveOrder(data) {
|
||||
return request({
|
||||
url: 'backendApi/order/save',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 验证核销订单
|
||||
export function verifyOrder(data) {
|
||||
return request({
|
||||
url: 'backendApi/order/verify',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 提交发货信息
|
||||
export function delivered(data) {
|
||||
return request({
|
||||
url: 'backendApi/order/delivered',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 获取配置信息
|
||||
export function getSettingInfo() {
|
||||
return request({
|
||||
url: 'backendApi/order/setting',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 保存配置
|
||||
export function saveSetting(data) {
|
||||
return request({
|
||||
url: 'backendApi/order/saveSetting',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
58
src/renderer/api/point.js
Normal file
@ -0,0 +1,58 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 分页查询积分明细列表
|
||||
export function getPointList(query) {
|
||||
return request({
|
||||
url: 'backendApi/point/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询明细详情
|
||||
export function getPointInfo(memberId) {
|
||||
return request({
|
||||
url: 'backendApi/point/info/' + memberId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 更新状态
|
||||
export function updatePointStatus(id, status) {
|
||||
const data = {
|
||||
id,
|
||||
status
|
||||
}
|
||||
return request({
|
||||
url: 'backendApi/point/updateStatus',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 获取配置信息
|
||||
export function getSettingInfo() {
|
||||
return request({
|
||||
url: 'backendApi/point/setting',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 保存配置
|
||||
export function saveSetting(data) {
|
||||
return request({
|
||||
url: 'backendApi/point/saveSetting',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 确定充值
|
||||
export function doRecharge(data) {
|
||||
return request({
|
||||
url: 'backendApi/point/doRecharge',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
53
src/renderer/api/refund.js
Normal file
@ -0,0 +1,53 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 分页查询退款订单列表
|
||||
export function getRefundList(query) {
|
||||
return request({
|
||||
url: 'backendApi/refund/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询订单信息
|
||||
export function getRefundInfo(refundId) {
|
||||
return request({
|
||||
url: 'backendApi/refund/info/' + refundId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 订单退款
|
||||
export function doRefund(data) {
|
||||
return request({
|
||||
url: 'backendApi/refund/doRefund',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除退款订单
|
||||
export function deleteRefund(refundId) {
|
||||
return request({
|
||||
url: 'backendApi/refund/delete/' + refundId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 保存退款订单
|
||||
export function saveRefund(data) {
|
||||
return request({
|
||||
url: 'backendApi/refund/save',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 订单预付金中补扣
|
||||
export function doDeduction(data) {
|
||||
return request({
|
||||
url: 'backendApi/refund/doDeduction',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
26
src/renderer/api/sms.js
Normal file
@ -0,0 +1,26 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 发送用户结算验证码
|
||||
export function sendSettlementCode(merchantId,mobile, amount) {
|
||||
return request({
|
||||
url: 'clientApi/sms/sendSCode',
|
||||
method: 'post',
|
||||
data:{
|
||||
merchantId,
|
||||
mobile,
|
||||
amount
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 验证用户结算验证码
|
||||
export function checkSettlementCode(mobile,code) {
|
||||
return request({
|
||||
url: 'clientApi/sms/checkSCode',
|
||||
method: 'post',
|
||||
data:{
|
||||
mobile,
|
||||
code
|
||||
}
|
||||
})
|
||||
}
|
0
src/renderer/assets/.gitkeep
Normal file
BIN
src/renderer/assets/404_images/404.png
Normal file
After Width: | Height: | Size: 96 KiB |
BIN
src/renderer/assets/404_images/404_cloud.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
src/renderer/assets/images/avatar.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
src/renderer/assets/images/bg.png
Normal file
After Width: | Height: | Size: 134 KiB |
BIN
src/renderer/assets/images/cashier.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
src/renderer/assets/images/goods.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
src/renderer/assets/images/hot.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
src/renderer/assets/images/life.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
src/renderer/assets/images/love.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
src/renderer/assets/images/noGoods.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
src/renderer/assets/images/office.png
Normal file
After Width: | Height: | Size: 504 B |
BIN
src/renderer/assets/images/order.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
src/renderer/assets/logo.png
Normal file
After Width: | Height: | Size: 9.1 KiB |
BIN
src/renderer/assets/user.png
Normal file
After Width: | Height: | Size: 18 KiB |
51
src/renderer/components/Breadcrumb/index.vue
Normal file
@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<el-breadcrumb class="app-breadcrumb" separator="/">
|
||||
<transition-group name="breadcrumb">
|
||||
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path" v-if="item.meta.title">
|
||||
<span v-if="item.redirect==='noredirect'||index==levelList.length-1" class="no-redirect">{{item.meta.title}}</span>
|
||||
<router-link v-else :to="item.redirect||item.path">{{item.meta.title}}</router-link>
|
||||
</el-breadcrumb-item>
|
||||
</transition-group>
|
||||
</el-breadcrumb>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
created() {
|
||||
this.getBreadcrumb()
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
levelList: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
$route() {
|
||||
this.getBreadcrumb()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getBreadcrumb() {
|
||||
let matched = this.$route.matched.filter(item => item.name)
|
||||
const first = matched[0]
|
||||
if (first && first.name !== 'dashboard') {
|
||||
matched = [{ path: '/dashboard', meta: { title: '总览' }}].concat(matched)
|
||||
}
|
||||
this.levelList = matched
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
.app-breadcrumb.el-breadcrumb {
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
line-height: 50px;
|
||||
margin-left: 10px;
|
||||
.no-redirect {
|
||||
color: #97a8be;
|
||||
cursor: text;
|
||||
}
|
||||
}
|
||||
</style>
|
46
src/renderer/components/Hamburger/index.vue
Normal file
@ -0,0 +1,46 @@
|
||||
<template>
|
||||
<div>
|
||||
<svg t="1492500959545" @click="toggleClick" class="hamburger" :class="{ 'is-active': isActive }" style=""
|
||||
viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1691"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64">
|
||||
<path
|
||||
d="M966.8023 568.849776 57.196677 568.849776c-31.397081 0-56.850799-25.452695-56.850799-56.850799l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 543.397081 998.200404 568.849776 966.8023 568.849776z"
|
||||
p-id="1692"></path>
|
||||
<path
|
||||
d="M966.8023 881.527125 57.196677 881.527125c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 856.07443 998.200404 881.527125 966.8023 881.527125z"
|
||||
p-id="1693"></path>
|
||||
<path
|
||||
d="M966.8023 256.17345 57.196677 256.17345c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.850799 56.850799-56.850799l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.850799l0 0C1023.653099 230.720755 998.200404 256.17345 966.8023 256.17345z"
|
||||
p-id="1694"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
defineProps({
|
||||
isActive: {
|
||||
type: Boolean
|
||||
}
|
||||
})
|
||||
const emits = defineEmits(['toggle-click'])
|
||||
const toggleClick = () => {
|
||||
emits('toggle-click')
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.hamburger {
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
transform: rotate(90deg);
|
||||
transition: .38s;
|
||||
transform-origin: 50% 50%;
|
||||
}
|
||||
|
||||
.hamburger.is-active {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
</style>
|
340
src/renderer/components/LandingPage.vue
Normal file
@ -0,0 +1,340 @@
|
||||
<template>
|
||||
<div id="wrapper">
|
||||
<img id="logo" :src="logo" alt="electron-vue" style="display: none"/>
|
||||
<main style="display: none">
|
||||
<div class="left-side">
|
||||
<span class="title">{{ $t("welcome") }}</span>
|
||||
<system-information></system-information>
|
||||
<div v-if="textarray.length === 0">
|
||||
<span>{{ text }}</span>
|
||||
</div>
|
||||
<div v-for="(itme, index) in textarray" :key="index" v-else>
|
||||
<span>{{ itme._id }}</span>
|
||||
<span>{{ itme.name }}</span>
|
||||
<span>{{ itme.age }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="right-side">
|
||||
<div class="doc">
|
||||
<div class="title alt">{{ $t("buttonTips") }}</div>
|
||||
<el-button type="primary" round @click="open()">{{
|
||||
$t("buttons.console")
|
||||
}}</el-button>
|
||||
<el-button type="primary" round @click="CheckUpdate('one')">{{
|
||||
$t("buttons.checkUpdate")
|
||||
}}</el-button>
|
||||
</div>
|
||||
<div class="doc">
|
||||
<el-button type="primary" round @click="CheckUpdate('two')">{{
|
||||
$t("buttons.checkUpdate2")
|
||||
}}</el-button>
|
||||
<el-button type="primary" round @click="StartServer">{{
|
||||
$t("buttons.startServer")
|
||||
}}</el-button>
|
||||
<el-button type="primary" round @click="StopServer">{{
|
||||
$t("buttons.stopServer")
|
||||
}}</el-button>
|
||||
<el-button type="primary" round @click="getMessage">{{
|
||||
$t("buttons.viewMessage")
|
||||
}}</el-button>
|
||||
</div>
|
||||
<div class="doc">
|
||||
<el-button type="primary" round @click="openNewWin">{{
|
||||
$t("buttons.openNewWindow")
|
||||
}}</el-button>
|
||||
<el-button type="primary" round @click="openDocument">{{
|
||||
$t("buttons.openDocument")
|
||||
}}</el-button>
|
||||
<el-button type="primary" round @click="changeLanguage">{{
|
||||
$t("buttons.changeLanguage")
|
||||
}}</el-button>
|
||||
</div>
|
||||
<div class="doc">
|
||||
<el-pagination :current-page="1" :page-sizes="[100, 200, 300, 400]" :page-size="100"
|
||||
layout="total, sizes, prev, pager, next, jumper" :total="400">
|
||||
</el-pagination>
|
||||
</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 { message } from "@/api/login";
|
||||
import { ipcRenderer, shell } from "electron";
|
||||
export default {
|
||||
name: "landing-page",
|
||||
components: { SystemInformation },
|
||||
data: () => ({
|
||||
newdata: {
|
||||
name: "yyy",
|
||||
age: "12",
|
||||
},
|
||||
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("环境打印示例");
|
||||
console.log("__lib路径", __lib);
|
||||
console.log("环境变量", process.env.userConfig);
|
||||
ipcRenderer.on("download-progress", (event, arg) => {
|
||||
this.percentage = Number(arg);
|
||||
});
|
||||
ipcRenderer.on("download-error", (event, arg) => {
|
||||
if (arg) {
|
||||
this.progressStaus = "exception";
|
||||
this.percentage = 40;
|
||||
this.colors = "#d81e06";
|
||||
}
|
||||
});
|
||||
ipcRenderer.on("download-paused", (event, arg) => {
|
||||
if (arg) {
|
||||
this.progressStaus = "warning";
|
||||
this.$alert("下载由于未知原因被中断!", "提示", {
|
||||
confirmButtonText: "重试",
|
||||
callback: (action) => {
|
||||
ipcRenderer.invoke("satrt-download");
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
ipcRenderer.on("download-done", (event, age) => {
|
||||
this.filePath = age.filePath;
|
||||
this.progressStaus = "success";
|
||||
console.log("下载完成啦");
|
||||
this.$alert("更新下载完成!", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
callback: (action) => {
|
||||
shell.openPath(this.filePath);
|
||||
},
|
||||
});
|
||||
});
|
||||
ipcRenderer.on("update-msg", (event, age) => {
|
||||
console.log("update-msg", age);
|
||||
switch (age.state) {
|
||||
case -1:
|
||||
const msgdata = {
|
||||
title: "发生错误",
|
||||
message: age.msg,
|
||||
};
|
||||
this.dialogVisible = false;
|
||||
ipcRenderer.invoke("open-errorbox", 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 = age.msg.percent.toFixed(1);
|
||||
break;
|
||||
case 4:
|
||||
this.progressStaus = "success";
|
||||
this.$alert("更新下载完成!", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
callback: (action) => {
|
||||
ipcRenderer.invoke("confirm-update");
|
||||
},
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
ipcRenderer.on('hot-update-status', (event, arg) => {
|
||||
console.log(arg);
|
||||
if (arg.status === 'finished') {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '热更新成功'
|
||||
});
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
openNewWin() {
|
||||
let data = {
|
||||
url: "/form/index",
|
||||
resizable: true,
|
||||
};
|
||||
ipcRenderer.invoke("open-win", data);
|
||||
},
|
||||
openDocument() {
|
||||
shell.openExternal("https://zh-sky.gitee.io/electron-vue-template-doc/Overview/#%E5%8A%9F%E8%83%BD")
|
||||
},
|
||||
getMessage() {
|
||||
message().then((res) => {
|
||||
this.$alert(res.data, "提示", {
|
||||
confirmButtonText: "确定",
|
||||
});
|
||||
});
|
||||
},
|
||||
StopServer() {
|
||||
ipcRenderer.invoke("stop-server").then((res) => {
|
||||
this.$message({
|
||||
type: "success",
|
||||
message: "已关闭",
|
||||
});
|
||||
});
|
||||
},
|
||||
StartServer() {
|
||||
ipcRenderer.invoke("statr-server").then((res) => {
|
||||
if (res) {
|
||||
this.$message({
|
||||
type: "success",
|
||||
message: res,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
// 获取electron方法
|
||||
open() { },
|
||||
CheckUpdate(data) {
|
||||
switch (data) {
|
||||
case "one":
|
||||
ipcRenderer.invoke("check-update").then((res) => {
|
||||
console.log("启动检查");
|
||||
});
|
||||
|
||||
break;
|
||||
case "two":
|
||||
ipcRenderer.invoke("start-download").then(() => {
|
||||
this.dialogVisible = true;
|
||||
});
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
},
|
||||
handleClose() {
|
||||
this.dialogVisible = false;
|
||||
},
|
||||
changeLanguage() {
|
||||
let lang = this.$i18n.locale === "zh-CN" ? "en" : "zh-CN";
|
||||
this.$i18n.locale = lang;
|
||||
},
|
||||
},
|
||||
destroyed() {
|
||||
console.log("销毁了哦");
|
||||
ipcRenderer.removeAllListeners("confirm-message");
|
||||
ipcRenderer.removeAllListeners("download-done");
|
||||
ipcRenderer.removeAllListeners("download-paused");
|
||||
ipcRenderer.removeAllListeners("confirm-stop");
|
||||
ipcRenderer.removeAllListeners("confirm-start");
|
||||
ipcRenderer.removeAllListeners("confirm-download");
|
||||
ipcRenderer.removeAllListeners("download-progress");
|
||||
ipcRenderer.removeAllListeners("download-error");
|
||||
ipcRenderer.removeAllListeners("update-msg");
|
||||
},
|
||||
computed: {
|
||||
text() {
|
||||
return this.$i18n.t("waitDataLoading");
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: "Source Sans Pro", sans-serif;
|
||||
}
|
||||
|
||||
#wrapper {
|
||||
padding: 60px 80px;
|
||||
}
|
||||
|
||||
#logo {
|
||||
height: auto;
|
||||
margin-bottom: 20px;
|
||||
width: 420px;
|
||||
}
|
||||
|
||||
main {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
main>div {
|
||||
flex-basis: 50%;
|
||||
}
|
||||
|
||||
.left-side {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.welcome {
|
||||
color: #555;
|
||||
font-size: 23px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: #2c3e50;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.title.alt {
|
||||
font-size: 18px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.doc {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.doc p {
|
||||
color: black;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.doc .el-button {
|
||||
margin-top: 10px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.doc .el-button+.el-button {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.conten {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
75
src/renderer/components/LandingPage/SystemInformation.vue
Normal file
@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="title">{{ $t("about.system") }}</div>
|
||||
<div class="items">
|
||||
<div class="item" v-for="(item, index) in tips" :key="index">
|
||||
<div class="name" v-text="item.name" />
|
||||
<div class="value" v-text="item.value" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { platform, release, arch } from "os";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
tips() {
|
||||
return [
|
||||
{ name: this.$i18n.t("about.language"), value: this.$i18n.t("about.languageValue") },
|
||||
{ name: this.$i18n.t("about.currentPagePath"), value: this.$route.path },
|
||||
{ name: this.$i18n.t("about.currentPageName"), value: this.$route.name },
|
||||
{ name: this.$i18n.t("about.vueVersion"), value: require("vue/package.json").version },
|
||||
{
|
||||
name: this.$i18n.t("about.electronVersion"),
|
||||
value: process.versions.electron || "浏览器环境",
|
||||
},
|
||||
{ name: this.$i18n.t("about.nodeVersion"), value: process.versions.node || "浏览器环境" },
|
||||
{ name: this.$i18n.t("about.systemPlatform"), value: platform() },
|
||||
{ name: this.$i18n.t("about.systemVersion"), value: release() },
|
||||
{ name: this.$i18n.t("about.systemArch"), value: arch() + "位" },
|
||||
{ name: this.$i18n.t("about.currentEnvironment"), value: process.env?.NODE_ENV }
|
||||
]
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
console.log(this.$route);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.title {
|
||||
color: #888;
|
||||
font-size: 18px;
|
||||
font-weight: initial;
|
||||
letter-spacing: 0.25px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.items {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 6px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.item .name {
|
||||
color: #6a6a6a;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
.item .value {
|
||||
color: #35495e;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
114
src/renderer/components/Pagination/index.vue
Normal file
@ -0,0 +1,114 @@
|
||||
<template>
|
||||
<div :class="{'hidden':hidden}" class="pagination-container">
|
||||
<el-pagination
|
||||
:background="background"
|
||||
:current-page.sync="currentPage"
|
||||
:page-size.sync="pageSize"
|
||||
:layout="layout"
|
||||
:page-sizes="pageSizes"
|
||||
:pager-count="pagerCount"
|
||||
:total="total"
|
||||
v-bind="$attrs"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { scrollTo } from '@/utils/scroll-to'
|
||||
|
||||
export default {
|
||||
name: 'Pagination',
|
||||
props: {
|
||||
total: {
|
||||
required: true,
|
||||
type: Number
|
||||
},
|
||||
page: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
limit: {
|
||||
type: Number,
|
||||
default: 20
|
||||
},
|
||||
pageSizes: {
|
||||
type: Array,
|
||||
default() {
|
||||
return [10, 20, 30, 50]
|
||||
}
|
||||
},
|
||||
// 移动端页码按钮的数量端默认值5
|
||||
pagerCount: {
|
||||
type: Number,
|
||||
default: document.body.clientWidth < 992 ? 5 : 7
|
||||
},
|
||||
layout: {
|
||||
type: String,
|
||||
default: 'total, sizes, prev, pager, next, jumper'
|
||||
},
|
||||
background: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
autoScroll: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
hidden: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
currentPage: {
|
||||
get() {
|
||||
return this.page
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('update:page', val)
|
||||
}
|
||||
},
|
||||
pageSize: {
|
||||
get() {
|
||||
return this.limit
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('update:limit', val)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleSizeChange(val) {
|
||||
if (this.currentPage * val > this.total) {
|
||||
this.currentPage = 1
|
||||
}
|
||||
this.$emit('pagination', { page: this.currentPage, limit: val })
|
||||
if (this.autoScroll) {
|
||||
scrollTo(0, 800)
|
||||
}
|
||||
},
|
||||
handleCurrentChange(val) {
|
||||
this.$emit('pagination', { page: val, limit: this.pageSize })
|
||||
if (this.autoScroll) {
|
||||
scrollTo(0, 800)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.pagination-container {
|
||||
background: #fff;
|
||||
padding: 32px 16px;
|
||||
}
|
||||
.pagination-container.hidden {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
57
src/renderer/components/ScrollBar/index.vue
Normal file
@ -0,0 +1,57 @@
|
||||
<template>
|
||||
<div class="scroll-container" ref="scrollContainer" @wheel.prevent="handleScroll" >
|
||||
<div class="scroll-wrapper" ref="scrollWrapper" :style="{top: top + 'px'}">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const delta = 15
|
||||
|
||||
export default {
|
||||
name: 'scrollBar',
|
||||
data() {
|
||||
return {
|
||||
top: 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleScroll(e) {
|
||||
const eventDelta = e.wheelDelta || -e.deltaY * 3
|
||||
const $container = this.$refs.scrollContainer
|
||||
const $containerHeight = $container.offsetHeight
|
||||
const $wrapper = this.$refs.scrollWrapper
|
||||
const $wrapperHeight = $wrapper.offsetHeight
|
||||
if (eventDelta > 0) {
|
||||
this.top = Math.min(0, this.top + eventDelta)
|
||||
} else {
|
||||
if ($containerHeight - delta < $wrapperHeight) {
|
||||
if (this.top < -($wrapperHeight - $containerHeight + delta)) {
|
||||
this.top = this.top
|
||||
} else {
|
||||
this.top = Math.max(this.top + eventDelta, $containerHeight - $wrapperHeight - delta)
|
||||
}
|
||||
} else {
|
||||
this.top = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
@import '../../styles/variables.scss';
|
||||
|
||||
.scroll-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: $menuBg;
|
||||
.scroll-wrapper {
|
||||
position: absolute;
|
||||
width: 100%!important;
|
||||
}
|
||||
}
|
||||
</style>
|
42
src/renderer/components/SvgIcon/index.vue
Normal file
@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<svg :class="svgClass" aria-hidden="true">
|
||||
<use :xlink:href="iconName"></use>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'svg-icon',
|
||||
props: {
|
||||
iconClass: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
className: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
iconName() {
|
||||
return `#icon-${this.iconClass}`
|
||||
},
|
||||
svgClass() {
|
||||
if (this.className) {
|
||||
return 'svg-icon ' + this.className
|
||||
} else {
|
||||
return 'svg-icon'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.svg-icon {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: -0.15em;
|
||||
fill: currentColor;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
112
src/renderer/components/Tinymce/components/EditorImage.vue
Normal file
@ -0,0 +1,112 @@
|
||||
<template>
|
||||
<div class="upload-container">
|
||||
<el-button
|
||||
:style="{ background: color, borderColor: color }"
|
||||
icon="el-icon-upload"
|
||||
size="mini"
|
||||
type="primary"
|
||||
@click="dialogVisible = true"
|
||||
>上传图片</el-button
|
||||
>
|
||||
<el-dialog :visible.sync="dialogVisible">
|
||||
<el-upload
|
||||
ref="upload"
|
||||
:multiple="true"
|
||||
:file-list="fileList"
|
||||
:show-file-list="true"
|
||||
:on-remove="handleRemove"
|
||||
:on-success="handleSuccess"
|
||||
:on-error="handleError"
|
||||
:data="picPostData"
|
||||
class="editor-slide-upload"
|
||||
action="https://jsonplaceholder.typicode.com/post/"
|
||||
list-type="picture-card"
|
||||
:limit="5"
|
||||
>
|
||||
<el-button size="small" type="primary">点击上传</el-button>
|
||||
</el-upload>
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "EditorSlideUpload",
|
||||
props: {
|
||||
color: {
|
||||
type: String,
|
||||
default: "#1890ff",
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialogVisible: false,
|
||||
listObj: {},
|
||||
fileList: [],
|
||||
picPostData: {},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
checkAllSuccess() {
|
||||
return Object.keys(this.listObj).every(
|
||||
(item) => this.listObj[item].hasSuccess
|
||||
);
|
||||
},
|
||||
handleSubmit() {
|
||||
const arr = Object.keys(this.listObj).map((v) => this.listObj[v]);
|
||||
console.log(arr);
|
||||
if (!this.checkAllSuccess()) {
|
||||
this.$message(
|
||||
"请等待所有图片上传完成,如果存在网络问题请刷新当前页重新上传"
|
||||
);
|
||||
return;
|
||||
}
|
||||
this.$emit("successCBK", arr);
|
||||
this.listObj = {};
|
||||
this.fileList = [];
|
||||
this.dialogVisible = false;
|
||||
},
|
||||
handleSuccess(response, file) {
|
||||
console.log("file", file);
|
||||
console.log("handleSuccess", response);
|
||||
const uid = file.uid;
|
||||
const objKeyArr = Object.keys(this.listObj);
|
||||
for (let i = 0, len = objKeyArr.length; i < len; i++) {
|
||||
if (this.listObj[objKeyArr[i]].uid === uid) {
|
||||
this.listObj[objKeyArr[i]].url = this.config.qiniuHost + response.key;
|
||||
this.listObj[objKeyArr[i]].hasSuccess = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
handleRemove(file) {
|
||||
const uid = file.uid;
|
||||
const objKeyArr = Object.keys(this.listObj);
|
||||
for (let i = 0, len = objKeyArr.length; i < len; i++) {
|
||||
if (this.listObj[objKeyArr[i]].uid === uid) {
|
||||
delete this.listObj[objKeyArr[i]];
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
handleError(err) {
|
||||
console.log(err);
|
||||
this.$alert(err, "发生错误", {
|
||||
confirmButtonText: "确定",
|
||||
callback: (action) => {},
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.editor-slide-upload {
|
||||
margin-bottom: 20px;
|
||||
::v-deep .el-upload--picture-card {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
60
src/renderer/components/Tinymce/dynamicLoadScript.js
Normal file
@ -0,0 +1,60 @@
|
||||
let callbacks = []
|
||||
|
||||
function loadedTinymce () {
|
||||
// to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2144
|
||||
// check is successfully downloaded script
|
||||
return window.tinymce
|
||||
}
|
||||
|
||||
const dynamicLoadScript = (src, callback) => {
|
||||
const existingScript = document.getElementById(src)
|
||||
const cb = callback || function () {}
|
||||
|
||||
if (!existingScript) {
|
||||
const script = document.createElement('script')
|
||||
console.log(src)
|
||||
script.src = src // src url for the third-party library being loaded.
|
||||
script.id = src
|
||||
document.body.appendChild(script)
|
||||
callbacks.push(cb)
|
||||
const onEnd = 'onload' in script ? stdOnEnd : ieOnEnd
|
||||
onEnd(script)
|
||||
}
|
||||
|
||||
if (existingScript && cb) {
|
||||
if (loadedTinymce()) {
|
||||
cb(null, existingScript)
|
||||
} else {
|
||||
callbacks.push(cb)
|
||||
}
|
||||
}
|
||||
|
||||
function stdOnEnd (script) {
|
||||
script.onload = function () {
|
||||
// this.onload = null here is necessary
|
||||
// because even IE9 works not like others
|
||||
this.onerror = this.onload = null
|
||||
for (const cb of callbacks) {
|
||||
cb(null, script)
|
||||
}
|
||||
callbacks = null
|
||||
}
|
||||
script.onerror = function () {
|
||||
this.onerror = this.onload = null
|
||||
cb(new Error('无法加载 ' + src), script)
|
||||
}
|
||||
}
|
||||
|
||||
function ieOnEnd (script) {
|
||||
script.onreadystatechange = function () {
|
||||
if (this.readyState !== 'complete' && this.readyState !== 'loaded') return
|
||||
this.onreadystatechange = null
|
||||
for (const cb of callbacks) {
|
||||
cb(null, script) // there is no way to catch loading errors in IE8
|
||||
}
|
||||
callbacks = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default dynamicLoadScript
|
223
src/renderer/components/Tinymce/index.vue
Normal file
@ -0,0 +1,223 @@
|
||||
<template>
|
||||
<div
|
||||
:class="{ fullscreen: fullscreen }"
|
||||
class="tinymce-container"
|
||||
:style="{ width: containerWidth }"
|
||||
>
|
||||
<textarea :id="tinymceId" class="tinymce-textarea" />
|
||||
<div class="editor-custom-btn-container">
|
||||
<editorImage
|
||||
color="#1890ff"
|
||||
class="editor-upload-btn"
|
||||
@successCBK="imageSuccessCBK"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* docs:
|
||||
* https://panjiachen.github.io/vue-element-admin-site/feature/component/rich-editor.html#tinymce
|
||||
*/
|
||||
import editorImage from "./components/EditorImage";
|
||||
import plugins from "./plugins";
|
||||
import toolbar from "./toolbar";
|
||||
import load from "./dynamicLoadScript";
|
||||
|
||||
const tinymceFile = `${
|
||||
process.browser ? "static" : __static
|
||||
}/tinymce/tinymce.min.js`;
|
||||
|
||||
export default {
|
||||
name: "Tinymce",
|
||||
components: { editorImage },
|
||||
props: {
|
||||
id: {
|
||||
type: String,
|
||||
default: function () {
|
||||
return (
|
||||
"vue-tinymce-" +
|
||||
+new Date() +
|
||||
((Math.random() * 1000).toFixed(0) + "")
|
||||
);
|
||||
},
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
toolbar: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default() {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
menubar: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
height: {
|
||||
type: [Number, String],
|
||||
required: false,
|
||||
default: 360,
|
||||
},
|
||||
width: {
|
||||
type: [Number, String],
|
||||
required: false,
|
||||
default: "auto",
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
hasChange: false,
|
||||
hasInit: false,
|
||||
tinymceId: this.id,
|
||||
fullscreen: false,
|
||||
languageTypeList: {
|
||||
zh: "zh_CN",
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
containerWidth() {
|
||||
const width = this.width;
|
||||
if (/^[\d]+(\.[\d]+)?$/.test(width)) {
|
||||
// matches `100`, `'100'`
|
||||
return `${width}px`;
|
||||
}
|
||||
return width;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
value(val) {
|
||||
if (!this.hasChange && this.hasInit) {
|
||||
this.$nextTick(() =>
|
||||
window.tinymce.get(this.tinymceId).setContent(val || "")
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
activated() {
|
||||
if (window.tinymce) {
|
||||
this.initTinymce();
|
||||
}
|
||||
},
|
||||
deactivated() {
|
||||
this.destroyTinymce();
|
||||
},
|
||||
destroyed() {
|
||||
this.destroyTinymce();
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
// dynamic load tinymce from cdn
|
||||
load(tinymceFile, (err) => {
|
||||
if (err) {
|
||||
this.$message.error(err.message);
|
||||
return;
|
||||
}
|
||||
this.initTinymce();
|
||||
});
|
||||
},
|
||||
initTinymce() {
|
||||
const _this = this;
|
||||
window.tinymce.init({
|
||||
selector: `#${this.tinymceId}`,
|
||||
language: this.languageTypeList["zh"],
|
||||
min_height: this.height,
|
||||
body_class: "panel-body ",
|
||||
draggable_modal: true,
|
||||
object_resizing: false,
|
||||
toolbar: this.toolbar.length > 0 ? this.toolbar : toolbar,
|
||||
menubar: this.menubar,
|
||||
plugins: plugins,
|
||||
fontsize_formats: "12px 14px 16px 18px 24px 36px 48px 56px 72px",
|
||||
font_formats:
|
||||
"微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;",
|
||||
end_container_on_empty_block: true,
|
||||
powerpaste_word_import: "clean",
|
||||
code_dialog_height: 450,
|
||||
code_dialog_width: 1000,
|
||||
custom_undo_redo_levels: 50,
|
||||
advlist_bullet_styles: "square",
|
||||
advlist_number_styles: "default",
|
||||
imagetools_cors_hosts: ["www.tinymce.com", "codepen.io"],
|
||||
default_link_target: "_blank",
|
||||
link_title: false,
|
||||
branding: false,
|
||||
nonbreaking_force_tab: true, // inserting nonbreaking space need Nonbreaking Space Plugin
|
||||
init_instance_callback: (editor) => {
|
||||
if (_this.value) {
|
||||
editor.setContent(_this.value);
|
||||
}
|
||||
_this.hasInit = true;
|
||||
editor.on("NodeChange Change KeyUp SetContent", () => {
|
||||
this.hasChange = true;
|
||||
this.$emit("input", editor.getContent());
|
||||
});
|
||||
},
|
||||
setup(editor) {
|
||||
editor.on("FullscreenStateChanged", (e) => {
|
||||
_this.fullscreen = e.state;
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
destroyTinymce() {
|
||||
const tinymce = window.tinymce.get(this.tinymceId);
|
||||
if (this.fullscreen) {
|
||||
tinymce.execCommand("mceFullScreen");
|
||||
}
|
||||
|
||||
if (tinymce) {
|
||||
tinymce.destroy();
|
||||
}
|
||||
},
|
||||
setContent(value) {
|
||||
window.tinymce.get(this.tinymceId).setContent(value);
|
||||
},
|
||||
getContent() {
|
||||
window.tinymce.get(this.tinymceId).getContent();
|
||||
},
|
||||
imageSuccessCBK(arr) {
|
||||
const _this = this;
|
||||
arr.forEach((v) => {
|
||||
window.tinymce
|
||||
.get(_this.tinymceId)
|
||||
.insertContent(`<img class="wscnph" src="${v.url}" >`);
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tinymce-container {
|
||||
position: relative;
|
||||
line-height: normal;
|
||||
}
|
||||
.tinymce-container >>> .mce-fullscreen {
|
||||
z-index: 10000;
|
||||
}
|
||||
.tinymce-textarea {
|
||||
visibility: hidden;
|
||||
z-index: -1;
|
||||
}
|
||||
.editor-custom-btn-container {
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
top: 4px;
|
||||
}
|
||||
.fullscreen .editor-custom-btn-container {
|
||||
z-index: 10000;
|
||||
position: fixed;
|
||||
}
|
||||
.editor-upload-btn {
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
7
src/renderer/components/Tinymce/plugins.js
Normal file
@ -0,0 +1,7 @@
|
||||
// Any plugins you want to use has to be imported
|
||||
// Detail plugins list see https://www.tinymce.com/docs/plugins/
|
||||
// Custom builds see https://www.tinymce.com/download/custom-builds/
|
||||
|
||||
const plugins = ['print preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template code codesample table charmap hr pagebreak nonbreaking anchor insertdatetime advlist lists wordcount imagetools help emoticons autoresize']
|
||||
|
||||
export default plugins
|
9
src/renderer/components/Tinymce/toolbar.js
Normal file
@ -0,0 +1,9 @@
|
||||
// Here is a list of the toolbar
|
||||
// Detail list see https://www.tinymce.com/docs/advanced/editor-control-identifiers/#toolbarcontrols
|
||||
|
||||
// eslint-disable-next-line no-multi-str
|
||||
const toolbar = ['code undo redo restoredraft | cut copy paste pastetext | forecolor backcolor bold italic underline strikethrough link anchor | alignleft aligncenter alignright alignjustify outdent indent | \
|
||||
styleselect formatselect fontselect fontsizeselect | bullist numlist | blockquote subscript superscript removeformat | \
|
||||
table image media charmap emoticons hr pagebreak insertdatetime print preview | fullscreen | bdmap indent2em lineheight formatpainter axupimgs']
|
||||
|
||||
export default toolbar
|
119
src/renderer/components/title/index.vue
Normal file
@ -0,0 +1,119 @@
|
||||
<!-- -->
|
||||
<template>
|
||||
<div class="window-title" v-if="!IsUseSysTitle&&!IsWeb">
|
||||
<!-- 软件logo预留位置 -->
|
||||
<div style="-webkit-app-region: drag;" class="logo" v-if="isNotMac">
|
||||
<img class="logo" src="@/assets/logo.png" />
|
||||
</div>
|
||||
<!-- 菜单栏位置 -->
|
||||
<div></div>
|
||||
<!-- 中间标题位置 -->
|
||||
<div style="-webkit-app-region: drag;" class="title"></div>
|
||||
<div class="controls-container" v-if="isNotMac">
|
||||
<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 { ipcRenderer } from "electron";
|
||||
export default {
|
||||
data: () => ({
|
||||
mix: false,
|
||||
IsUseSysTitle: false,
|
||||
isNotMac: process.platform !== "darwin",
|
||||
IsWeb: process.env.IS_WEB
|
||||
}),
|
||||
|
||||
components: {},
|
||||
created() {
|
||||
ipcRenderer.invoke("IsUseSysTitle").then(res => {
|
||||
this.IsUseSysTitle = res;
|
||||
});
|
||||
},
|
||||
|
||||
mounted() {
|
||||
ipcRenderer.on("w-max",(event,state)=>{
|
||||
this.mix = state
|
||||
})
|
||||
},
|
||||
|
||||
methods: {
|
||||
Mini() {
|
||||
ipcRenderer.invoke("windows-mini");
|
||||
},
|
||||
MixOrReduction() {
|
||||
ipcRenderer.invoke("window-max").then(res=>{
|
||||
this.mix = res.status
|
||||
})
|
||||
},
|
||||
Close() {
|
||||
ipcRenderer.invoke("window-close");
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
ipcRenderer.removeAllListeners("w-max");
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style rel='stylesheet/scss' lang='scss' scoped>
|
||||
.window-title {
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
display: flex;
|
||||
-webkit-app-region: drag;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
z-index: 99999;
|
||||
.title {
|
||||
text-align: center;
|
||||
}
|
||||
.logo {
|
||||
margin-left: 8px;
|
||||
margin-top: 5px;
|
||||
width:20px;
|
||||
height: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>
|
63
src/renderer/directive/dialog/drag.js
Normal file
@ -0,0 +1,63 @@
|
||||
/**
|
||||
* v-dialogDrag 弹窗拖拽
|
||||
*/
|
||||
|
||||
export default {
|
||||
bind(el, binding, vnode, oldVnode) {
|
||||
const value = binding.value
|
||||
if (value == false) return
|
||||
// 获取拖拽内容头部
|
||||
const dialogHeaderEl = el.querySelector('.el-dialog__header');
|
||||
const dragDom = el.querySelector('.el-dialog');
|
||||
dialogHeaderEl.style.cursor = 'move';
|
||||
// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
|
||||
const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null);
|
||||
dragDom.style.position = 'absolute';
|
||||
dragDom.style.marginTop = 0;
|
||||
let width = dragDom.style.width;
|
||||
if (width.includes('%')) {
|
||||
width = +document.body.clientWidth * (+width.replace(/\%/g, '') / 100);
|
||||
} else {
|
||||
width = +width.replace(/\px/g, '');
|
||||
}
|
||||
dragDom.style.left = `${(document.body.clientWidth - width) / 2}px`;
|
||||
// 鼠标按下事件
|
||||
dialogHeaderEl.onmousedown = (e) => {
|
||||
// 鼠标按下,计算当前元素距离可视区的距离 (鼠标点击位置距离可视窗口的距离)
|
||||
const disX = e.clientX - dialogHeaderEl.offsetLeft;
|
||||
const disY = e.clientY - dialogHeaderEl.offsetTop;
|
||||
|
||||
// 获取到的值带px 正则匹配替换
|
||||
let styL, styT;
|
||||
|
||||
// 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
|
||||
if (sty.left.includes('%')) {
|
||||
styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, '') / 100);
|
||||
styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, '') / 100);
|
||||
} else {
|
||||
styL = +sty.left.replace(/\px/g, '');
|
||||
styT = +sty.top.replace(/\px/g, '');
|
||||
};
|
||||
|
||||
// 鼠标拖拽事件
|
||||
document.onmousemove = function (e) {
|
||||
// 通过事件委托,计算移动的距离 (开始拖拽至结束拖拽的距离)
|
||||
const l = e.clientX - disX;
|
||||
const t = e.clientY - disY;
|
||||
|
||||
let finallyL = l + styL
|
||||
let finallyT = t + styT
|
||||
|
||||
// 移动当前元素
|
||||
dragDom.style.left = `${finallyL}px`;
|
||||
dragDom.style.top = `${finallyT}px`;
|
||||
|
||||
};
|
||||
|
||||
document.onmouseup = function (e) {
|
||||
document.onmousemove = null;
|
||||
document.onmouseup = null;
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
33
src/renderer/directive/dialog/dragHeight.js
Normal file
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* v-dialogDragWidth 可拖动弹窗高度(右下角)
|
||||
*/
|
||||
|
||||
export default {
|
||||
bind(el) {
|
||||
const dragDom = el.querySelector('.el-dialog');
|
||||
const lineEl = document.createElement('div');
|
||||
lineEl.style = 'width: 6px; background: inherit; height: 10px; position: absolute; right: 0; bottom: 0; margin: auto; z-index: 1; cursor: nwse-resize;';
|
||||
lineEl.addEventListener('mousedown',
|
||||
function(e) {
|
||||
// 鼠标按下,计算当前元素距离可视区的距离
|
||||
const disX = e.clientX - el.offsetLeft;
|
||||
const disY = e.clientY - el.offsetTop;
|
||||
// 当前宽度 高度
|
||||
const curWidth = dragDom.offsetWidth;
|
||||
const curHeight = dragDom.offsetHeight;
|
||||
document.onmousemove = function(e) {
|
||||
e.preventDefault(); // 移动时禁用默认事件
|
||||
// 通过事件委托,计算移动的距离
|
||||
const xl = e.clientX - disX;
|
||||
const yl = e.clientY - disY
|
||||
dragDom.style.width = `${curWidth + xl}px`;
|
||||
dragDom.style.height = `${curHeight + yl}px`;
|
||||
};
|
||||
document.onmouseup = function(e) {
|
||||
document.onmousemove = null;
|
||||
document.onmouseup = null;
|
||||
};
|
||||
}, false);
|
||||
dragDom.appendChild(lineEl);
|
||||
}
|
||||
}
|
29
src/renderer/directive/dialog/dragWidth.js
Normal file
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* v-dialogDragWidth 可拖动弹窗宽度(右侧边)
|
||||
*/
|
||||
|
||||
export default {
|
||||
bind(el) {
|
||||
const dragDom = el.querySelector('.el-dialog');
|
||||
const lineEl = document.createElement('div');
|
||||
lineEl.style = 'width: 5px; background: inherit; height: 80%; position: absolute; right: 0; top: 0; bottom: 0; margin: auto; z-index: 1; cursor: w-resize;';
|
||||
lineEl.addEventListener('mousedown',
|
||||
function (e) {
|
||||
// 鼠标按下,计算当前元素距离可视区的距离
|
||||
const disX = e.clientX - el.offsetLeft;
|
||||
// 当前宽度
|
||||
const curWidth = dragDom.offsetWidth;
|
||||
document.onmousemove = function (e) {
|
||||
e.preventDefault(); // 移动时禁用默认事件
|
||||
// 通过事件委托,计算移动的距离
|
||||
const l = e.clientX - disX;
|
||||
dragDom.style.width = `${curWidth + l}px`;
|
||||
};
|
||||
document.onmouseup = function (e) {
|
||||
document.onmousemove = null;
|
||||
document.onmouseup = null;
|
||||
};
|
||||
}, false);
|
||||
dragDom.appendChild(lineEl);
|
||||
}
|
||||
}
|
23
src/renderer/directive/index.js
Normal file
@ -0,0 +1,23 @@
|
||||
import hasRole from './permission/hasRole'
|
||||
import hasPermi from './permission/hasPermi'
|
||||
import dialogDrag from './dialog/drag'
|
||||
import dialogDragWidth from './dialog/dragWidth'
|
||||
import dialogDragHeight from './dialog/dragHeight'
|
||||
import clipboard from './module/clipboard'
|
||||
|
||||
const install = function(Vue) {
|
||||
Vue.directive('hasRole', hasRole)
|
||||
Vue.directive('hasPermi', hasPermi)
|
||||
Vue.directive('clipboard', clipboard)
|
||||
Vue.directive('dialogDrag', dialogDrag)
|
||||
Vue.directive('dialogDragWidth', dialogDragWidth)
|
||||
Vue.directive('dialogDragHeight', dialogDragHeight)
|
||||
}
|
||||
|
||||
if (window.Vue) {
|
||||
window['hasRole'] = hasRole
|
||||
window['hasPermi'] = hasPermi
|
||||
Vue.use(install); // eslint-disable-line
|
||||
}
|
||||
|
||||
export default install
|
53
src/renderer/directive/module/clipboard.js
Normal file
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* v-clipboard 文字复制剪贴
|
||||
*/
|
||||
|
||||
import Clipboard from 'clipboard'
|
||||
export default {
|
||||
bind(el, binding, vnode) {
|
||||
switch (binding.arg) {
|
||||
case 'success':
|
||||
el._vClipBoard_success = binding.value;
|
||||
break;
|
||||
case 'error':
|
||||
el._vClipBoard_error = binding.value;
|
||||
break;
|
||||
default: {
|
||||
const clipboard = new Clipboard(el, {
|
||||
text: () => binding.value,
|
||||
action: () => binding.arg === 'cut' ? 'cut' : 'copy'
|
||||
});
|
||||
clipboard.on('success', e => {
|
||||
const callback = el._vClipBoard_success;
|
||||
callback && callback(e);
|
||||
});
|
||||
clipboard.on('error', e => {
|
||||
const callback = el._vClipBoard_error;
|
||||
callback && callback(e);
|
||||
});
|
||||
el._vClipBoard = clipboard;
|
||||
}
|
||||
}
|
||||
},
|
||||
update(el, binding) {
|
||||
if (binding.arg === 'success') {
|
||||
el._vClipBoard_success = binding.value;
|
||||
} else if (binding.arg === 'error') {
|
||||
el._vClipBoard_error = binding.value;
|
||||
} else {
|
||||
el._vClipBoard.text = function () { return binding.value; };
|
||||
el._vClipBoard.action = () => binding.arg === 'cut' ? 'cut' : 'copy';
|
||||
}
|
||||
},
|
||||
unbind(el, binding) {
|
||||
if (!el._vClipboard) return
|
||||
if (binding.arg === 'success') {
|
||||
delete el._vClipBoard_success;
|
||||
} else if (binding.arg === 'error') {
|
||||
delete el._vClipBoard_error;
|
||||
} else {
|
||||
el._vClipBoard.destroy();
|
||||
delete el._vClipBoard;
|
||||
}
|
||||
}
|
||||
}
|
22
src/renderer/directive/permission/hasPermi.js
Normal file
@ -0,0 +1,22 @@
|
||||
/**
|
||||
* v-hasPermi 操作权限处理
|
||||
*/
|
||||
export default {
|
||||
inserted(el, binding, vnode) {
|
||||
const { value } = binding
|
||||
const all_permission = "*:*:*";
|
||||
const permissions = localStorage.getItem("permissions") ? JSON.parse(localStorage.getItem("permissions")) : [];
|
||||
|
||||
if (permissions.length > 0 && value && value instanceof Array && value.length > 0) {
|
||||
const permissionFlag = value
|
||||
const hasPermissions = permissions.some(permission => {
|
||||
return all_permission === permission || permissionFlag.includes(permission)
|
||||
})
|
||||
if (!hasPermissions) {
|
||||
el.parentNode && el.parentNode.removeChild(el)
|
||||
}
|
||||
} else {
|
||||
throw new Error(`请设置操作权限标签值`)
|
||||
}
|
||||
}
|
||||
}
|
21
src/renderer/directive/permission/hasRole.js
Normal file
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* v-hasRole 角色权限处理
|
||||
*/
|
||||
export default {
|
||||
inserted(el, binding, vnode) {
|
||||
const { value } = binding
|
||||
const super_admin = "admin";
|
||||
const roles = localStorage.getItem("roles") ? localStorage.getItem("roles") : [];
|
||||
if (roles.length > 0 && value && value instanceof Array && value.length > 0) {
|
||||
const roleFlag = value
|
||||
const hasRole = roles.some(role => {
|
||||
return super_admin === role || roleFlag.includes(role)
|
||||
})
|
||||
if (!hasRole) {
|
||||
el.parentNode && el.parentNode.removeChild(el)
|
||||
}
|
||||
} else {
|
||||
throw new Error(`请设置角色权限标签值"`)
|
||||
}
|
||||
}
|
||||
}
|
17
src/renderer/error.js
Normal file
@ -0,0 +1,17 @@
|
||||
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()
|
||||
}
|
||||
})
|
||||
}
|
7
src/renderer/hooks/use-router.js
Normal file
@ -0,0 +1,7 @@
|
||||
import { getCurrentInstance } from 'vue'
|
||||
export const useRoute = () => {
|
||||
return getCurrentInstance()?.proxy.$route
|
||||
}
|
||||
export const useRouter = () => {
|
||||
return getCurrentInstance()?.proxy.$router
|
||||
}
|
25
src/renderer/i18n/index.js
Normal file
@ -0,0 +1,25 @@
|
||||
export default function loadLanguage() {
|
||||
const context = require.context("./languages", false, /([a-z_]+)\.js$/i)
|
||||
|
||||
const languages = context
|
||||
.keys()
|
||||
.map((key) => ({ key, name: key.match(/([a-z_-]+)\.js$/i)[1] }))
|
||||
.reduce(
|
||||
(languages, {key, name}) => {
|
||||
let lang;
|
||||
try {
|
||||
// 引入 element-ui 语言包
|
||||
lang = Object.assign(context(key).lang, require(`element-ui/lib/locale/lang/${name}`).default);
|
||||
} catch(err) {
|
||||
lang = context(key).lang
|
||||
}
|
||||
return {
|
||||
...languages,
|
||||
[name]: lang
|
||||
}
|
||||
},
|
||||
{}
|
||||
)
|
||||
|
||||
return languages
|
||||
}
|
30
src/renderer/i18n/languages/en.js
Normal file
@ -0,0 +1,30 @@
|
||||
export const lang = {
|
||||
welcome: "Welcome use the framework",
|
||||
buttonTips: "You can click buttons to experience",
|
||||
waitDataLoading: "Wait data loading",
|
||||
about: {
|
||||
system: "About system",
|
||||
language: "language:",
|
||||
languageValue: "English",
|
||||
currentPagePath: "current page path:",
|
||||
currentPageName: "current page name:",
|
||||
vueVersion: "Vue version:",
|
||||
electronVersion: "Electron version:",
|
||||
nodeVersion: "Node version:",
|
||||
systemPlatform: "system platform:",
|
||||
systemVersion: "system version:",
|
||||
systemArch: "system arch:",
|
||||
currentEnvironment:"current environment:"
|
||||
},
|
||||
buttons: {
|
||||
console: "Console",
|
||||
checkUpdate: "Check update",
|
||||
checkUpdate2: "Check update(plan 2)",
|
||||
startServer: "Start server",
|
||||
stopServer: "Stop server",
|
||||
viewMessage: "view message",
|
||||
openNewWindow: "Open new window",
|
||||
openDocument: "Open document",
|
||||
changeLanguage: "Change language"
|
||||
}
|
||||
}
|
30
src/renderer/i18n/languages/zh-CN.js
Normal file
@ -0,0 +1,30 @@
|
||||
export const lang = {
|
||||
welcome: "欢迎进入本框架",
|
||||
buttonTips: "您可以点击的按钮测试功能",
|
||||
waitDataLoading: "等待数据读取",
|
||||
about: {
|
||||
system: "关于系统",
|
||||
language: "语言:",
|
||||
languageValue: "中文简体",
|
||||
currentPagePath: "当前页面路径:",
|
||||
currentPageName: "当前页面名称:",
|
||||
vueVersion: "Vue版本:",
|
||||
electronVersion: "Electron版本:",
|
||||
nodeVersion: "Node版本:",
|
||||
systemPlatform: "系统平台:",
|
||||
systemVersion: "系统版本:",
|
||||
systemArch: "系统位数:",
|
||||
currentEnvironment:'当前环境:'
|
||||
},
|
||||
buttons: {
|
||||
console: "控制台打印",
|
||||
checkUpdate: "检查更新",
|
||||
checkUpdate2: "检查更新(第二种方法)",
|
||||
startServer: "启动内置服务端",
|
||||
stopServer: "关闭内置服务端",
|
||||
viewMessage: "查看消息",
|
||||
openNewWindow: "打开新窗口",
|
||||
openDocument: "打开文档",
|
||||
changeLanguage: "切换语言"
|
||||
}
|
||||
}
|
9
src/renderer/icons/index.js
Normal file
@ -0,0 +1,9 @@
|
||||
import Vue from 'vue'
|
||||
import SvgIcon from '@/components/SvgIcon'// svg组件
|
||||
|
||||
// register globally
|
||||
Vue.component('svg-icon', SvgIcon)
|
||||
|
||||
const requireAll = requireContext => requireContext.keys().map(requireContext)
|
||||
const req = require.context('./svg', false, /\.svg$/)
|
||||
requireAll(req)
|
1
src/renderer/icons/svg/close.svg
Normal file
@ -0,0 +1 @@
|
||||
<?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>
|
After Width: | Height: | Size: 366 B |
529
src/renderer/icons/svg/electron-logo.svg
Normal file
@ -0,0 +1,529 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="256px" height="256px" viewBox="0 0 256 256" enable-background="new 0 0 256 256" xml:space="preserve"> <image id="image0" width="256" height="256" x="0" y="0"
|
||||
href="data:image/png;base64,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" />
|
||||
</svg>
|
After Width: | Height: | Size: 40 KiB |
1
src/renderer/icons/svg/example.svg
Normal file
@ -0,0 +1 @@
|
||||
<?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="1511504199105" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1815" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M770.56 460.8h250.88C998.4 220.16 803.84 25.6 563.2 2.56v250.88c104.96 20.48 186.88 102.4 207.36 207.36z m0 0M460.8 253.44V2.56C220.16 25.6 25.6 220.16 2.56 460.8h250.88c20.48-104.96 102.4-186.88 207.36-207.36z m0 0M563.2 770.56v250.88c243.2-23.04 435.2-217.6 460.8-460.8H773.12C750.08 668.16 668.16 750.08 563.2 770.56z m0 0M253.44 563.2H2.56c23.04 243.2 217.6 435.2 460.8 460.8V773.12C355.84 750.08 273.92 668.16 253.44 563.2z m0 0" fill="" p-id="1816"></path></svg>
|
After Width: | Height: | Size: 852 B |
1
src/renderer/icons/svg/eye-open.svg
Normal file
@ -0,0 +1 @@
|
||||
<?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>
|
After Width: | Height: | Size: 1.5 KiB |
1
src/renderer/icons/svg/eye.svg
Normal file
@ -0,0 +1 @@
|
||||
<?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="1503993826520" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7878" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M941.677063 391.710356c9.337669-14.005992 6.224772-32.68133-6.224772-43.575447-14.005992-10.894118-32.68133-7.78122-43.575447 6.224771-1.556449 1.556449-174.300768 205.426673-379.727441 205.426673-199.200878 0-379.727441-205.426673-381.28389-206.982098-10.894118-12.450567-31.124881-14.005992-43.575448-3.112898-12.450567 10.894118-14.005992 31.124881-3.112897 43.575448 3.112897 4.668323 40.46255 46.687322 99.600439 93.375667l-79.369676 82.48155c-12.450567 12.450567-10.894118 32.68133 1.556449 43.575448 3.112897 6.224772 10.894118 9.337669 18.675338 9.337669 7.78122 0 15.562441-3.112897 21.787213-9.337669l85.594447-88.706321c40.46255 28.013007 88.706321 54.469566 141.619438 73.14388L340.959485 707.631586c-4.668323 17.118889 4.669346 34.237779 21.787213 38.906101h9.337669c14.005992 0 26.456558-9.337669 29.568432-23.343661l32.68133-110.494556c24.90011 4.668323 51.356668 7.78122 77.813227 7.78122s52.913117-3.112897 77.813227-7.78122l32.68133 108.938108c3.112897 14.005992 17.118889 23.343661 29.569456 23.343661 3.112897 0 6.224772 0 7.78122-1.556449 17.118889-4.669346 26.456558-21.787212 21.788236-38.906102l-32.68133-108.938108c52.913117-18.675338 101.156888-45.131897 141.619438-73.14388l84.037998 87.150896c6.224772 6.224772 14.005992 9.337669 21.787212 9.337669 7.78122 0 15.562441-3.112897 21.787212-9.337669 12.450567-12.450567 12.450567-31.124881 1.556449-43.575448l-79.369675-82.48155c63.808258-46.688345 101.158934-91.820242 101.158934-91.820242z" p-id="7879"></path></svg>
|
After Width: | Height: | Size: 1.8 KiB |
1
src/renderer/icons/svg/form.svg
Normal file
@ -0,0 +1 @@
|
||||
<?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="1511504319223" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3230" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M942.827259 80.3367c-11.42419-11.406794-26.41051-17.117866-41.377386-17.117866-14.985296 0-29.952172 5.711072-41.358967 17.117866L719.392444 221.014696l-19.441794 19.441794L681.577187 258.832 569.516971 370.909611 375.99749 564.411697l0 0.019443 0 84.372619 81.145112 0 0.010233 0 95.418186-95.435583 213.398228-213.400275 3.14155-3.14155-0.019443 0 9.979282-9.977235 0 0L942.827259 163.073052C965.697129 140.259464 965.697129 103.186104 942.827259 80.3367z" p-id="3231"></path><path d="M793.542234 367.521444 580.14196 580.939115 484.72582 676.376745 473.299583 687.800935 457.152834 687.800935 375.99749 687.800935 337.000314 687.800935 337.000314 648.803759 337.000314 564.411697 337.000314 548.264948 348.424504 536.838711 541.943986 343.338672 654.004201 231.259014 665.428392 219.834824 64.020082 219.834824 64.020082 960.781166 804.966425 960.781166 804.966425 356.116697 796.607036 364.475062Z" p-id="3232"></path></svg>
|
After Width: | Height: | Size: 1.3 KiB |
1
src/renderer/icons/svg/logo.svg
Normal file
@ -0,0 +1 @@
|
||||
<?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="1564902100209" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="840" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" height="300"><defs><style type="text/css"></style></defs><path d="M615.6 123.6h165.5L512 589.7 242.9 123.6H63.5L512 900.4l448.5-776.9z" fill="#41B883" p-id="841"></path><path d="M781.1 123.6H615.6L512 303 408.4 123.6H242.9L512 589.7z" fill="#34495E" p-id="842"></path></svg>
|
After Width: | Height: | Size: 584 B |
1
src/renderer/icons/svg/mini.svg
Normal file
@ -0,0 +1 @@
|
||||
<?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>
|
After Width: | Height: | Size: 274 B |
1
src/renderer/icons/svg/mix.svg
Normal file
@ -0,0 +1 @@
|
||||
<?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>
|
After Width: | Height: | Size: 294 B |
1
src/renderer/icons/svg/nested.svg
Normal file
@ -0,0 +1 @@
|
||||
<?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="1529559567446" class="icon" style="" viewBox="0 0 1167 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1767" xmlns:xlink="http://www.w3.org/1999/xlink" width="227.9296875" height="200"><defs><style type="text/css"></style></defs><path d="M0.015952 74.459413A2.286 2.286 1440 1 0 145.85218 74.459413 2.286 2.286 1440 1 0 0.015952 74.459413zM291.720312 1.525347 1166.801488 1.525347 1166.801488 147.361574 291.720312 147.361574zM291.720312 366.163773A2.286 2.286 1440 1 0 437.55654 366.163773 2.286 2.286 1440 1 0 291.720312 366.163773zM583.424672 293.229707 1166.801488 293.229707 1166.801488 439.065934 583.424672 439.065934zM291.720312 949.540588A2.286 2.286 1440 1 0 437.55654 949.540588 2.286 2.286 1440 1 0 291.720312 949.540588zM583.424672 876.638427 1166.801488 876.638427 1166.801488 1022.474654 583.424672 1022.474654zM583.424672 657.836228A2.286 2.286 1440 1 0 729.2609 657.836228 2.286 2.286 1440 1 0 583.424672 657.836228zM875.129032 584.934067 1166.801488 584.934067 1166.801488 730.770294 875.129032 730.770294z" p-id="1768"></path></svg>
|
After Width: | Height: | Size: 1.2 KiB |
1
src/renderer/icons/svg/password.svg
Normal file
@ -0,0 +1 @@
|
||||
<?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="1503994678729" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9229" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M780.8 354.579692 665.6 354.579692 665.6 311.689846c0-72.310154-19.849846-193.299692-153.6-193.299692-138.870154 0-153.6 135.049846-153.6 193.299692l0 42.889846L243.2 354.579692 243.2 311.689846C243.2 122.249846 348.790154 0 512 0s268.8 122.249846 268.8 311.689846L780.8 354.579692zM588.8 669.420308C588.8 625.900308 554.220308 590.769231 512 590.769231s-76.8 35.131077-76.8 78.651077c0 29.459692 15.399385 54.468923 38.439385 67.820308l0 89.639385c0 21.740308 17.250462 39.699692 38.4 39.699692s38.4-17.959385 38.4-39.699692l0-89.639385C573.44 723.889231 588.8 698.88 588.8 669.420308zM896 512l0 393.609846c0 65.260308-51.869538 118.390154-115.2 118.390154L243.2 1024c-63.291077 0-115.2-53.129846-115.2-118.390154L128 512c0-65.220923 51.869538-118.390154 115.2-118.390154l537.6 0C844.130462 393.609846 896 446.779077 896 512z" p-id="9230"></path></svg>
|
After Width: | Height: | Size: 1.2 KiB |
1
src/renderer/icons/svg/reduction.svg
Normal file
@ -0,0 +1 @@
|
||||
<?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>
|
After Width: | Height: | Size: 361 B |
1
src/renderer/icons/svg/table.svg
Normal file
@ -0,0 +1 @@
|
||||
<?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="1511504440567" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5070" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M568.6 0h454.9v454.9H568.6V0z m0 568.6h454.9v454.9H568.6V568.6zM0 568.6h454.9v454.9H0V568.6zM0 0h454.9v454.9H0V0z" fill="" p-id="5071"></path></svg>
|
After Width: | Height: | Size: 532 B |