mirror of
https://gitee.com/dromara/electron-egg.git
synced 2026-05-14 19:52:10 +08:00
662 lines
15 KiB
JavaScript
662 lines
15 KiB
JavaScript
'use strict';
|
||
|
||
const _ = require('lodash');
|
||
const path = require('path');
|
||
const fs = require('fs');
|
||
const is = require('electron-is');
|
||
const { exec } = require('child_process');
|
||
const Controller = require('ee-core').Controller;
|
||
const Utils = require('ee-core').Utils;
|
||
const electronApp = require('electron').app;
|
||
const {dialog, webContents, shell, BrowserWindow, BrowserView,
|
||
Notification, powerMonitor, screen, nativeTheme} = require('electron');
|
||
const autoLaunchManager = require('../library/autoLaunch');
|
||
const dayjs = require('dayjs');
|
||
|
||
let myTimer = null;
|
||
let browserViewObj = null;
|
||
let notificationObj = null;
|
||
|
||
/**
|
||
* 示例控制器
|
||
* @class
|
||
*/
|
||
class ExampleController extends Controller {
|
||
|
||
constructor(ctx) {
|
||
super(ctx);
|
||
}
|
||
|
||
/**
|
||
* 所有方法接收两个参数
|
||
* @param args 前端传的参数
|
||
* @param event - ipc通信时才有值。invoke()方法时,event == IpcMainInvokeEvent; send()/sendSync()方法时,event == IpcMainEvent
|
||
*/
|
||
|
||
/**
|
||
* test
|
||
*/
|
||
async test () {
|
||
const result = await this.service.example.test('electron');
|
||
|
||
let tmpDir = Utils.getLogDir();
|
||
console.log('tmpDir:', tmpDir);
|
||
|
||
console.log('this.app.request:', this.app.request.query);
|
||
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* json数据库操作
|
||
*/
|
||
async dbOperation(args) {
|
||
const { service } = this;
|
||
const paramsObj = args;
|
||
//console.log('eeeee paramsObj:', paramsObj);
|
||
const data = {
|
||
action: paramsObj.action,
|
||
result: null,
|
||
all_list: []
|
||
};
|
||
|
||
switch (paramsObj.action) {
|
||
case 'add' :
|
||
data.result = await service.storage.addTestData(paramsObj.info);;
|
||
break;
|
||
case 'del' :
|
||
data.result = await service.storage.delTestData(paramsObj.delete_name);;
|
||
break;
|
||
case 'update' :
|
||
data.result = await service.storage.updateTestData(paramsObj.update_name, paramsObj.update_age);
|
||
break;
|
||
case 'get' :
|
||
data.result = await service.storage.getTestData(paramsObj.search_age);
|
||
break;
|
||
}
|
||
|
||
data.all_list = await service.storage.getAllTestData();
|
||
|
||
return data;
|
||
}
|
||
|
||
/**
|
||
* sqlite数据库操作
|
||
*/
|
||
async sqlitedbOperation(args) {
|
||
const { service } = this;
|
||
const paramsObj = args;
|
||
//console.log('eeeee paramsObj:', paramsObj);
|
||
const data = {
|
||
action: paramsObj.action,
|
||
result: null,
|
||
all_list: []
|
||
};
|
||
|
||
switch (paramsObj.action) {
|
||
case 'add' :
|
||
data.result = await service.storage.addTestDataSqlite(paramsObj.info);;
|
||
break;
|
||
case 'del' :
|
||
data.result = await service.storage.delTestDataSqlite(paramsObj.delete_name);;
|
||
break;
|
||
case 'update' :
|
||
data.result = await service.storage.updateTestDataSqlite(paramsObj.update_name, paramsObj.update_age);
|
||
break;
|
||
case 'get' :
|
||
data.result = await service.storage.getTestDataSqlite(paramsObj.search_age);
|
||
break;
|
||
}
|
||
|
||
data.all_list = await service.storage.getAllTestDataSqlite();
|
||
|
||
return data;
|
||
}
|
||
|
||
/**
|
||
* 消息提示对话框
|
||
*/
|
||
messageShow () {
|
||
dialog.showMessageBoxSync({
|
||
type: 'info', // "none", "info", "error", "question" 或者 "warning"
|
||
title: '自定义标题-message',
|
||
message: '自定义消息内容',
|
||
detail: '其它的额外信息'
|
||
})
|
||
|
||
return '打开了消息框';
|
||
}
|
||
|
||
/**
|
||
* 消息提示与确认对话框
|
||
*/
|
||
messageShowConfirm () {
|
||
const res = dialog.showMessageBoxSync({
|
||
type: 'info',
|
||
title: '自定义标题-message',
|
||
message: '自定义消息内容',
|
||
detail: '其它的额外信息',
|
||
cancelId: 1, // 用于取消对话框的按钮的索引
|
||
defaultId: 0, // 设置默认选中的按钮
|
||
buttons: ['确认', '取消'], // 按钮及索引
|
||
})
|
||
let data = (res === 0) ? '点击确认按钮' : '点击取消按钮';
|
||
|
||
return data;
|
||
}
|
||
|
||
/**
|
||
* 选择目录
|
||
*/
|
||
selectFolder () {
|
||
const filePaths = dialog.showOpenDialogSync({
|
||
properties: ['openDirectory', 'createDirectory']
|
||
});
|
||
|
||
if (_.isEmpty(filePaths)) {
|
||
return null
|
||
}
|
||
|
||
return filePaths[0];
|
||
}
|
||
|
||
/**
|
||
* 打开目录
|
||
*/
|
||
openDirectory (args) {
|
||
if (!args.id) {
|
||
return false;
|
||
}
|
||
const dir = electronApp.getPath(args.id);
|
||
shell.openPath(dir);
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 加载视图内容
|
||
*/
|
||
loadViewContent (args) {
|
||
let content = null;
|
||
if (args.type == 'html') {
|
||
content = path.join('file://', electronApp.getAppPath(), args.content)
|
||
} else {
|
||
content = args.content;
|
||
}
|
||
|
||
browserViewObj = new BrowserView();
|
||
this.app.electron.mainWindow.setBrowserView(browserViewObj)
|
||
browserViewObj.setBounds({
|
||
x: 300,
|
||
y: 170,
|
||
width: 650,
|
||
height: 400
|
||
});
|
||
browserViewObj.webContents.loadURL(content);
|
||
return true
|
||
}
|
||
|
||
/**
|
||
* 移除视图内容
|
||
*/
|
||
removeViewContent () {
|
||
this.app.electron.mainWindow.removeBrowserView(browserViewObj);
|
||
return true
|
||
}
|
||
|
||
/**
|
||
* 打开新窗口
|
||
*/
|
||
createWindow (args) {
|
||
let content = null;
|
||
if (args.type == 'html') {
|
||
content = path.join('file://', electronApp.getAppPath(), args.content)
|
||
} else if (args.type == 'web') {
|
||
content = args.content;
|
||
} else if (args.type == 'vue') {
|
||
let addr = 'http://localhost:8080'
|
||
if (this.config.env == 'prod') {
|
||
const mainServer = this.app.config.mainServer;
|
||
addr = mainServer.protocol + mainServer.host + ':' + mainServer.port;
|
||
}
|
||
|
||
content = addr + args.content;
|
||
} else {
|
||
// some
|
||
}
|
||
|
||
console.log('url:', content);
|
||
const addonWindow = this.app.addon.window;
|
||
let opt = {
|
||
title: args.windowName || 'new window'
|
||
}
|
||
const name = args.windowName || 'window-1';
|
||
const win = addonWindow.create(name, opt);
|
||
const winContentsId = win.webContents.id;
|
||
|
||
// load page
|
||
win.loadURL(content);
|
||
|
||
return winContentsId
|
||
}
|
||
|
||
/**
|
||
* 获取窗口contents id
|
||
*/
|
||
getWCid (args) {
|
||
const addonWindow = this.app.addon.window;
|
||
|
||
// 主窗口的name默认是main,其它窗口name开发者自己定义
|
||
const name = args;
|
||
const id = addonWindow.getWCid(name);
|
||
|
||
return id;
|
||
}
|
||
|
||
/**
|
||
* 加载扩展程序
|
||
*/
|
||
// async loadExtension (args) {
|
||
// const crxFile = args[0];
|
||
// if (_.isEmpty(crxFile)) {
|
||
// return false;
|
||
// }
|
||
// const extensionId = path.basename(crxFile, '.crx');
|
||
// const chromeExtensionDir = chromeExtension.getDirectory();
|
||
// const extensionDir = path.join(chromeExtensionDir, extensionId);
|
||
|
||
// console.log("[api] [example] [loadExtension] extension id:", extensionId);
|
||
// unzip(crxFile, extensionDir).then(() => {
|
||
// console.log("[api] [example] [loadExtension] unzip success!");
|
||
// chromeExtension.load(extensionId);
|
||
// });
|
||
|
||
// return true;
|
||
// }
|
||
|
||
/**
|
||
* 创建系统通知
|
||
*/
|
||
sendNotification (arg, event) {
|
||
const channel = 'controller.example.sendNotification';
|
||
if (!Notification.isSupported()) {
|
||
return '当前系统不支持通知';
|
||
}
|
||
|
||
let options = {};
|
||
if (!_.isEmpty(arg.title)) {
|
||
options.title = arg.title;
|
||
}
|
||
if (!_.isEmpty(arg.subtitle)) {
|
||
options.subtitle = arg.subtitle;
|
||
}
|
||
if (!_.isEmpty(arg.body)) {
|
||
options.body = arg.body;
|
||
}
|
||
if (!_.isEmpty(arg.silent)) {
|
||
options.silent = arg.silent;
|
||
}
|
||
|
||
notificationObj = new Notification(options);
|
||
|
||
if (arg.clickEvent) {
|
||
notificationObj.on('click', (e) => {
|
||
let data = {
|
||
type: 'click',
|
||
msg: '您点击了通知消息'
|
||
}
|
||
event.reply(`${channel}`, data)
|
||
});
|
||
}
|
||
|
||
if (arg.closeEvent) {
|
||
notificationObj.on('close', (e) => {
|
||
let data = {
|
||
type: 'close',
|
||
msg: '您关闭了通知消息'
|
||
}
|
||
event.reply(`${channel}`, data)
|
||
});
|
||
}
|
||
|
||
notificationObj.show();
|
||
|
||
return true
|
||
}
|
||
|
||
/**
|
||
* 电源监控
|
||
*/
|
||
initPowerMonitor (arg, event) {
|
||
const channel = 'controller.example.initPowerMonitor';
|
||
powerMonitor.on('on-ac', (e) => {
|
||
let data = {
|
||
type: 'on-ac',
|
||
msg: '接入了电源'
|
||
}
|
||
event.reply(`${channel}`, data)
|
||
});
|
||
|
||
powerMonitor.on('on-battery', (e) => {
|
||
let data = {
|
||
type: 'on-battery',
|
||
msg: '使用电池中'
|
||
}
|
||
event.reply(`${channel}`, data)
|
||
});
|
||
|
||
powerMonitor.on('lock-screen', (e) => {
|
||
let data = {
|
||
type: 'lock-screen',
|
||
msg: '锁屏了'
|
||
}
|
||
event.reply(`${channel}`, data)
|
||
});
|
||
|
||
powerMonitor.on('unlock-screen', (e) => {
|
||
let data = {
|
||
type: 'unlock-screen',
|
||
msg: '解锁了'
|
||
}
|
||
event.reply(`${channel}`, data)
|
||
});
|
||
|
||
return true
|
||
}
|
||
|
||
/**
|
||
* 获取屏幕信息
|
||
*/
|
||
getScreen (arg) {
|
||
let data = [];
|
||
let res = {};
|
||
if (arg == 0) {
|
||
let res = screen.getCursorScreenPoint();
|
||
data = [
|
||
{
|
||
title: '横坐标',
|
||
desc: res.x
|
||
},
|
||
{
|
||
title: '纵坐标',
|
||
desc: res.y
|
||
},
|
||
]
|
||
|
||
return data;
|
||
}
|
||
if (arg == 1) {
|
||
res = screen.getPrimaryDisplay();
|
||
}
|
||
if (arg == 2) {
|
||
let resArr = screen.getAllDisplays();
|
||
// 数组,只取一个吧
|
||
res = resArr[0];
|
||
}
|
||
// console.log('[electron] [ipc] [example] [getScreen] res:', res);
|
||
data = [
|
||
{
|
||
title: '分辨率',
|
||
desc: res.bounds.width + ' x ' + res.bounds.height
|
||
},
|
||
{
|
||
title: '单色显示器',
|
||
desc: res.monochrome ? '是' : '否'
|
||
},
|
||
{
|
||
title: '色深',
|
||
desc: res. colorDepth
|
||
},
|
||
{
|
||
title: '色域',
|
||
desc: res.colorSpace
|
||
},
|
||
{
|
||
title: 'scaleFactor',
|
||
desc: res.scaleFactor
|
||
},
|
||
{
|
||
title: '加速器',
|
||
desc: res.accelerometerSupport
|
||
},
|
||
{
|
||
title: '触控',
|
||
desc: res.touchSupport == 'unknown' ? '不支持' : '支持'
|
||
},
|
||
]
|
||
|
||
return data;
|
||
}
|
||
|
||
/**
|
||
* 调用其它程序(exe、bash等可执行程序)
|
||
*/
|
||
openSoftware (softName) {
|
||
if (!softName) {
|
||
return false;
|
||
}
|
||
|
||
let softwarePath = path.join(Utils.getExtraResourcesDir(), softName);
|
||
this.app.logger.info('[openSoftware] softwarePath:', softwarePath);
|
||
|
||
// 检查程序是否存在
|
||
if (!fs.existsSync(softwarePath)) {
|
||
return false;
|
||
}
|
||
// 命令行字符串 并 执行
|
||
let cmdStr = 'start ' + softwarePath;
|
||
exec(cmdStr);
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 开机启动-开启
|
||
*/
|
||
autoLaunch (type) {
|
||
console.log('type:', type);
|
||
let res = {
|
||
type: type,
|
||
status: null
|
||
};
|
||
if (type == 'check') {
|
||
res.status = autoLaunchManager.isEnabled();
|
||
} else if (type == 'open') {
|
||
autoLaunchManager.enable();
|
||
res.status = true;
|
||
} else if (type == 'close') {
|
||
autoLaunchManager.disable();
|
||
res.status = false;
|
||
}
|
||
|
||
return res
|
||
}
|
||
|
||
/**
|
||
* 获取系统主题
|
||
*/
|
||
getTheme () {
|
||
let theme = 'system';
|
||
if (nativeTheme.shouldUseHighContrastColors) {
|
||
theme = 'light';
|
||
} else if (nativeTheme.shouldUseInvertedColorScheme) {
|
||
theme = 'dark';
|
||
}
|
||
|
||
return theme;
|
||
}
|
||
|
||
/**
|
||
* 设置系统主题
|
||
*/
|
||
setTheme (args) {
|
||
|
||
// TODO 好像没有什么明显效果
|
||
nativeTheme.themeSource = args;
|
||
|
||
return args;
|
||
}
|
||
|
||
|
||
/**
|
||
* 检查是否有新版本
|
||
*/
|
||
checkForUpdater () {
|
||
const config = this.app.config.autoUpdate;
|
||
if ( (is.windows() && config.windows) || (is.macOS() && config.macOS) || (is.linux() && config.linux) ) {
|
||
const autoUpdater = require('../library/autoUpdater');
|
||
autoUpdater.checkUpdate();
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
/**
|
||
* 下载新版本
|
||
*/
|
||
downloadApp () {
|
||
const config = this.app.config.autoUpdate;
|
||
if ( (is.windows() && config.windows) || (is.macOS() && config.macOS) || (is.linux() && config.linux) ) {
|
||
const autoUpdater = require('../library/autoUpdater');
|
||
autoUpdater.download();
|
||
}
|
||
return;
|
||
}
|
||
|
||
/**
|
||
* 检测http服务是否开启
|
||
*/
|
||
async checkHttpServer () {
|
||
const httpServerConfig = this.app.config.httpServer;
|
||
const url = httpServerConfig.protocol + httpServerConfig.host + ':' + httpServerConfig.port;
|
||
|
||
const data = {
|
||
enable: httpServerConfig.enable,
|
||
server: url
|
||
}
|
||
return data;
|
||
}
|
||
|
||
/**
|
||
* 一个http请求访问此方法
|
||
*/
|
||
async doHttpRequest () {
|
||
// http方法
|
||
const method = this.app.request.method;
|
||
// http get 参数
|
||
let params = this.app.request.query;
|
||
params = (params instanceof Object) ? params : JSON.parse(JSON.stringify(params));
|
||
// http post 参数
|
||
const body = this.app.request.body;
|
||
|
||
const httpInfo = {
|
||
method,
|
||
params,
|
||
body
|
||
}
|
||
console.log('httpInfo:', httpInfo);
|
||
|
||
if (!body.id) {
|
||
return false;
|
||
}
|
||
const dir = electronApp.getPath(body.id);
|
||
shell.openPath(dir);
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 一个socket io请求访问此方法
|
||
*/
|
||
async doSocketRequest (args) {
|
||
if (!args.id) {
|
||
return false;
|
||
}
|
||
const dir = electronApp.getPath(args.id);
|
||
shell.openPath(dir);
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 异步消息类型
|
||
* @param args 前端传的参数
|
||
* @param event - IpcMainInvokeEvent 文档:https://www.electronjs.org/zh/docs/latest/api/structures/ipc-main-invoke-event
|
||
*/
|
||
async ipcInvokeMsg (args, event) {
|
||
let timeNow = dayjs().format('YYYY-MM-DD HH:mm:ss');
|
||
const data = args + ' - ' + timeNow;
|
||
|
||
return data;
|
||
}
|
||
|
||
/**
|
||
* 同步消息类型
|
||
* @param args 前端传的参数
|
||
* @param event - IpcMainEvent 文档:https://www.electronjs.org/docs/latest/api/structures/ipc-main-event
|
||
*/
|
||
async ipcSendSyncMsg (args) {
|
||
let timeNow = dayjs().format('YYYY-MM-DD HH:mm:ss');
|
||
const data = args + ' - ' + timeNow;
|
||
|
||
return data;
|
||
}
|
||
|
||
/**
|
||
* 双向异步通信
|
||
* @param args 前端传的参数
|
||
* @param event - IpcMainEvent 文档:https://www.electronjs.org/docs/latest/api/structures/ipc-main-event
|
||
*/
|
||
ipcSendMsg (args, event) {
|
||
// 前端ipc频道 channel
|
||
const channel = 'controller.example.ipcSendMsg';
|
||
|
||
if (args.type == 'start') {
|
||
// 每隔1秒,向前端页面发送消息
|
||
// 用定时器模拟
|
||
myTimer = setInterval(function(e, c, msg) {
|
||
let timeNow = Date.now();
|
||
let data = msg + ':' + timeNow;
|
||
e.reply(`${c}`, data)
|
||
}, 1000, event, channel, args.content)
|
||
|
||
return '开始了'
|
||
} else if (args.type == 'end') {
|
||
clearInterval(myTimer);
|
||
return '停止了'
|
||
} else {
|
||
return 'ohther'
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 上传文件
|
||
*/
|
||
async uploadFile() {
|
||
let tmpDir = Utils.getLogDir();
|
||
const files = this.app.request.files;
|
||
let file = files.file;
|
||
|
||
let tmpFilePath = path.join(tmpDir, file.originalFilename);
|
||
try {
|
||
let tmpFile = fs.readFileSync(file.filepath);
|
||
fs.writeFileSync(tmpFilePath, tmpFile);
|
||
} finally {
|
||
await fs.unlink(file.filepath, function(){});
|
||
}
|
||
const fileStream = fs.createReadStream(tmpFilePath);
|
||
const uploadRes = await this.service.example.uploadFileToSMMS(fileStream);
|
||
|
||
return uploadRes;
|
||
}
|
||
|
||
/**
|
||
* 测试接口
|
||
*/
|
||
hello (args) {
|
||
console.log('hello ', args);
|
||
}
|
||
}
|
||
|
||
ExampleController.toString = () => '[class ExampleController]';
|
||
module.exports = ExampleController;
|