no message
This commit is contained in:
parent
79a94d25bd
commit
1d20f529a0
112
electron/build.js
vendored
112
electron/build.js
vendored
@ -3,103 +3,11 @@ const fse = require('fs-extra');
|
|||||||
const path = require('path')
|
const path = require('path')
|
||||||
const inquirer = require('inquirer');
|
const inquirer = require('inquirer');
|
||||||
const child_process = require('child_process');
|
const child_process = require('child_process');
|
||||||
|
const utils = require('./utils');
|
||||||
const config = require('../package.json')
|
const config = require('../package.json')
|
||||||
const argv = process.argv;
|
const argv = process.argv;
|
||||||
const env = require('dotenv').config({ path: './.env' })
|
const env = require('dotenv').config({ path: './.env' })
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除文件夹及文件
|
|
||||||
* @param path
|
|
||||||
*/
|
|
||||||
function deleteFile(path) {
|
|
||||||
let files = [];
|
|
||||||
if (fs.existsSync(path)) {
|
|
||||||
files = fs.readdirSync(path);
|
|
||||||
files.forEach(function (file, index) {
|
|
||||||
let curPath = path + "/" + file;
|
|
||||||
if (fs.statSync(curPath).isDirectory()) {
|
|
||||||
deleteFile(curPath);
|
|
||||||
} else {
|
|
||||||
fs.unlinkSync(curPath);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
fs.rmdirSync(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 复制文件
|
|
||||||
* @param srcPath
|
|
||||||
* @param tarPath
|
|
||||||
* @param cb
|
|
||||||
*/
|
|
||||||
function copyFile(srcPath, tarPath, cb) {
|
|
||||||
let rs = fs.createReadStream(srcPath)
|
|
||||||
rs.on('error', function (err) {
|
|
||||||
if (err) {
|
|
||||||
console.log('read error', srcPath)
|
|
||||||
}
|
|
||||||
cb && cb(err)
|
|
||||||
})
|
|
||||||
let ws = fs.createWriteStream(tarPath)
|
|
||||||
ws.on('error', function (err) {
|
|
||||||
if (err) {
|
|
||||||
console.log('write error', tarPath)
|
|
||||||
}
|
|
||||||
cb && cb(err)
|
|
||||||
})
|
|
||||||
ws.on('close', function (ex) {
|
|
||||||
cb && cb(ex)
|
|
||||||
})
|
|
||||||
rs.pipe(ws)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 给地址加上前后
|
|
||||||
* @param str
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
function formatUrl(str) {
|
|
||||||
let url;
|
|
||||||
if (str.substring(0, 7) === "http://" ||
|
|
||||||
str.substring(0, 8) === "https://") {
|
|
||||||
url = str.trim();
|
|
||||||
} else {
|
|
||||||
url = "http://" + str.trim();
|
|
||||||
}
|
|
||||||
if (url.substring(url.length - 1) != "/") {
|
|
||||||
url += "/"
|
|
||||||
}
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 正则提取域名
|
|
||||||
* @param weburl
|
|
||||||
* @returns {string|string}
|
|
||||||
*/
|
|
||||||
function getDomain(weburl) {
|
|
||||||
let urlReg = /http(s)?:\/\/([^\/]+)/i;
|
|
||||||
let domain = weburl.match(urlReg);
|
|
||||||
return ((domain != null && domain.length > 0) ? domain[2] : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 右边是否包含
|
|
||||||
* @param string
|
|
||||||
* @param find
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
function rightExists(string, find) {
|
|
||||||
string += "";
|
|
||||||
find += "";
|
|
||||||
return (string.substring(string.length - find.length) === find);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** ***************************************************************************************************/
|
|
||||||
/** ***************************************************************************************************/
|
|
||||||
/** ***************************************************************************************************/
|
|
||||||
|
|
||||||
const electronDir = path.resolve(__dirname, "public");
|
const electronDir = path.resolve(__dirname, "public");
|
||||||
const nativeCachePath = path.resolve(__dirname, ".native");
|
const nativeCachePath = path.resolve(__dirname, ".native");
|
||||||
const devloadCachePath = path.resolve(__dirname, ".devload");
|
const devloadCachePath = path.resolve(__dirname, ".devload");
|
||||||
@ -108,7 +16,7 @@ const packageBakFile = path.resolve(__dirname, "package-bak.json");
|
|||||||
const platform = ["build-mac", "build-mac-arm", "build-win"];
|
const platform = ["build-mac", "build-mac-arm", "build-win"];
|
||||||
|
|
||||||
// 生成配置、编译应用
|
// 生成配置、编译应用
|
||||||
function start(data, publish) {
|
function startBuild(data, publish) {
|
||||||
console.log("Name: " + data.name);
|
console.log("Name: " + data.name);
|
||||||
console.log("AppId: " + data.id);
|
console.log("AppId: " + data.id);
|
||||||
console.log("Version: " + config.version);
|
console.log("Version: " + config.version);
|
||||||
@ -117,10 +25,10 @@ function start(data, publish) {
|
|||||||
title: data.name,
|
title: data.name,
|
||||||
version: config.version,
|
version: config.version,
|
||||||
origin: "./",
|
origin: "./",
|
||||||
apiUrl: formatUrl(data.url) + "api/",
|
apiUrl: utils.formatUrl(data.url) + "api/",
|
||||||
}
|
}
|
||||||
fs.writeFileSync(electronDir + "/config.js", "window.systemInformation = " + JSON.stringify(systemInfo, null, 2), 'utf8');
|
fs.writeFileSync(electronDir + "/config.js", "window.systemInformation = " + JSON.stringify(systemInfo, null, 2), 'utf8');
|
||||||
fs.writeFileSync(nativeCachePath, formatUrl(data.url));
|
fs.writeFileSync(nativeCachePath, utils.formatUrl(data.url));
|
||||||
fs.writeFileSync(devloadCachePath, "", 'utf8');
|
fs.writeFileSync(devloadCachePath, "", 'utf8');
|
||||||
// index.html
|
// index.html
|
||||||
let indexFile = path.resolve(electronDir, "index.html");
|
let indexFile = path.resolve(electronDir, "index.html");
|
||||||
@ -134,8 +42,8 @@ function start(data, publish) {
|
|||||||
econfig.name = data.name;
|
econfig.name = data.name;
|
||||||
econfig.version = config.version;
|
econfig.version = config.version;
|
||||||
econfig.build.appId = data.id;
|
econfig.build.appId = data.id;
|
||||||
econfig.build.artifactName = getDomain(data.url) + "-v${version}-${os}-${arch}.${ext}";
|
econfig.build.artifactName = utils.getDomain(data.url) + "-v${version}-${os}-${arch}.${ext}";
|
||||||
econfig.build.nsis.artifactName = getDomain(data.url) + "-v${version}-${os}-${arch}.${ext}";
|
econfig.build.nsis.artifactName = utils.getDomain(data.url) + "-v${version}-${os}-${arch}.${ext}";
|
||||||
econfig.build.pkg.mustClose = [data.id];
|
econfig.build.pkg.mustClose = [data.id];
|
||||||
fs.writeFileSync(packageFile, JSON.stringify(econfig, null, 2), 'utf8');
|
fs.writeFileSync(packageFile, JSON.stringify(econfig, null, 2), 'utf8');
|
||||||
// build
|
// build
|
||||||
@ -146,7 +54,7 @@ function start(data, publish) {
|
|||||||
|
|
||||||
if (["dev"].includes(argv[2])) {
|
if (["dev"].includes(argv[2])) {
|
||||||
// 开发模式
|
// 开发模式
|
||||||
fs.writeFileSync(devloadCachePath, formatUrl("127.0.0.1:" + env.parsed.APP_PORT), 'utf8');
|
fs.writeFileSync(devloadCachePath, utils.formatUrl("127.0.0.1:" + env.parsed.APP_PORT), 'utf8');
|
||||||
child_process.spawn("npx", ["mix", "watch", "--hot", "--", "--env", "--electron"], {stdio: "inherit"});
|
child_process.spawn("npx", ["mix", "watch", "--hot", "--", "--env", "--electron"], {stdio: "inherit"});
|
||||||
child_process.spawn("npm", ["run", "start-quiet"], {stdio: "inherit", cwd: "electron"});
|
child_process.spawn("npm", ["run", "start-quiet"], {stdio: "inherit", cwd: "electron"});
|
||||||
} else if (platform.includes(argv[2])) {
|
} else if (platform.includes(argv[2])) {
|
||||||
@ -154,7 +62,7 @@ if (["dev"].includes(argv[2])) {
|
|||||||
config.app.sites.forEach((data) => {
|
config.app.sites.forEach((data) => {
|
||||||
if (data.name && data.id && data.url) {
|
if (data.name && data.id && data.url) {
|
||||||
data.platform = argv[2];
|
data.platform = argv[2];
|
||||||
start(data, true)
|
startBuild(data, true)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -171,7 +79,7 @@ if (["dev"].includes(argv[2])) {
|
|||||||
return undefined;
|
return undefined;
|
||||||
},
|
},
|
||||||
validate: function (value) {
|
validate: function (value) {
|
||||||
if (!rightExists(value, "/")) {
|
if (!utils.rightExists(value, "/")) {
|
||||||
return '网址必须以 "/" 结尾';
|
return '网址必须以 "/" 结尾';
|
||||||
}
|
}
|
||||||
return value !== ''
|
return value !== ''
|
||||||
@ -198,7 +106,7 @@ if (["dev"].includes(argv[2])) {
|
|||||||
];
|
];
|
||||||
inquirer.prompt(questions).then(answers => {
|
inquirer.prompt(questions).then(answers => {
|
||||||
answers.platform.forEach(platform => {
|
answers.platform.forEach(platform => {
|
||||||
start({
|
startBuild({
|
||||||
"name": config.name,
|
"name": config.name,
|
||||||
"id": config.app.id,
|
"id": config.app.id,
|
||||||
"url": answers.website,
|
"url": answers.website,
|
||||||
|
77
electron/main.js
vendored
77
electron/main.js
vendored
@ -4,19 +4,24 @@ const path = require('path')
|
|||||||
const XLSX = require('xlsx');
|
const XLSX = require('xlsx');
|
||||||
const {app, BrowserWindow, ipcMain, dialog} = require('electron')
|
const {app, BrowserWindow, ipcMain, dialog} = require('electron')
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
|
const config = require('./package.json');
|
||||||
const log = require("electron-log");
|
const log = require("electron-log");
|
||||||
|
|
||||||
let mainWindow = null,
|
let mainWindow = null,
|
||||||
subWindow = [],
|
subWindow = [],
|
||||||
downloadList = [],
|
|
||||||
willQuitApp = false,
|
willQuitApp = false,
|
||||||
inheritClose = false,
|
inheritClose = false,
|
||||||
|
devloadUrl = "",
|
||||||
devloadCachePath = path.resolve(__dirname, ".devload"),
|
devloadCachePath = path.resolve(__dirname, ".devload"),
|
||||||
devloadUrl = "";
|
downloadList = [],
|
||||||
|
downloadCacheFile = path.join(app.getPath('cache'), config.name + '.downloadCache');
|
||||||
|
|
||||||
if (fs.existsSync(devloadCachePath)) {
|
if (fs.existsSync(devloadCachePath)) {
|
||||||
devloadUrl = fs.readFileSync(devloadCachePath, 'utf8')
|
devloadUrl = fs.readFileSync(devloadCachePath, 'utf8')
|
||||||
}
|
}
|
||||||
|
if (fs.existsSync(downloadCacheFile)) {
|
||||||
|
downloadList = utils.jsonParse(fs.readFileSync(downloadCacheFile, 'utf8'), [])
|
||||||
|
}
|
||||||
|
|
||||||
function createMainWindow() {
|
function createMainWindow() {
|
||||||
mainWindow = new BrowserWindow({
|
mainWindow = new BrowserWindow({
|
||||||
@ -64,7 +69,7 @@ function createMainWindow() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
mainWindow.webContents.session.on('will-download', (event, item) => {
|
mainWindow.webContents.session.on('will-download', (event, item) => {
|
||||||
item.setSavePath(path.join(app.getPath('temp'), item.getFilename()));
|
item.setSavePath(path.join(app.getPath('cache'), item.getFilename()));
|
||||||
item.on('done', (event, state) => {
|
item.on('done', (event, state) => {
|
||||||
try {
|
try {
|
||||||
const info = {
|
const info = {
|
||||||
@ -87,15 +92,14 @@ function createMainWindow() {
|
|||||||
download.info = info
|
download.info = info
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
fs.writeFileSync(downloadCacheFile, utils.jsonStringify(downloadList), 'utf8');
|
||||||
} else {
|
} else {
|
||||||
// 下载失败
|
// 下载失败
|
||||||
info.chain.some(url => {
|
info.chain.some(url => {
|
||||||
downloadList = downloadList.filter(item => item.url != url)
|
downloadList = downloadList.filter(item => item.url != url)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) { }
|
||||||
//
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -184,12 +188,19 @@ app.on('before-quit', () => {
|
|||||||
willQuitApp = true
|
willQuitApp = true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 继承关闭窗口事件
|
||||||
|
*/
|
||||||
ipcMain.on('inheritClose', (event) => {
|
ipcMain.on('inheritClose', (event) => {
|
||||||
inheritClose = true
|
inheritClose = true
|
||||||
event.returnValue = "ok"
|
event.returnValue = "ok"
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcMain.on('downloadURL', (event, args) => {
|
/**
|
||||||
|
* 下载文件
|
||||||
|
* @param args {url}
|
||||||
|
*/
|
||||||
|
ipcMain.on('downloadFile', (event, args) => {
|
||||||
const download = downloadList.find(({url}) => url == args.url);
|
const download = downloadList.find(({url}) => url == args.url);
|
||||||
if (download) {
|
if (download) {
|
||||||
if (download.status == "completed") {
|
if (download.status == "completed") {
|
||||||
@ -212,21 +223,35 @@ ipcMain.on('downloadURL', (event, args) => {
|
|||||||
event.returnValue = "ok"
|
event.returnValue = "ok"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开文件
|
||||||
|
* @param args {path}
|
||||||
|
*/
|
||||||
ipcMain.on('openFile', (event, args) => {
|
ipcMain.on('openFile', (event, args) => {
|
||||||
utils.openFile(args.path)
|
utils.openFile(args.path)
|
||||||
event.returnValue = "ok"
|
event.returnValue = "ok"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退出客户端
|
||||||
|
*/
|
||||||
ipcMain.on('windowQuit', (event) => {
|
ipcMain.on('windowQuit', (event) => {
|
||||||
event.returnValue = "ok"
|
event.returnValue = "ok"
|
||||||
app.quit();
|
app.quit();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建路由窗口
|
||||||
|
* @param args {path, ?}
|
||||||
|
*/
|
||||||
ipcMain.on('windowRouter', (event, args) => {
|
ipcMain.on('windowRouter', (event, args) => {
|
||||||
createSubWindow(args)
|
createSubWindow(args)
|
||||||
event.returnValue = "ok"
|
event.returnValue = "ok"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 隐藏窗口(mac隐藏,其他关闭)
|
||||||
|
*/
|
||||||
ipcMain.on('windowHidden', (event) => {
|
ipcMain.on('windowHidden', (event) => {
|
||||||
if (process.platform === 'darwin') {
|
if (process.platform === 'darwin') {
|
||||||
app.hide();
|
app.hide();
|
||||||
@ -236,12 +261,19 @@ ipcMain.on('windowHidden', (event) => {
|
|||||||
event.returnValue = "ok"
|
event.returnValue = "ok"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭窗口
|
||||||
|
*/
|
||||||
ipcMain.on('windowClose', (event) => {
|
ipcMain.on('windowClose', (event) => {
|
||||||
const win = BrowserWindow.fromWebContents(event.sender);
|
const win = BrowserWindow.fromWebContents(event.sender);
|
||||||
win.close()
|
win.close()
|
||||||
event.returnValue = "ok"
|
event.returnValue = "ok"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置窗口尺寸
|
||||||
|
* @param args {width, height, autoZoom, minWidth, minHeight, maxWidth, maxHeight}
|
||||||
|
*/
|
||||||
ipcMain.on('windowSize', (event, args) => {
|
ipcMain.on('windowSize', (event, args) => {
|
||||||
const win = BrowserWindow.fromWebContents(event.sender);
|
const win = BrowserWindow.fromWebContents(event.sender);
|
||||||
if (win) {
|
if (win) {
|
||||||
@ -277,23 +309,34 @@ ipcMain.on('windowSize', (event, args) => {
|
|||||||
event.returnValue = "ok"
|
event.returnValue = "ok"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置窗口最小尺寸
|
||||||
|
* @param args {minWidth, minHeight}
|
||||||
|
*/
|
||||||
ipcMain.on('windowMinSize', (event, args) => {
|
ipcMain.on('windowMinSize', (event, args) => {
|
||||||
const win = BrowserWindow.fromWebContents(event.sender);
|
const win = BrowserWindow.fromWebContents(event.sender);
|
||||||
if (win) {
|
if (win) {
|
||||||
win.setMinimumSize(args.width || win.getMinimumSize()[0], args.height || win.getMinimumSize()[1])
|
win.setMinimumSize(args.minWidth || win.getMinimumSize()[0], args.minHeight || win.getMinimumSize()[1])
|
||||||
}
|
}
|
||||||
event.returnValue = "ok"
|
event.returnValue = "ok"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置窗口最大尺寸
|
||||||
|
* @param args {maxWidth, maxHeight}
|
||||||
|
*/
|
||||||
ipcMain.on('windowMaxSize', (event, args) => {
|
ipcMain.on('windowMaxSize', (event, args) => {
|
||||||
const win = BrowserWindow.fromWebContents(event.sender);
|
const win = BrowserWindow.fromWebContents(event.sender);
|
||||||
if (win) {
|
if (win) {
|
||||||
win.setMaximumSize(args.width || win.getMaximumSize()[0], args.height || win.getMaximumSize()[1])
|
win.setMaximumSize(args.maxWidth || win.getMaximumSize()[0], args.maxHeight || win.getMaximumSize()[1])
|
||||||
}
|
}
|
||||||
event.returnValue = "ok"
|
event.returnValue = "ok"
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcMain.on('windowCenter', (event, args) => {
|
/**
|
||||||
|
* 窗口居中
|
||||||
|
*/
|
||||||
|
ipcMain.on('windowCenter', (event) => {
|
||||||
const win = BrowserWindow.fromWebContents(event.sender);
|
const win = BrowserWindow.fromWebContents(event.sender);
|
||||||
if (win) {
|
if (win) {
|
||||||
win.center();
|
win.center();
|
||||||
@ -301,6 +344,9 @@ ipcMain.on('windowCenter', (event, args) => {
|
|||||||
event.returnValue = "ok"
|
event.returnValue = "ok"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 窗口最大化或恢复
|
||||||
|
*/
|
||||||
ipcMain.on('windowMax', (event) => {
|
ipcMain.on('windowMax', (event) => {
|
||||||
const win = BrowserWindow.fromWebContents(event.sender);
|
const win = BrowserWindow.fromWebContents(event.sender);
|
||||||
if (win.isMaximized()) {
|
if (win.isMaximized()) {
|
||||||
@ -311,6 +357,10 @@ ipcMain.on('windowMax', (event) => {
|
|||||||
event.returnValue = "ok"
|
event.returnValue = "ok"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 给主窗口发送信息
|
||||||
|
* @param args {channel, data}
|
||||||
|
*/
|
||||||
ipcMain.on('sendForwardMain', (event, args) => {
|
ipcMain.on('sendForwardMain', (event, args) => {
|
||||||
if (mainWindow) {
|
if (mainWindow) {
|
||||||
mainWindow.webContents.send(args.channel, args.data)
|
mainWindow.webContents.send(args.channel, args.data)
|
||||||
@ -318,6 +368,10 @@ ipcMain.on('sendForwardMain', (event, args) => {
|
|||||||
event.returnValue = "ok"
|
event.returnValue = "ok"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置Dock标记
|
||||||
|
* @param args
|
||||||
|
*/
|
||||||
ipcMain.on('setDockBadge', (event, args) => {
|
ipcMain.on('setDockBadge', (event, args) => {
|
||||||
if(process.platform !== 'darwin'){
|
if(process.platform !== 'darwin'){
|
||||||
// Mac only
|
// Mac only
|
||||||
@ -331,6 +385,9 @@ ipcMain.on('setDockBadge', (event, args) => {
|
|||||||
event.returnValue = "ok"
|
event.returnValue = "ok"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存sheets
|
||||||
|
*/
|
||||||
ipcMain.on('saveSheet', (event, data, filename, opts) => {
|
ipcMain.on('saveSheet', (event, data, filename, opts) => {
|
||||||
const EXTENSIONS = "xls|xlsx|xlsm|xlsb|xml|csv|txt|dif|sylk|slk|prn|ods|fods|htm|html".split("|");
|
const EXTENSIONS = "xls|xlsx|xlsm|xlsb|xml|csv|txt|dif|sylk|slk|prn|ods|fods|htm|html".split("|");
|
||||||
dialog.showSaveDialog({
|
dialog.showSaveDialog({
|
||||||
|
155
electron/utils.js
vendored
155
electron/utils.js
vendored
@ -2,18 +2,73 @@ const fs = require("fs");
|
|||||||
const {shell} = require("electron");
|
const {shell} = require("electron");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
/**
|
||||||
|
* 是否数组
|
||||||
|
* @param obj
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
isArray(obj) {
|
||||||
|
return typeof (obj) == "object" && Object.prototype.toString.call(obj).toLowerCase() == '[object array]' && typeof obj.length == "number";
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否数组对象
|
||||||
|
* @param obj
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
isJson(obj) {
|
||||||
|
return typeof (obj) == "object" && Object.prototype.toString.call(obj).toLowerCase() == "[object object]" && typeof obj.length == "undefined";
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将一个 JSON 字符串转换为对象(已try)
|
||||||
|
* @param str
|
||||||
|
* @param defaultVal
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
jsonParse(str, defaultVal = undefined) {
|
||||||
|
if (str === null) {
|
||||||
|
return defaultVal ? defaultVal : {};
|
||||||
|
}
|
||||||
|
if (typeof str === "object") {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return JSON.parse(str.replace(/\n/g,"\\n").replace(/\r/g,"\\r"));
|
||||||
|
} catch (e) {
|
||||||
|
return defaultVal ? defaultVal : {};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 JavaScript 值转换为 JSON 字符串(已try)
|
||||||
|
* @param json
|
||||||
|
* @param defaultVal
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
jsonStringify(json, defaultVal = undefined) {
|
||||||
|
if (typeof json !== 'object') {
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
try{
|
||||||
|
return JSON.stringify(json);
|
||||||
|
}catch (e) {
|
||||||
|
return defaultVal ? defaultVal : "";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 随机数字
|
* 随机数字
|
||||||
* @param str
|
* @param str
|
||||||
* @param fixed
|
* @param fixed
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
runNum(str, fixed) {
|
runNum(str, fixed = null) {
|
||||||
let _s = Number(str);
|
let _s = Number(str);
|
||||||
if (_s + "" === "NaN") {
|
if (_s + "" === "NaN") {
|
||||||
_s = 0;
|
_s = 0;
|
||||||
}
|
}
|
||||||
if (/^[0-9]*[1-9][0-9]*$/.test(fixed)) {
|
if (fixed && /^[0-9]*[1-9][0-9]*$/.test(fixed)) {
|
||||||
_s = _s.toFixed(fixed);
|
_s = _s.toFixed(fixed);
|
||||||
let rs = _s.indexOf('.');
|
let rs = _s.indexOf('.');
|
||||||
if (rs < 0) {
|
if (rs < 0) {
|
||||||
@ -43,7 +98,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 字符串包含
|
* 字符串是否包含
|
||||||
* @param string
|
* @param string
|
||||||
* @param find
|
* @param find
|
||||||
* @param lower
|
* @param lower
|
||||||
@ -92,6 +147,23 @@ module.exports = {
|
|||||||
return string ? string : '';
|
return string ? string : '';
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符串是否右边包含
|
||||||
|
* @param string
|
||||||
|
* @param find
|
||||||
|
* @param lower
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
rightExists(string, find, lower = false) {
|
||||||
|
string += "";
|
||||||
|
find += "";
|
||||||
|
if (lower !== true) {
|
||||||
|
string = string.toLowerCase();
|
||||||
|
find = find.toLowerCase();
|
||||||
|
}
|
||||||
|
return (string.substring(string.length - find.length) === find);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 打开文件
|
* 打开文件
|
||||||
* @param path
|
* @param path
|
||||||
@ -103,4 +175,81 @@ module.exports = {
|
|||||||
shell.openPath(path).then(() => {
|
shell.openPath(path).then(() => {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除文件夹及文件
|
||||||
|
* @param path
|
||||||
|
*/
|
||||||
|
deleteFile(path) {
|
||||||
|
let files = [];
|
||||||
|
if (fs.existsSync(path)) {
|
||||||
|
files = fs.readdirSync(path);
|
||||||
|
files.forEach(function (file, index) {
|
||||||
|
let curPath = path + "/" + file;
|
||||||
|
if (fs.statSync(curPath).isDirectory()) {
|
||||||
|
deleteFile(curPath);
|
||||||
|
} else {
|
||||||
|
fs.unlinkSync(curPath);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
fs.rmdirSync(path);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复制文件
|
||||||
|
* @param srcPath
|
||||||
|
* @param tarPath
|
||||||
|
* @param cb
|
||||||
|
*/
|
||||||
|
copyFile(srcPath, tarPath, cb) {
|
||||||
|
let rs = fs.createReadStream(srcPath)
|
||||||
|
rs.on('error', function (err) {
|
||||||
|
if (err) {
|
||||||
|
console.log('read error', srcPath)
|
||||||
|
}
|
||||||
|
cb && cb(err)
|
||||||
|
})
|
||||||
|
let ws = fs.createWriteStream(tarPath)
|
||||||
|
ws.on('error', function (err) {
|
||||||
|
if (err) {
|
||||||
|
console.log('write error', tarPath)
|
||||||
|
}
|
||||||
|
cb && cb(err)
|
||||||
|
})
|
||||||
|
ws.on('close', function (ex) {
|
||||||
|
cb && cb(ex)
|
||||||
|
})
|
||||||
|
rs.pipe(ws)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 给地址加上前后
|
||||||
|
* @param str
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
formatUrl(str) {
|
||||||
|
let url;
|
||||||
|
if (str.substring(0, 7) === "http://" ||
|
||||||
|
str.substring(0, 8) === "https://") {
|
||||||
|
url = str.trim();
|
||||||
|
} else {
|
||||||
|
url = "http://" + str.trim();
|
||||||
|
}
|
||||||
|
if (url.substring(url.length - 1) != "/") {
|
||||||
|
url += "/"
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 正则提取域名
|
||||||
|
* @param weburl
|
||||||
|
* @returns {string|string}
|
||||||
|
*/
|
||||||
|
getDomain(weburl) {
|
||||||
|
let urlReg = /http(s)?:\/\/([^\/]+)/i;
|
||||||
|
let domain = weburl.match(urlReg);
|
||||||
|
return ((domain != null && domain.length > 0) ? domain[2] : "");
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="status && !$store.state.windowMax768" class="common-app-down">
|
<div v-if="showButton" class="common-app-down" :data-route="$route.name">
|
||||||
<div v-if="$Electron" class="common-app-down-link" @click="installApplication">
|
<div v-if="$Electron" class="common-app-down-link" @click="releasesNotification">
|
||||||
<Icon type="md-download"/> {{$L(repoTitle)}}
|
<Icon type="md-download"/> {{$L(repoTitle)}}
|
||||||
</div>
|
</div>
|
||||||
<a v-else class="common-app-down-link" :href="releases.html_url" target="_blank">
|
<a v-else class="common-app-down-link" :href="releases.html_url" target="_blank">
|
||||||
@ -36,51 +36,7 @@ export default {
|
|||||||
this.$Electron.ipcRenderer.on('downloadDone', (event, args) => {
|
this.$Electron.ipcRenderer.on('downloadDone', (event, args) => {
|
||||||
if (args.name == this.repoData.name) {
|
if (args.name == this.repoData.name) {
|
||||||
this.downInfo = args;
|
this.downInfo = args;
|
||||||
const h = this.$createElement;
|
this.releasesNotification()
|
||||||
window.__appNotification && window.__appNotification.close();
|
|
||||||
window.__appNotification = Notification({
|
|
||||||
title: this.$L("更新提示"),
|
|
||||||
duration: 0,
|
|
||||||
position: "bottom-right",
|
|
||||||
customClass: "common-app-down-notification",
|
|
||||||
onClose: () => {
|
|
||||||
this.status = 2;
|
|
||||||
},
|
|
||||||
message: h('span', [
|
|
||||||
h('span', [
|
|
||||||
h('span', this.$L('发现新版本') + ": "),
|
|
||||||
h('Tag', {
|
|
||||||
props: {
|
|
||||||
color: 'volcano'
|
|
||||||
}
|
|
||||||
}, this.releases.tag_name)
|
|
||||||
]),
|
|
||||||
h('MarkdownPreview', {
|
|
||||||
class: 'common-app-down-body',
|
|
||||||
props: {
|
|
||||||
initialValue: this.releases.body
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
h('div', {
|
|
||||||
class: 'common-app-down-link',
|
|
||||||
on: {
|
|
||||||
click: () => {
|
|
||||||
this.installApplication();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}, [
|
|
||||||
h('Icon', {
|
|
||||||
props: {
|
|
||||||
type: 'md-download'
|
|
||||||
},
|
|
||||||
style: {
|
|
||||||
marginRight: '5px'
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
h('span', this.$L('立即安装'))
|
|
||||||
]),
|
|
||||||
])
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -88,74 +44,12 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
repoTitle() {
|
repoTitle() {
|
||||||
return this.status == 2 ? '更新客户端' : '客户端下载';
|
return this.status == 2 ? '更新客户端' : '客户端下载';
|
||||||
|
},
|
||||||
|
showButton() {
|
||||||
|
return this.status && !this.$store.state.windowMax768 && ['login', 'manage-dashboard'].includes(this.$route.name)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getReleases() {
|
|
||||||
let cache = $A.getStorageJson("cacheAppdown");
|
|
||||||
if (cache.time && cache.time + 3600 > Math.round(new Date().getTime() / 1000)) {
|
|
||||||
this.releases = cache.data;
|
|
||||||
this.chackReleases()
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
;(() => {
|
|
||||||
axios
|
|
||||||
.get("https://api.github.com/repos/" + this.repoName + "/releases/latest")
|
|
||||||
.then(({status, data}) => {
|
|
||||||
if (status === 200) {
|
|
||||||
$A.setStorage("cacheAppdown", {
|
|
||||||
time: Math.round(new Date().getTime() / 1000),
|
|
||||||
data: data
|
|
||||||
});
|
|
||||||
this.releases = data;
|
|
||||||
this.chackReleases()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})();
|
|
||||||
},
|
|
||||||
|
|
||||||
chackReleases() {
|
|
||||||
let hostName = window.location.hostname;
|
|
||||||
if (hostName == '127.0.0.1') {
|
|
||||||
hostName = "www.dootask.com"
|
|
||||||
}
|
|
||||||
if (this.$Electron) {
|
|
||||||
// 客户端(更新)
|
|
||||||
let match = (window.navigator.userAgent + "").match(/\s+(Main|Sub)TaskWindow\/(.*?)\/(.*?)\//)
|
|
||||||
if (!match) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let artifactName = null;
|
|
||||||
if (match[2] === 'darwin') {
|
|
||||||
artifactName = `${hostName}-${this.releases.tag_name}-mac-${match[3]}.pkg`;
|
|
||||||
} else if (match[2] === 'win32') {
|
|
||||||
artifactName = `${hostName}-${this.releases.tag_name}-win-${match[3]}.exe`;
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.repoData = (this.releases.assets || []).find(({name}) => name == artifactName);
|
|
||||||
if (!this.repoData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let currentVersion = window.systemInformation.version;
|
|
||||||
let latestVersion = $A.leftDelete(this.releases.tag_name.toLowerCase(), "v")
|
|
||||||
if (this.compareVersion(latestVersion, currentVersion) === 1) {
|
|
||||||
// 有新版本
|
|
||||||
console.log("有新版本");
|
|
||||||
this.$Electron.ipcRenderer.send('downloadURL', {
|
|
||||||
url: this.repoData.browser_download_url
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 网页版(提示有客户端下载)
|
|
||||||
this.repoData = (this.releases.assets || []).find(({name}) => $A.strExists(name, hostName));
|
|
||||||
if (this.repoData) {
|
|
||||||
console.log("有客户端");
|
|
||||||
this.status = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
compareVersion(version1, version2) {
|
compareVersion(version1, version2) {
|
||||||
let pA = 0, pB = 0;
|
let pA = 0, pB = 0;
|
||||||
// 寻找当前区间的版本号
|
// 寻找当前区间的版本号
|
||||||
@ -200,6 +94,129 @@ export default {
|
|||||||
return 0;
|
return 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getReleases() {
|
||||||
|
if (this.status > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
let cache = $A.getStorageJson("cacheAppdown");
|
||||||
|
let timeout = 1800;
|
||||||
|
if (cache.time && cache.time + timeout > Math.round(new Date().getTime() / 1000)) {
|
||||||
|
this.releases = cache.data;
|
||||||
|
this.chackReleases()
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
;(() => {
|
||||||
|
axios
|
||||||
|
.get("https://api.github.com/repos/" + this.repoName + "/releases/latest")
|
||||||
|
.then(({status, data}) => {
|
||||||
|
if (status === 200) {
|
||||||
|
$A.setStorage("cacheAppdown", {
|
||||||
|
time: Math.round(new Date().getTime() / 1000),
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
this.releases = data;
|
||||||
|
this.chackReleases();
|
||||||
|
setTimeout(this.getReleases, timeout)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
},
|
||||||
|
|
||||||
|
chackReleases() {
|
||||||
|
let hostName = window.location.hostname;
|
||||||
|
if (hostName == '127.0.0.1') {
|
||||||
|
hostName = "www.dootask.com"
|
||||||
|
}
|
||||||
|
if (this.$Electron) {
|
||||||
|
// 客户端(更新)
|
||||||
|
let match = (window.navigator.userAgent + "").match(/\s+(Main|Sub)TaskWindow\/(.*?)\/(.*?)\//)
|
||||||
|
if (!match) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let artifactName = null;
|
||||||
|
if (match[2] === 'darwin') {
|
||||||
|
artifactName = `${hostName}-${this.releases.tag_name}-mac-${match[3]}.pkg`;
|
||||||
|
} else if (match[2] === 'win32') {
|
||||||
|
artifactName = `${hostName}-${this.releases.tag_name}-win-${match[3]}.exe`;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.repoData = (this.releases.assets || []).find(({name}) => name == artifactName);
|
||||||
|
if (!this.repoData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let currentVersion = window.systemInformation.version;
|
||||||
|
let latestVersion = $A.leftDelete(this.releases.tag_name.toLowerCase(), "v")
|
||||||
|
if (this.compareVersion(latestVersion, currentVersion) === 1) {
|
||||||
|
// 有新版本
|
||||||
|
console.log("New version: " + latestVersion);
|
||||||
|
this.$Electron.ipcRenderer.send('downloadFile', {
|
||||||
|
url: this.repoData.browser_download_url
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 网页版(提示有客户端下载)
|
||||||
|
this.repoData = (this.releases.assets || []).find(({name}) => $A.strExists(name, hostName));
|
||||||
|
if (this.repoData) {
|
||||||
|
console.log("有客户端");
|
||||||
|
this.status = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
releasesNotification() {
|
||||||
|
if (this.downInfo.state != "completed") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const h = this.$createElement;
|
||||||
|
window.__appNotification && window.__appNotification.close();
|
||||||
|
window.__appNotification = Notification({
|
||||||
|
title: this.$L("更新提示"),
|
||||||
|
duration: 0,
|
||||||
|
position: "bottom-right",
|
||||||
|
customClass: "common-app-down-notification",
|
||||||
|
onClose: () => {
|
||||||
|
this.status = 2;
|
||||||
|
},
|
||||||
|
message: h('span', [
|
||||||
|
h('span', [
|
||||||
|
h('span', this.$L('发现新版本') + ": "),
|
||||||
|
h('Tag', {
|
||||||
|
props: {
|
||||||
|
color: 'volcano'
|
||||||
|
}
|
||||||
|
}, this.releases.tag_name)
|
||||||
|
]),
|
||||||
|
h('MarkdownPreview', {
|
||||||
|
class: 'common-app-down-body',
|
||||||
|
props: {
|
||||||
|
initialValue: this.releases.body
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
h('div', {
|
||||||
|
class: 'common-app-down-link',
|
||||||
|
on: {
|
||||||
|
click: () => {
|
||||||
|
this.installApplication();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
h('Icon', {
|
||||||
|
props: {
|
||||||
|
type: 'md-checkmark-circle-outline'
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
marginRight: '5px'
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
h('span', this.$L('立即更新'))
|
||||||
|
]),
|
||||||
|
])
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
installApplication() {
|
installApplication() {
|
||||||
if (!this.$Electron) {
|
if (!this.$Electron) {
|
||||||
return;
|
return;
|
||||||
|
@ -42,8 +42,8 @@
|
|||||||
<div class="login-forgot">{{$L('忘记密码了?')}}<a href="javascript:void(0)" @click="forgotPassword">{{$L('重置密码')}}</a></div>
|
<div class="login-forgot">{{$L('忘记密码了?')}}<a href="javascript:void(0)" @click="forgotPassword">{{$L('重置密码')}}</a></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="login-right-bottom">
|
<div v-if="$Electron" class="login-right-bottom">
|
||||||
<Button v-if="$Electron" icon="ios-globe-outline" type="primary" @click="onServerUrlInput">{{$L('自定义服务器')}}</Button>
|
<Button icon="ios-globe-outline" type="primary" @click="onServerUrlInput">{{$L('自定义服务器')}}</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -5,6 +5,10 @@
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
transition: bottom 0.3s;
|
||||||
|
&[data-route=login] {
|
||||||
|
bottom: 75px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.common-app-down-notification {
|
.common-app-down-notification {
|
||||||
|
6
resources/assets/sass/pages/page-login.scss
vendored
6
resources/assets/sass/pages/page-login.scss
vendored
@ -114,11 +114,5 @@
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
.common-app-down {
|
|
||||||
position: static;
|
|
||||||
bottom: auto;
|
|
||||||
right: auto;
|
|
||||||
margin-left: 12px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user