Emperor_Shun_Reading/electron/controller/os.js

634 lines
16 KiB
JavaScript
Raw Normal View History

2024-08-22 01:03:01 +00:00
'use strict';
const _ = require('lodash');
const path = require('path');
const { Controller } = require('ee-core');
const {
app: electronApp, dialog, shell, Notification,
powerMonitor, screen, nativeTheme
} = require('electron');
const Conf = require('ee-core/config');
const Ps = require('ee-core/ps');
const Services = require('ee-core/services');
const Addon = require('ee-core/addon');
const { getNetworkIFaceOne, getMac, getAllMac, getAllPhysicsMac } = require('@lzwme/get-physical-address');
const os = require('os');
const shutdown = require('electron-shutdown-command');
// 终端命令
const { exec, execSync, execFile } = require("child_process");
// 声音控制库 https://github.com/LinusU/node-loudness
const loudness = require("loudness");
// 文件处理
const fs = require('fs');
/**
* 操作系统 - 功能demo
* @class
*/
class OsController extends Controller {
constructor(ctx) {
super(ctx);
}
/**
* 所有方法接收两个参数
* @param args 前端传的参数
* @param event - ipc通信时才有值详情见控制器文档
*/
// 获取所有的网卡-无参数
async getAllMac(args) {
// 文档说明 https://github.com/lzwme/get-physical-address/blob/main/.github/README_zh-CN.md
const list = getAllPhysicsMac();
return list;
}
// 查找到指定进程并关闭? 注意 进程要全, 不然容易误杀
deviceKillName(name) {
// 最新 taskkill /F /IM program.exe 这个命令一句话能直接杀掉进程
const self = this;
let rebootShell = "tasklist|findstr " + name;
let command = exec(rebootShell, function (err, stdout, stderr) {
if (err || stderr) {
console.log("tasklist failed" + err + stderr);
} else {
const lines = stdout.split('\n')
console.log(lines);
for (let index = 0; index < lines.length; index++) {
const element = lines[index];
const strs = element.split(' ')
const firstNumber = strs.find(item => !isNaN(Number(item)) && item != '')
console.log('jincheng id :' + firstNumber);
self.deviceKillPid(firstNumber)
}
}
});
command.stdin.end();
command.on("close", function (code) {
console.log("tasklist", code);
});
}
// 杀掉pid 进程
deviceKillPid(pid) {
let rebootShell = "tskill " + pid;
let command = exec(rebootShell, function (err, stdout, stderr) {
if (err || stderr) {
console.log("tskill failed" + err + stderr);
}
})
command.stdin.end();
command.on("close", function (code) {
console.log("tskill", code);
});
}
// 启动指定目录的程序 可能有权限问题, 方案1 打包后管理员权限执行, 2 按照egg 的方案把需要执行的程序拷贝到安装包
deviceStarExe(path) {
let rebootShell = 'start ' + path;
exec(rebootShell);
}
/**
* 设备关机
*/
deviceShutdown() {
// 关机
// let shutdownShell = "shutdown -s -t 00";
console.log('deviceShutdown=============')
shutdown.shutdown();
return true;
}
deviceRestart(args) {
// 重启
let rebootShell = "shutdown -r -t 0";
let command = exec(rebootShell, function (err, stdout, stderr) {
if (err || stderr) {
console.log("shutdown failed" + err + stderr);
}
});
command.stdin.end();
command.on("close", function (code) {
console.log("shutdown", code);
});
}
// 同步执行 声音设置 支持0-100
async deviceLoudness(args) {
const value = args.value;
//操作系统平台
const pf = os.platform();
console.log("OS: " + pf)
// 特殊处理以下
if (pf == "linux") {
let shellStr = "amixer -D pulse set Master " + value + "% unmute"
if (value == 0) {
shellStr = "amixer -D pulse set Master mute"
}
// else{
// shellStr = "amixer -c 0 set Master,0 100%,80% unmute"
// }
let command = exec(shellStr, function (err, stdout, stderr) {
if (err || stderr) {
console.log("amixer failed" + err + stderr);
}
});
command.stdin.end();
command.on("close", function (code) {
console.log("amixer", code);
});
return;
} else {
/// 兼容模式, try catch 如果第一种方式报错, 在采用第二种
try {
//0 为静音
if (value == 0) {
await loudness.setMuted(true)
return await loudness.getMuted()
}
// 设置声音改为不静音 且设置声音
await loudness.setMuted(false)
await loudness.setVolume(value)
const newValue = await loudness.getVolume();
return newValue;
} catch {
const maxVolume = 65535;
let volumeValue = Math.round((value / 100) * maxVolume);
// 确保音量值在有效范围内
volumeValue = Math.max(0, Math.min(maxVolume, volumeValue));
// 将音量值转换为字符串
const valueStr = volumeValue.toString();
let excPath = path.join(Ps.getExtraResourcesDir(), 'nircmd.exe');
execFile(excPath, ['setsysvolume', valueStr], (error, stdout, stderr) => {
if (error) {
console.error(' Nircmd error: ', error);
return;
}
console.log('Nircmd ok ');
});
return value;
}
}
}
// 获取电脑信息
async getOSMessage(args) {
var OSDic = {};
var dealTime = (seconds) => {
var seconds = seconds | 0;
var day = (seconds / (3600 * 24)) | 0;
var hours = ((seconds - day * 3600) / 3600) | 0;
var minutes = ((seconds - day * 3600 * 24 - hours * 3600) / 60) | 0;
var second = seconds % 60;
(day < 10) && (day = '0' + day);
(hours < 10) && (hours = '0' + hours);
(minutes < 10) && (minutes = '0' + minutes);
(second < 10) && (second = '0' + second);
return [day, hours, minutes, second].join(':');
};
var dealMem = (mem) => {
var G = 0,
M = 0,
KB = 0;
(mem > (1 << 30)) && (G = (mem / (1 << 30)).toFixed(2));
(mem > (1 << 20)) && (mem < (1 << 30)) && (M = (mem / (1 << 20)).toFixed(2));
(mem > (1 << 10)) && (mem > (1 << 20)) && (KB = (mem / (1 << 10)).toFixed(2));
return G > 0 ? G + 'G' : M > 0 ? M + 'M' : KB > 0 ? KB + 'KB' : mem + 'B';
};
//cpu架构
const arch = os.arch();
// console.log("cpu架构" + arch);
OSDic["arch"] = arch;
//操作系统内核
const kernel = os.type();
// console.log("操作系统内核:" + kernel);
OSDic["kernel"] = kernel;
//操作系统平台
const pf = os.platform();
// console.log("平台:" + pf);
OSDic["pf"] = pf;
//系统开机时间
const uptime = os.uptime();
// console.log("开机时间:" + dealTime(uptime));
OSDic["uptime"] = uptime;
//主机名
const hn = os.hostname();
// console.log("主机名:" + hn);
OSDic["hostname"] = hn;
// //主目录
// const hdir = os.homedir();
// console.log("主目录:" + hdir);
// OSDic["homedir"] = hdir;
//内存
const totalMem = os.totalmem();
const freeMem = os.freemem();
// console.log("内存大小:" + dealMem(totalMem) + ' 空闲内存:' + dealMem(freeMem));
OSDic["totalmem"] = totalMem;
OSDic["freeMem"] = freeMem;
//cpu
const cpus = os.cpus();
OSDic["cpuModel"] = cpus[0]["model"];
// OSDic["cpus"] = cpus;
// console.log('*****cpu信息*******');
// cpus.forEach((cpu, idx, arr) => {
// var times = cpu.times;
// console.log(`cpu${idx}`);
// console.log(`型号:${cpu.model}`);
// console.log(`频率:${cpu.speed}MHz`);
// console.log(`使用率:${((1 - times.idle / (times.idle + times.user + times.nice + times.sys + times.irq)) * 100).toFixed(2)}%`);
// });
try {
const volumeValue = await loudness.getVolume()
OSDic["volume"] = volumeValue;
console.log('volumeValue' + volumeValue);
} catch (error) {
console.log(error)
}
return OSDic;
}
// const volume = await loudness.getVolume()
// OSDic["volume"] = volume;
// return OSDic;
// }
/**
* 获取当前目录的配置
* @param {*} name 配置文件名
* @returns
*/
getCurrentDirectoryConfig(name) {
let configPath = '';
configPath = path.join(Ps.getExtraResourcesDir(), name);
console.log(configPath)
// let configJSON = null;
let dataString = null;
try {
// 同步读取配置文件
dataString = fs.readFileSync(configPath, 'utf8');
// 解析 JSON 格式的配置数据
// configJSON = JSON.parse(data);
// console.log('读取到的配置:', configJSON);
// 在这里可以根据需要使用配置数据进行操作
} catch (err) {
console.error('无法读取配置文件:', err);
}
return dataString;
}
/**
* 消息提示对话框
*/
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;
}
let dir = '';
if (path.isAbsolute(args.id)) {
dir = args.id;
} else {
dir = electronApp.getPath(args.id);
}
shell.openPath(dir);
return true;
}
/**
* 选择图片
*/
selectPic() {
const filePaths = dialog.showOpenDialogSync({
title: 'select pic',
properties: ['openFile'],
filters: [
{ name: 'Images', extensions: ['jpg', 'png', 'gif'] },
]
});
if (_.isEmpty(filePaths)) {
return null
}
return filePaths[0];
}
/**
* 加载视图内容
*/
loadViewContent(args) {
const { type, content } = args;
let contentUrl = content;
if (type == 'html') {
contentUrl = path.join('file://', electronApp.getAppPath(), content);
}
Services.get('os').createBrowserView(contentUrl);
return true
}
/**
* 移除视图内容
*/
removeViewContent() {
Services.get('os').removeBrowserView();
return true
}
/**
* 打开新窗口
*/
createWindow(args) {
const { type, content, windowName, windowTitle } = args;
let contentUrl = null;
if (type == 'html') {
contentUrl = path.join('file://', electronApp.getAppPath(), content)
} else if (type == 'web') {
contentUrl = content;
} else if (type == 'vue') {
let addr = 'http://localhost:17680'
if (Ps.isProd()) {
const mainServer = Conf.getValue('mainServer');
if (Conf.isFileProtocol(mainServer)) {
addr = mainServer.protocol + path.join(Ps.getHomeDir(), mainServer.indexPath);
} else {
addr = mainServer.protocol + mainServer.host + ':' + mainServer.port;
}
}
contentUrl = addr + content;
} else {
// some
}
console.log('contentUrl: ', contentUrl);
let opt = {
title: windowTitle
}
const win = Addon.get('window').create(windowName, opt);
const winContentsId = win.webContents.id;
// load page
win.loadURL(contentUrl);
return winContentsId;
}
/**
* 获取窗口contents id
*/
getWCid(args) {
// 主窗口的name默认是main其它窗口name开发者自己定义
const name = args;
const id = Addon.get('window').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);
// Log.info("[api] [example] [loadExtension] extension id:", extensionId);
// unzip(crxFile, extensionDir).then(() => {
// Log.info("[api] [example] [loadExtension] unzip success!");
// chromeExtension.load(extensionId);
// });
// return true;
// }
/**
* 创建系统通知
*/
sendNotification(args, event) {
const { title, subtitle, body, silent } = args;
if (!Notification.isSupported()) {
return '当前系统不支持通知';
}
let options = {};
if (!_.isEmpty(title)) {
options.title = title;
}
if (!_.isEmpty(subtitle)) {
options.subtitle = subtitle;
}
if (!_.isEmpty(body)) {
options.body = body;
}
if (!_.isEmpty(silent)) {
options.silent = silent;
}
Services.get('os').createNotification(options, event);
return true
}
/**
* 电源监控
*/
initPowerMonitor(args, event) {
const channel = 'controller.os.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(args) {
let data = [];
let res = {};
if (args == 0) {
let res = screen.getCursorScreenPoint();
data = [
{
title: '横坐标',
desc: res.x
},
{
title: '纵坐标',
desc: res.y
},
]
return data;
}
if (args == 1) {
res = screen.getPrimaryDisplay();
}
if (args == 2) {
let resArr = screen.getAllDisplays();
// 数组,只取一个吧
res = resArr[0];
}
// Log.info('[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;
}
/**
* 获取系统主题
*/
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;
}
}
OsController.toString = () => '[class OsController]';
module.exports = OsController;