mirror of
https://github.com/rubickCenter/rubick
synced 2025-06-20 03:03:40 +08:00
Merge branch 'master' of https://github.com/clouDr-f2e/rubick into master
This commit is contained in:
commit
129f19bf39
108
README.md
108
README.md
@ -15,12 +15,16 @@
|
|||||||
|
|
||||||
|
|
||||||
基于 electron 的工具箱,媲美 utools的开源插件,已实现 utools 大部分的 API 能力,所以可以做到无缝适配 utools 开源的插件。
|
基于 electron 的工具箱,媲美 utools的开源插件,已实现 utools 大部分的 API 能力,所以可以做到无缝适配 utools 开源的插件。
|
||||||
之所以做这个工具箱一方面是 utools 本身并未开源,但是公司内部的工具库又无法发布到 utools 插件中,所以为了既要享受 utools 生态又要有定制化需求,我们自己参考 utools 设计,做了 Rubick
|
之所以做这个工具箱一方面是 utools 本身并未开源,但是公司内部的工具库又无法发布到 utools 插件中,所以为了既要享受 utools 生态又要有定制化需求,我们自己参考 utools 设计,做了 Rubick.
|
||||||
|
|
||||||
|
Rubick(拉比克) 是 dota 里面的英雄之一,其核心技能是插件化使用其他英雄的技能,用完即走。非常符合本工具的设计理念,所以取名 Rubick。
|
||||||
|
|
||||||
## 安装包
|
## 安装包
|
||||||
* [Rubick Mac OS V0.0.2](https://github.com/clouDr-f2e/rubick/releases/download/v0.0.2/rubick2-0.0.2.pkg)
|
* [Rubick Mac OS V0.0.2](https://github.com/clouDr-f2e/rubick/releases/download/v0.0.2/rubick2-0.0.2.pkg)
|
||||||
|
|
||||||
## 支持能力
|
## 支持能力
|
||||||
|
- [x] 支持 uTools 90% API。可直接按照 uTools 文档开发 Rubick 插件
|
||||||
|
- [x] 支持 uTools github 开源插件。
|
||||||
- [x] 支持远程下载安装插件,支持插件开发者模式
|
- [x] 支持远程下载安装插件,支持插件开发者模式
|
||||||
- [x] 支持插件分离
|
- [x] 支持插件分离
|
||||||
- [x] 支持系统命令取色、截屏、帮助
|
- [x] 支持系统命令取色、截屏、帮助
|
||||||
@ -39,106 +43,42 @@
|
|||||||
1. 目前 `Rubick` 插件市场 server 端还没有部署,所以目前看不到插件市场的插件。
|
1. 目前 `Rubick` 插件市场 server 端还没有部署,所以目前看不到插件市场的插件。
|
||||||
2. 依赖于 `robotjs` dev 环境运行请在 `install` 后执行 `npm run rebuild`
|
2. 依赖于 `robotjs` dev 环境运行请在 `install` 后执行 `npm run rebuild`
|
||||||
|
|
||||||
## utools 插件支持
|
## 目前支持能力
|
||||||
### plugin.json
|
### 加载utools生态插件
|
||||||
在你觉得合适的地方新建一个文件夹,并创建 `plugin.json` 文件。这是最重要的一个文件,用来说明这个插件将如何与 `rubick` 集成,最基本的格式如下:
|
拿 `github` 上开源的 斗图 插件举例,要加载斗图插件,只需要将代码 clone下来后,复制其 `plugin.json` 进入搜索框即可使用
|
||||||
```json
|
|
||||||
{
|
|
||||||
"pluginName": "helloWorld",
|
|
||||||
"description": "我的第一个uTools插件",
|
|
||||||
"main": "index.html",
|
|
||||||
"version": "0.0.1",
|
|
||||||
"logo": "logo.png",
|
|
||||||
"features": [
|
|
||||||
{
|
|
||||||
"code": "hello",
|
|
||||||
"explain": "hello world",
|
|
||||||
"cmds":["hello", "你好"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
所有字段和 `utools` 保持一致,这将可以完美使用`utools`的插件生态
|
|
||||||
|
|
||||||
## utools api 支持
|
斗图:https://github.com/vst93/doutu-uToolsPlugin
|
||||||
|
|
||||||
### 事件
|
<img src=https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/cba1eb758180433294c93b59724adefd~tplv-k3u1fbpfcp-watermark.image width=500 />
|
||||||
|
|
||||||
#### onPluginReady(callback)
|
### 超级面板
|
||||||
* `callback` Function
|
长按鼠标右键,即可呼起超级面板,可以根据当前鼠标选择内容,匹配对应插件能力。比如当前选择图片后长按右击,则会呼起上传图床插件:
|
||||||
|
|
||||||
> 当插件装载成功,uTools 将会主动调用这个方法(生命周期内仅调用一次),所有的 `api` 都应该在 `onPluginReady` 之后进行调用。
|

|
||||||
|
|
||||||
##### 示例
|
### 模板
|
||||||
|
为了更贴合 `uTools` 的插件能力,需要实现模板功能,模板即是一个内置 UI 样式的功能插件。
|
||||||
|
|
||||||
```js
|
<img src=https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0b113ad547974699b9c73c28bc09b9b1~tplv-k3u1fbpfcp-watermark.image width=500 />
|
||||||
utools.onPluginReady(() => {
|
|
||||||
console.log('插件装配完成,已准备好')
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
#### onPluginEnter(callback)
|
### utools 自带的系统命令
|
||||||
* `callback` Function
|
#### 取色
|
||||||
|
基于 `robot.js` 以及 `iohook` 实现。未使用 C++ 扩展。
|
||||||
|
|
||||||
> 每当插件从后台进入到前台时,uTools 将会主动调用这个方法。
|
<img src=https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8c3e00e5f08545bcb96613689649b337~tplv-k3u1fbpfcp-watermark.image width=500 />
|
||||||
|
|
||||||
##### 示例
|
#### 截屏
|
||||||
|
|
||||||
```js
|
<img src=https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/18023dab52e1420c9e87362cefddb2a1~tplv-k3u1fbpfcp-watermark.image width=500 />
|
||||||
utools.onPluginEnter(({code, type, payload, optional}) => {
|
|
||||||
console.log('用户进入插件', code, type, payload)
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
更多可以参考 `utools` 文档:https://u.tools/docs/developer/api.html#%E4%BA%8B%E4%BB%B6
|
|
||||||
|
|
||||||
### 窗口交互
|
|
||||||
|
|
||||||
|
|
||||||
### 本地数据库
|
#### 全局快捷键
|
||||||
类似于 `utools` 的功能,我们也提供了本地数据库的 api 能力
|
|
||||||
|
|
||||||
#### utools.db.put(doc)
|
<img src=https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/62cc424eacac4c9eb178f0e055e87d9a~tplv-k3u1fbpfcp-watermark.image width=500 />
|
||||||
|
|
||||||
##### 示例
|
|
||||||
```js
|
|
||||||
// 创建请求
|
|
||||||
utools.db.put({
|
|
||||||
_id: "demo",
|
|
||||||
data: "demo"
|
|
||||||
})
|
|
||||||
// 返回 {id: "demo", ok: true, rev: "1-05c9b92e6f24287dc1f4ec79d9a34fa8"}
|
|
||||||
|
|
||||||
// 更新请求
|
|
||||||
utools.db.put({
|
|
||||||
_id: "demo",
|
|
||||||
data: "demo",
|
|
||||||
_rev: "1-05c9b92e6f24287dc1f4ec79d9a34fa8"
|
|
||||||
})
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
#### utools.db.get(id)
|
|
||||||
#### utools.db.remove(doc)
|
|
||||||
#### utools.db.bulkDocs(docs)
|
|
||||||
|
|
||||||
### ubrowser
|
|
||||||
可编程浏览器
|
|
||||||
|
|
||||||
```js
|
|
||||||
const page = await utools.ubrowser.goto('https://www.baidu.com')
|
|
||||||
await page.value('#kw', 'uTools');
|
|
||||||
await page.click('#su');
|
|
||||||
page.run({
|
|
||||||
width: 600,
|
|
||||||
height: 800,
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
### 最后
|
### 最后
|
||||||
utools过于强大,目前还没有完全实现其所有功能,不过我们会根据需要不断更新。欢迎小伙伴一起 `pr` 或 `star`
|
utools过于强大,目前还没有完全实现其所有功能,不过我们会根据需要不断更新。欢迎小伙伴一起 `pr` 或 `star`
|
||||||
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
This project is licensed under the MIT License - see the [LICENSE.md](https://github.com/clouDr-f2e/rubick/blob/master/LICENSE) file for details.
|
This project is licensed under the MIT License - see the [LICENSE.md](https://github.com/clouDr-f2e/rubick/blob/master/LICENSE) file for details.
|
||||||
|
|
||||||
|
@ -181,7 +181,7 @@ class Listener {
|
|||||||
// 锁屏
|
// 锁屏
|
||||||
ipcMain.on('lock-screen', () => {
|
ipcMain.on('lock-screen', () => {
|
||||||
const lockCommands = {
|
const lockCommands = {
|
||||||
darwin: '/System/Library/CoreServices/"Menu Extras"/User.menu/Contents/Resources/CGSession -suspend',
|
darwin: '/System/Library/CoreServices/ScreenSaverEngine.app/Contents/MacOS/ScreenSaverEngine',
|
||||||
win32: 'rundll32.exe user32.dll, LockWorkStation',
|
win32: 'rundll32.exe user32.dll, LockWorkStation',
|
||||||
linux: '(hash gnome-screensaver-command 2>/dev/null && gnome-screensaver-command -l) || (hash dm-tool 2>/dev/null && dm-tool lock)'
|
linux: '(hash gnome-screensaver-command 2>/dev/null && gnome-screensaver-command -l) || (hash dm-tool 2>/dev/null && dm-tool lock)'
|
||||||
};
|
};
|
||||||
|
@ -7,7 +7,20 @@ function createTray(window) {
|
|||||||
const appIcon = new Tray(path.join(__static, './rocket.png'));
|
const appIcon = new Tray(path.join(__static, './rocket.png'));
|
||||||
const contextMenu = Menu.buildFromTemplate([
|
const contextMenu = Menu.buildFromTemplate([
|
||||||
{
|
{
|
||||||
id: 3,
|
label: "帮助文档", click: () => {
|
||||||
|
process.nextTick((() => {
|
||||||
|
shell.openExternal('https://github.com/clouDr-f2e/rubick');
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
label: "意见反馈", click: () => {
|
||||||
|
process.nextTick((() => {
|
||||||
|
shell.openExternal('https://github.com/clouDr-f2e/rubick/issues')
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{type: "separator"},
|
||||||
|
{
|
||||||
label: '显示窗口',
|
label: '显示窗口',
|
||||||
accelerator: "Alt+R",
|
accelerator: "Alt+R",
|
||||||
click() {
|
click() {
|
||||||
@ -15,23 +28,25 @@ function createTray(window) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 4,
|
role: 'quit',
|
||||||
label: '文档',
|
label: '退出'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '重启',
|
||||||
click() {
|
click() {
|
||||||
shell.openExternal('https://muwoo.github.io/rubick-doc/');
|
app.relaunch();
|
||||||
|
app.quit();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{type: "separator"},
|
||||||
{
|
{
|
||||||
id: 5,
|
label: '偏好设置',
|
||||||
label: '显示窗口',
|
|
||||||
click() {
|
click() {
|
||||||
window.show();
|
window.show();
|
||||||
}
|
window.webContents.send('tray-setting');
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
id: 6,
|
|
||||||
label: '关于',
|
label: '关于',
|
||||||
click() {
|
click() {
|
||||||
dialog.showMessageBox({
|
dialog.showMessageBox({
|
||||||
@ -39,21 +54,8 @@ function createTray(window) {
|
|||||||
message: '极简、插件化的现代桌面软件',
|
message: '极简、插件化的现代桌面软件',
|
||||||
detail: `Version: ${pkg.version}\nAuthor: muwoo`
|
detail: `Version: ${pkg.version}\nAuthor: muwoo`
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: 7,
|
|
||||||
role: 'quit',
|
|
||||||
label: '退出'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 7,
|
|
||||||
label: '重启',
|
|
||||||
click() {
|
|
||||||
app.relaunch();
|
|
||||||
app.exit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]);
|
]);
|
||||||
appIcon.on('click', () => {
|
appIcon.on('click', () => {
|
||||||
appIcon.popUpContextMenu(contextMenu);
|
appIcon.popUpContextMenu(contextMenu);
|
||||||
|
@ -108,6 +108,7 @@ export default {
|
|||||||
ipcRenderer.on('new-window', this.newWindow);
|
ipcRenderer.on('new-window', this.newWindow);
|
||||||
// 超级面板打开插件
|
// 超级面板打开插件
|
||||||
ipcRenderer.on('superPanel-openPlugin', (e, args) => {
|
ipcRenderer.on('superPanel-openPlugin', (e, args) => {
|
||||||
|
this.closeTag();
|
||||||
ipcRenderer.send('msg-trigger', {
|
ipcRenderer.send('msg-trigger', {
|
||||||
type: 'showMainWindow',
|
type: 'showMainWindow',
|
||||||
});
|
});
|
||||||
@ -145,6 +146,11 @@ export default {
|
|||||||
});
|
});
|
||||||
config && this.openPlugin(config);
|
config && this.openPlugin(config);
|
||||||
});
|
});
|
||||||
|
// 打开偏好设置
|
||||||
|
ipcRenderer.on('tray-setting', () => {
|
||||||
|
this.showMainUI();
|
||||||
|
this.changePath({key: 'settings'});
|
||||||
|
});
|
||||||
const searchNd = document.getElementById('search');
|
const searchNd = document.getElementById('search');
|
||||||
searchNd && searchNd.addEventListener('keydown', this.checkNeedInit)
|
searchNd && searchNd.addEventListener('keydown', this.checkNeedInit)
|
||||||
},
|
},
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<a-list-item-meta
|
<a-list-item-meta
|
||||||
@click="showPannel(item)"
|
@click="showPannel(item, index)"
|
||||||
:description="item.description"
|
:description="item.description"
|
||||||
>
|
>
|
||||||
<div slot="title">{{ item.pluginName }}</div>
|
<div slot="title">{{ item.pluginName }}</div>
|
||||||
@ -37,12 +37,43 @@
|
|||||||
</a-list-item-meta>
|
</a-list-item-meta>
|
||||||
</a-list-item>
|
</a-list-item>
|
||||||
</a-list>
|
</a-list>
|
||||||
|
<a-drawer
|
||||||
|
placement="right"
|
||||||
|
:visible="show"
|
||||||
|
@close="show=false"
|
||||||
|
width="100%"
|
||||||
|
>
|
||||||
|
<div class="plugin-market-desc" slot="title">
|
||||||
|
<img width="80" :src="currentSelect.logo"/>
|
||||||
|
<div class="desc">
|
||||||
|
<h4>{{currentSelect.pluginName}}</h4>
|
||||||
|
<div class="info">
|
||||||
|
<div class="actor">
|
||||||
|
开发者:{{currentSelect.author}}
|
||||||
|
<a-button
|
||||||
|
v-if="showButton(currentSelect)"
|
||||||
|
:loading="loading[currentSelect.index]"
|
||||||
|
@click="download(currentSelect.index, currentSelect)"
|
||||||
|
icon="cloud-download"
|
||||||
|
type="primary"
|
||||||
|
>
|
||||||
|
获取
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
<div>{{currentSelect.description}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="market-plugin-detail" v-html="readme"></div>
|
||||||
|
</a-drawer>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import api from '../../../assets/api';
|
import api from '../../../assets/api';
|
||||||
import {mapActions, mapState} from 'vuex';
|
import {mapActions, mapState} from 'vuex';
|
||||||
|
import marked from "marked";
|
||||||
|
const rendererMD = new marked.Renderer();
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
@ -78,19 +109,68 @@ export default {
|
|||||||
showButton(item) {
|
showButton(item) {
|
||||||
return !this.devPlugins.filter(plugin => (plugin.name === item.name && plugin.type === 'prod')).length;
|
return !this.devPlugins.filter(plugin => (plugin.name === item.name && plugin.type === 'prod')).length;
|
||||||
},
|
},
|
||||||
showPannel(item) {
|
showPannel(item, index) {
|
||||||
this.show = true;
|
this.show = true;
|
||||||
this.currentSelect = item;
|
this.currentSelect = item;
|
||||||
|
this.currentSelect.index = index;
|
||||||
},
|
},
|
||||||
...mapActions('main', ['downloadPlugin'])
|
...mapActions('main', ['downloadPlugin'])
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState('main', ['devPlugins'])
|
...mapState('main', ['devPlugins']),
|
||||||
|
readme() {
|
||||||
|
marked.setOptions({
|
||||||
|
renderer: rendererMD,
|
||||||
|
gfm: true,
|
||||||
|
tables: true,
|
||||||
|
breaks: false,
|
||||||
|
pedantic: false,
|
||||||
|
sanitize: false,
|
||||||
|
smartLists: true,
|
||||||
|
smartypants: false
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
return marked(this.currentSelect.detail);
|
||||||
|
} catch (e) {
|
||||||
|
return '暂无描述信息'
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
.market-plugin-detail {
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
height: 430px;
|
||||||
|
overflow: auto;
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.plugin-market-desc {
|
||||||
|
display: flex;
|
||||||
|
img {
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
.desc {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.info {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
font-weight: normal;
|
||||||
|
padding-right: 40px;
|
||||||
|
}
|
||||||
|
.actor {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
}
|
||||||
.market {
|
.market {
|
||||||
height: calc(~'100vh - 110px');
|
height: calc(~'100vh - 110px');
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user