这两天工作又比较忙,没看书,没思考,写一篇简单的技术教程。其实我是不想写这种的,因为本身没啥技术含量,只是把写的东西整理一下,即提高不了技术,也没有思考深度,以后要少写,这类还是以笔记的形式记录到博客即可。
最近公司在推jira,但是整体感觉用起来很困难。主要因为是日常浏览器用的会比较多,基本上chrome上都有四五十个tab标签,经常会切到其它tab看东西,然后每次想要找jira的时候都不太好找,所以就想把jira单独打成一个桌面应用,整体操作和心理感受上感觉都简单很多。
Electron是由Github开发,用HTML,CSS和JavaScript来构建跨平台桌面应用程序的一个开源库。 Electron通过将Chromium和Node.js合并到同一个运行时环境中,并将其打包为Mac,Windows和Linux系统下的应用来实现这一目的。
新建一个项目并安装electron electron-builder两个依赖
mkdir desktopdemo
cd desktopdemo
cnpm init
cnpm i electron --save-dev
cnpm i electron-builder --save-dev
添加构建命令到package.json
"build": {
"appId": "com.example.app",
"mac": {
"target": [
"dmg",
"zip"
]
},
"win": {
"target": [
"nsis",
"zip"
]
}
},
"scripts": {
"start": "electron .",
"dist": "electron-builder"
},
新建index.js
(async () => {
const {app, BrowserWindow, BrowserView, ipcMain, webContents} = require("electron");
const {join} = require("path");
await app.whenReady()
const window = new BrowserWindow({
webPreferences: {
sandbox: false,
nodeIntegration: true,
contextIsolation: false
}
});
await window.loadFile(join(__dirname, "./titlebar.html"));
const browserView = new BrowserView({
webPreferences: {
sandbox: true,
nodeIntegration: false
}
});
window.setBrowserView(browserView);
// const contents = window.webContents;
// contents.openDevTools(); //打开调试工具
const contentBounds = window.getContentBounds();
browserView.setBounds({x: 0, y: 50, width: contentBounds.width, height: contentBounds.height - 30});
browserView.setAutoResize({width: true, height: true});
await browserView.webContents.loadURL("https://www.liuyushuai.com/"); // 更换自己的域名
window.webContents.send("sendId", browserView.webContents.id);
window.webContents.on('did-finish-load', function () {
window.webContents.send("sendId", browserView.webContents.id);
})
browserView.webContents.on("did-navigate", () => {
window.webContents.send("canNav", browserView.webContents.canGoBack(), browserView.webContents.canGoForward());
});
ipcMain.on("goBack", (e, webContentsId) => {
const wc = webContents.fromId(webContentsId);
if (wc && wc.canGoBack()) {
wc.goBack();
}
});
ipcMain.on("goForward", (e, webContentsId) => {
const wc = webContents.fromId(webContentsId);
if (wc && wc.canGoForward()) {
wc.goForward();
}
});
})();
新建titlebar.html
<html>
<body>
<div id="toolbar">
<button id="back" class="button back" disabled>go back</button>
<button id="forward" class="button next" disabled>go forward</button>
</div>
<script src="./renderer.js"></script>
<style>
#toolbar {
height: 50px;
}
a {
margin: 10px;
}
.active {
color:#555 !important;
}
.button {
display: inline-block;
position: relative;
color: #888;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.8);
text-decoration: none;
text-align: center;
padding: 8px 12px;
font-size: 12px;
font-weight: 700;
font-family: helvetica, arial, sans-serif;
border-radius: 4px;
border: 1px solid #bcbcbc;
-webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
background-image: -webkit-linear-gradient(top, #fff 0%, #efefef 60%, #e1dfe2 100%);
background-image: -moz-linear-gradient(top, #fff 0%, #efefef 60%, #e1dfe2 100%);
background-image: -o-linear-gradient(top, #fff 0%, #efefef 60%, #e1dfe2 100%);
background-image: -ms-linear-gradient(top, #fff 0%, #efefef 60%, #e1dfe2 100%);
background-image: linear-gradient(top, #fff 0%, #efefef 60%, #e1dfe2 100%);
}
.button:hover {
color: #555;
}
.button:active,
.button:active:after,
.button:active:before {
-webkit-box-shadow: none;
box-shadow: none;
/* Back Button */
}
.button.back {
border-left: none;
}
.button.back:after {
content: '';
position: absolute;
height: 50%;
width: 15px;
border-left: 1px solid #bcbcbc;
background-image: -webkit-linear-gradient(top, rgba(255, 255, 255, 0) 0%, #fff 1%, #f0f0f0 100%);
background-image: -moz-linear-gradient(top, rgba(255, 255, 255, 0) 0%, #fff 1%, #f0f0f0 100%);
background-image: -o-linear-gradient(top, rgba(255, 255, 255, 0) 0%, #fff 1%, #f0f0f0 100%);
background-image: -ms-linear-gradient(top, rgba(255, 255, 255, 0) 0%, #fff 1%, #f0f0f0 100%);
background-image: linear-gradient(top, rgba(255, 255, 255, 0) 0%, #fff 1%, #f0f0f0 100%);
left: -5px;
top: 1px;
-webkit-transform: skew(-35deg, 0);
-moz-transform: skew(-35deg, 0);
-o-transform: skew(-35deg, 0);
-ms-transform: skew(-35deg, 0);
transform: skew(-35deg, 0);
}
.button.back:before {
content: '';
position: absolute;
height: 48%;
width: 15px;
border-left: 1px solid #bcbcbc;
bottom: 1px;
left: -5px;
-webkit-transform: skew(35deg, 0);
-moz-transform: skew(35deg, 0);
-o-transform: skew(35deg, 0);
-ms-transform: skew(35deg, 0);
transform: skew(35deg, 0);
background-image: -webkit-linear-gradient(top, #f0f0f0 0%, #efefef 10%, #e1dfe2 100%);
background-image: -moz-linear-gradient(top, #f0f0f0 0%, #efefef 10%, #e1dfe2 100%);
background-image: -o-linear-gradient(top, #f0f0f0 0%, #efefef 10%, #e1dfe2 100%);
background-image: -ms-linear-gradient(top, #f0f0f0 0%, #efefef 10%, #e1dfe2 100%);
background-image: linear-gradient(top, #f0f0f0 0%, #efefef 10%, #e1dfe2 100%);
-webkit-box-shadow: -2px 1px 2px rgba(100, 100, 100, 0.1);
box-shadow: -2px 1px 2px rgba(100, 100, 100, 0.1);
/* Next Button */
}
.button.next {
border-right: none;
}
.button.next:after {
content: '';
position: absolute;
height: 48%;
width: 15px;
border-right: 1px solid #bcbcbc;
background-image: -webkit-linear-gradient(top, #f0f0f0 0%, #efefef 10%, #e1dfe2 100%);
background-image: -moz-linear-gradient(top, #f0f0f0 0%, #efefef 10%, #e1dfe2 100%);
background-image: -o-linear-gradient(top, #f0f0f0 0%, #efefef 10%, #e1dfe2 100%);
background-image: -ms-linear-gradient(top, #f0f0f0 0%, #efefef 10%, #e1dfe2 100%);
background-image: linear-gradient(top, #f0f0f0 0%, #efefef 10%, #e1dfe2 100%);
right: -5px;
bottom: 1px;
-webkit-transform: skew(-35deg, 0);
-moz-transform: skew(-35deg, 0);
-o-transform: skew(-35deg, 0);
-ms-transform: skew(-35deg, 0);
transform: skew(-35deg, 0);
-webkit-box-shadow: 2px 1px 2px rgba(100, 100, 100, 0.1);
box-shadow: 2px 1px 2px rgba(100, 100, 100, 0.1);
}
.button.next:before {
content: '';
position: absolute;
background-image: -webkit-linear-gradient(top, rgba(255, 255, 255, 0) 0%, #fff 1%, #f0f0f0 100%);
background-image: -moz-linear-gradient(top, rgba(255, 255, 255, 0) 0%, #fff 1%, #f0f0f0 100%);
background-image: -o-linear-gradient(top, rgba(255, 255, 255, 0) 0%, #fff 1%, #f0f0f0 100%);
background-image: -ms-linear-gradient(top, rgba(255, 255, 255, 0) 0%, #fff 1%, #f0f0f0 100%);
background-image: linear-gradient(top, rgba(255, 255, 255, 0) 0%, #fff 1%, #f0f0f0 100%);
height: 50%;
width: 15px;
border-right: 1px solid #bcbcbc;
top: 1px;
right: -5px;
-webkit-transform: skew(35deg, 0);
-moz-transform: skew(35deg, 0);
-o-transform: skew(35deg, 0);
-ms-transform: skew(35deg, 0);
transform: skew(35deg, 0);
}
</style>
</body>
</html>
新建 renderer.js
const {ipcRenderer} = require("electron");
const backButton = document.getElementById("back");
const forwardButton = document.getElementById("forward");
let webContentsId = -1;
ipcRenderer.on("sendId", (e, id) => {
webContentsId = id;
});
ipcRenderer.on("canNav", (e, canBack, canForward) => {
backButton.disabled = !canBack;
forwardButton.disabled = !canForward;
backButton.classList = canBack ? "button back active":"button back";
forwardButton.classList = canForward?"button next active":"button next";
});
backButton.onclick = () => {
ipcRenderer.send("goBack", webContentsId);
};
forwardButton.onclick = () => {
ipcRenderer.send("goForward", webContentsId);
};
启动
cnpm start

打包
cnpm run dist
可以看到dist目录下打包好的包

非著名程序员,全栈开发工程师,长期专注系统开发与架构设计。
功能待开通!
自2月份开始,我对ChatGPT的精彩表现感到非常着迷,它展现出了真正的智能。随后,我陆续注册了ChatGPT Plus会员,申请了GPT-4 API权限等。起初,我通过简单的数学和逻辑题来测试它的智能水平;后来,我开始将其视为搜索引擎,不仅用于搜寻概念性知识,还用于解决技术问题、技术方案,甚至是公司业务应用。如今,ChatGPT已经逐渐融入了我的工作和生活。 然而,由于日常工作繁忙,我总是根据需要解决的问题,寻找针对性的方案,而没有认真研究过基于ChatGPT的应用现状。因此,我决定花时间了解一下ChatGPT相关的热门开源项目,并将所得到的信息整理和记录在此。 lencx/ChatGPT
shadowsocks 使用的 sockets5 代理,而一般只有浏览器支持,所以使用 shadowsocks 可以实现科学上网,但是其他的应用却仍无法科学上网,所以要想实现全局科学上网需要 Proxifier 支持。 Proxifier介绍 Proxifier是一款功能非常强大的socks5客户端,可以让不支持通过代理服务器工作的网络程序能通过HTTPS或SOCKS代理或代理链。支持 64位系统,支持Xp,Vista,Win7,MAC OS ,支持socks4,socks5,http代理协议,支持TCP,UDP协议,可以指定端口,指定IP,指定域名,指定程序等运行模式,兼容性非常好。有点类
问题 搭建好 svn 之后可以正常拉下库,但是 commit 的时候报以下权限错误。 > $ svn commit -m "test" svn: E170001: Commit failed (details follow): svn: E170001: Authorization failed 解决 问题是因为 svn 权限配置问题。
webcron 源码地址 功能列表 基本任务创建、启动、手动执行、暂停 任务日志 任务执行结果邮件通知 任务分组 任务运行实例控制 缺点 任务只能在单机跑 不能添加用户 评价 安装部署简单,功能页面简洁,适合任务量不多个人或者小型项目组使用。 gocron 源码地址 功能列表 基本任务创建、手动执行、禁止执行、删除 任务依赖 任务分组 超时、重试 可以选择任务执行结果通知不同用户,通知类型包括邮件(并支持模板配置)、slack、webhook。 任务日志 支持分布式,添加执行任务节点,创建任务可指定任务可运行的节点(如果是单例模式,会选择一台执行) 用户管理 登录日志 执行方式支持
我电脑上原本装了Xcode,但是我电脑是128G,用了两年东西越来越多硬盘不够用了,而我本身开发中很少用Xcode所以就把它卸载了,卸载之后发现Xcode占了11G左右的空间。。 卸载Xcode之后执行git,报错如下: > $ git status xcrun: error: active developer path ("/Applications/Xcode.app/Contents/Developer") does not exist Use `sudo xcode-select --switch path/to/Xcode.app` to specify the Xcode t