mirror of
https://github.com/rubickCenter/rubick
synced 2025-08-10 05:49:33 +08:00
✨ 支持偏好设置
This commit is contained in:
parent
64f2eba2fa
commit
fc7e3e91bd
@ -3,7 +3,7 @@
|
||||
"pluginName": "rubick 系统菜单",
|
||||
"description": "rubick 系统菜单",
|
||||
"main": "index.html",
|
||||
"logo": "logo.jpg",
|
||||
"logo": "httpss://static.91jkys.com/upload/202112/08/8a1abbb051bf4b05bbc9bbf66ade63f2.png",
|
||||
"version": "0.0.0",
|
||||
"preload":"preload.js",
|
||||
"pluginType": "ui",
|
||||
|
@ -20,7 +20,7 @@
|
||||
</template>
|
||||
设置
|
||||
</a-menu-item>
|
||||
<a-menu-item key="user">
|
||||
<a-menu-item key="account">
|
||||
<template #icon>
|
||||
<UserOutlined />
|
||||
</template>
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router";
|
||||
import Market from "../views/market/index.vue";
|
||||
import Installed from "../views/installed/index.vue";
|
||||
import Account from "../views/account/index.vue";
|
||||
import Settings from "../views/settings/index.vue";
|
||||
|
||||
const routes: Array<RouteRecordRaw> = [
|
||||
{
|
||||
@ -13,6 +15,16 @@ const routes: Array<RouteRecordRaw> = [
|
||||
name: "installed",
|
||||
component: Installed,
|
||||
},
|
||||
{
|
||||
path: "/account",
|
||||
name: "account",
|
||||
component: Account,
|
||||
},
|
||||
{
|
||||
path: "/settings",
|
||||
name: "settings",
|
||||
component: Settings,
|
||||
},
|
||||
{
|
||||
path: "/:catchAll(.*)",
|
||||
name: "market",
|
||||
|
21
feature/src/views/account/index.vue
Normal file
21
feature/src/views/account/index.vue
Normal file
@ -0,0 +1,21 @@
|
||||
<template>
|
||||
<div class="account">
|
||||
<a-result status="404" title="玩命开发中" sub-title="个人中心正在开发中,敬请期待...">
|
||||
</a-result>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.account {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
overflow-x: hidden;
|
||||
background: #f3efef;
|
||||
height: calc(~"100vh - 46px");
|
||||
}
|
||||
</style>
|
@ -1,10 +1,17 @@
|
||||
<template>
|
||||
<div class="installed">
|
||||
<div class="installed-list">
|
||||
<div :class="currentSelect === index ? 'item active' : 'item'" :key="index" v-for="(plugin, index) in localPlugins">
|
||||
<div
|
||||
:class="currentSelect === index ? 'item active' : 'item'"
|
||||
:key="index"
|
||||
v-for="(plugin, index) in localPlugins"
|
||||
>
|
||||
<img :src="plugin.logo" />
|
||||
<div class="info">
|
||||
<div class="title">{{ plugin.pluginName }} <span class="desc">v{{ plugin.version }}</span></div>
|
||||
<div class="title">
|
||||
{{ plugin.pluginName }}
|
||||
<span class="desc">v{{ plugin.version }}</span>
|
||||
</div>
|
||||
<div class="desc">{{ plugin.description }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -17,27 +24,44 @@
|
||||
<a-tag>{{ pluginDetail.version }}</a-tag>
|
||||
</div>
|
||||
<div class="desc">
|
||||
开发者:{{`${pluginDetail.author || '未知'}`}}
|
||||
开发者:{{ `${pluginDetail.author || "未知"}` }}
|
||||
</div>
|
||||
<div class="desc">
|
||||
{{pluginDetail.description}}
|
||||
{{ pluginDetail.description }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<a-button type="danger" size="small" shape="round" @click="deletePlugin(pluginDetail)">移除</a-button>
|
||||
<a-button
|
||||
type="danger"
|
||||
size="small"
|
||||
shape="round"
|
||||
@click="deletePlugin(pluginDetail)"
|
||||
>移除</a-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<a-tabs default-active-key="1">
|
||||
<a-tab-pane key="1" tab="功能关键字">
|
||||
<div class="feature-container">
|
||||
<div class="desc-item" :key="index" v-for="(item, index) in pluginDetail.features">
|
||||
<div>{{item.explain}}</div>
|
||||
<div
|
||||
class="desc-item"
|
||||
:key="index"
|
||||
v-for="(item, index) in pluginDetail.features"
|
||||
>
|
||||
<div>{{ item.explain }}</div>
|
||||
<a-tag
|
||||
:key="cmd"
|
||||
@click="openPlugin({cmd, plugin: pluginDetail, feature: item, router: $router})"
|
||||
@click="
|
||||
openPlugin({
|
||||
cmd,
|
||||
plugin: pluginDetail,
|
||||
feature: item,
|
||||
router: $router,
|
||||
})
|
||||
"
|
||||
v-for="cmd in item.cmds"
|
||||
>
|
||||
{{cmd}}
|
||||
{{ cmd }}
|
||||
</a-tag>
|
||||
</div>
|
||||
</div>
|
||||
@ -74,12 +98,18 @@ const pluginDetail = computed(() => {
|
||||
});
|
||||
|
||||
const readme = computed(() => {
|
||||
if(!pluginDetail.value.name) return "";
|
||||
const str = fs.readFileSync(
|
||||
path.resolve(baseDir, "node_modules", pluginDetail.value.name, "readme.md"),
|
||||
"utf-8"
|
||||
if (!pluginDetail.value.name) return "";
|
||||
const readmePath = path.resolve(
|
||||
baseDir,
|
||||
"node_modules",
|
||||
pluginDetail.value.name,
|
||||
"readme.md"
|
||||
);
|
||||
return md.render(str);
|
||||
if (fs.existsSync(readmePath)) {
|
||||
const str = fs.readFileSync(readmePath, "utf-8");
|
||||
return md.render(str);
|
||||
}
|
||||
return "";
|
||||
});
|
||||
|
||||
const deletePlugin = async (plugin) => {
|
||||
@ -93,7 +123,7 @@ const deletePlugin = async (plugin) => {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
background: #F3EFEF;
|
||||
background: #f3efef;
|
||||
height: calc(~"100vh - 46px");
|
||||
display: flex;
|
||||
.installed-list {
|
||||
@ -139,7 +169,8 @@ const deletePlugin = async (plugin) => {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
.detail-container, .feature-container {
|
||||
.detail-container,
|
||||
.feature-container {
|
||||
height: 380px;
|
||||
overflow: auto;
|
||||
img {
|
||||
|
@ -14,11 +14,12 @@
|
||||
/>
|
||||
</a-button>
|
||||
</template>
|
||||
<a-list-item-meta
|
||||
:description="item.description"
|
||||
>
|
||||
<a-list-item-meta>
|
||||
<template #description>
|
||||
<span class="ellipse">{{ item.description }}</span>
|
||||
</template>
|
||||
<template #title>
|
||||
<span>{{ item.pluginName }}</span>
|
||||
<span class="ellipse">{{ item.pluginName }}</span>
|
||||
</template>
|
||||
<template #avatar>
|
||||
<a-avatar :src="item.logo" />
|
||||
@ -45,8 +46,10 @@
|
||||
<ArrowLeftOutlined />
|
||||
</div>
|
||||
<div class="info">
|
||||
<img src="https://static.91jkys.com/activity/img/2adb63c2e5d54dc1b26001958fcdb044.jpg"
|
||||
class="plugin-icon" />
|
||||
<img
|
||||
src="https://static.91jkys.com/activity/img/2adb63c2e5d54dc1b26001958fcdb044.jpg"
|
||||
class="plugin-icon"
|
||||
/>
|
||||
<div class="plugin-desc">
|
||||
<div class="title">
|
||||
备忘快贴
|
||||
@ -104,6 +107,13 @@ const visible = ref(false);
|
||||
.title {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
.ellipse {
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: 100%;
|
||||
}
|
||||
&:after{
|
||||
content: " ";
|
||||
display: block;
|
||||
|
340
feature/src/views/settings/index.vue
Normal file
340
feature/src/views/settings/index.vue
Normal file
@ -0,0 +1,340 @@
|
||||
<template>
|
||||
<div class="settings">
|
||||
<div class="left-menu">
|
||||
<a-menu v-model:selectedKeys="currentSelect" mode="inline">
|
||||
<a-menu-item key="normal">
|
||||
<template #icon>
|
||||
<ToolOutlined />
|
||||
</template>
|
||||
基本设置
|
||||
</a-menu-item>
|
||||
<a-menu-item key="global">
|
||||
<template #icon>
|
||||
<LaptopOutlined />
|
||||
</template>
|
||||
全局快捷键
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</div>
|
||||
<div class="settings-detail">
|
||||
<div v-if="currentSelect[0] === 'normal'">
|
||||
<div class="setting-item">
|
||||
<div class="title">
|
||||
快捷键(需要使用 option/ctrl/shift/command 键修饰)
|
||||
</div>
|
||||
<div class="settings-item-li">
|
||||
<div class="label">显示/隐藏快捷键</div>
|
||||
<div
|
||||
class="value"
|
||||
tabIndex="-1"
|
||||
@keyup="(e) => changeShortCut(e, 'showAndHidden')"
|
||||
>
|
||||
{{ config.perf.shortCut.showAndHidden }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings-item-li">
|
||||
<div class="label">插件分离快捷键</div>
|
||||
<div
|
||||
class="value"
|
||||
tabIndex="-1"
|
||||
@keyup="(e) => changeShortCut(e, 'separate')"
|
||||
>
|
||||
{{ config.perf.shortCut.separate }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings-item-li">
|
||||
<div class="label">返回主界面</div>
|
||||
<div
|
||||
class="value"
|
||||
tabIndex="-1"
|
||||
@keyup="(e) => changeShortCut(e, 'quit')"
|
||||
>
|
||||
{{ config.perf.shortCut.quit }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div class="title">通用</div>
|
||||
<div class="settings-item-li">
|
||||
<div class="label">开机启动</div>
|
||||
<a-switch
|
||||
v-model:checked="config.perf.common.start"
|
||||
checked-children="开"
|
||||
un-checked-children="关"
|
||||
></a-switch>
|
||||
</div>
|
||||
<div class="settings-item-li">
|
||||
<div class="label">空格执行</div>
|
||||
<a-switch
|
||||
v-model:checked="config.perf.common.space"
|
||||
checked-children="开"
|
||||
un-checked-children="关"
|
||||
></a-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div class="title">本地搜索启动</div>
|
||||
<div class="settings-item-li">
|
||||
<div class="label">搜索启动应用&文件</div>
|
||||
<a-switch
|
||||
v-model:checked="config.perf.local.search"
|
||||
checked-children="开"
|
||||
un-checked-children="关"
|
||||
></a-switch>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="currentSelect[0] === 'global'">
|
||||
<a-collapse>
|
||||
<a-collapse-panel key="1" header="说明及示例">
|
||||
<div>
|
||||
按下快捷键,自动搜索对应关键字,当关键字结果完全匹配,且结果唯一时,会直接指向该功能。
|
||||
</div>
|
||||
<h3 style="margin-top: 10px;">示例</h3>
|
||||
<a-divider style="margin: 5px 0;" />
|
||||
<a-list item-layout="horizontal" :data-source="examples">
|
||||
<template #renderItem="{ item }">
|
||||
<a-list-item>
|
||||
<a-list-item-meta :description="item.desc">
|
||||
<template #title>
|
||||
<div>{{ item.title }}</div>
|
||||
</template>
|
||||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
</template>
|
||||
</a-list>
|
||||
</a-collapse-panel>
|
||||
</a-collapse>
|
||||
<div class="feature-container">
|
||||
<div class="keywords item">
|
||||
<div>快捷键</div>
|
||||
<a-tooltip placement="top" trigger="click">
|
||||
<template #title>
|
||||
<span>先按功能键(Ctrl、Shift、Alt、Option、Command),再按其他普通键。或按
|
||||
F1-F12 单键
|
||||
</span>
|
||||
</template>
|
||||
<div
|
||||
:key="index"
|
||||
v-for="(item, index) in config.global"
|
||||
class="value"
|
||||
tabIndex="-1"
|
||||
@keyup="(e) => changeGlobalKey(e, index)"
|
||||
>
|
||||
{{ item.key }}
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<div class="short-cut item">
|
||||
<div>功能关键字</div>
|
||||
<a-input
|
||||
:key="index"
|
||||
:value="item.value"
|
||||
v-for="(item, index) in config.global"
|
||||
class="value"
|
||||
:disabled="!item.key"
|
||||
@change="(e) => changeGlobalValue(index, e.target.value)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div @click="addConfig" class="add-global">+ 新增全局快捷功能</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ToolOutlined, LaptopOutlined } from "@ant-design/icons-vue";
|
||||
import { ref, watch } from "vue";
|
||||
import keycodes from "./keycode";
|
||||
|
||||
const { remote, ipcRenderer } = window.require("electron");
|
||||
|
||||
const examples = [
|
||||
{
|
||||
title: "快捷键 「 Alt + W」 关键字 「 微信」",
|
||||
desc: "按下Alt + W 直接打开本地微信应用",
|
||||
},
|
||||
{
|
||||
title: "快捷键 「 Alt + Q」 关键字 「 取色」",
|
||||
desc: "按下Alt + Q 直接打开屏幕取色功能",
|
||||
},
|
||||
];
|
||||
|
||||
const currentSelect = ref(["normal"]);
|
||||
const config = ref({});
|
||||
|
||||
config.value = remote.getGlobal("OP_CONFIG").get();
|
||||
|
||||
const changeShortCut = (e, key) => {
|
||||
if (e.altKey && e.keyCode !== 18) {
|
||||
const compose = `Option+${keycodes[e.keyCode].toUpperCase()}`;
|
||||
config.value.perf.shortCut[key] = compose;
|
||||
}
|
||||
if (e.ctrlKey && e.keyCode !== 17) {
|
||||
const compose = `Ctrl+${keycodes[e.keyCode].toUpperCase()}`;
|
||||
config.value.config.perf.shortCut[key] = compose;
|
||||
}
|
||||
if (e.shiftKey && e.keyCode !== 16) {
|
||||
const compose = `Shift+${keycodes[e.keyCode].toUpperCase()}`;
|
||||
config.value.config.perf.shortCut[key] = compose;
|
||||
}
|
||||
if (e.metaKey && e.keyCode !== 93) {
|
||||
const compose = `Command+${keycodes[e.keyCode].toUpperCase()}`;
|
||||
config.value.config.perf.shortCut[key] = compose;
|
||||
}
|
||||
};
|
||||
|
||||
const changeGlobalKey = (e, index) => {
|
||||
let compose;
|
||||
if (e.altKey && e.keyCode !== 18) {
|
||||
compose = `Alt+${keycodes[e.keyCode].toUpperCase()}`;
|
||||
}
|
||||
if (e.ctrlKey && e.keyCode !== 17) {
|
||||
compose = `Ctrl+${keycodes[e.keyCode].toUpperCase()}`;
|
||||
}
|
||||
if (e.shiftKey && e.keyCode !== 16) {
|
||||
compose = `Shift+${keycodes[e.keyCode].toUpperCase()}`;
|
||||
}
|
||||
if (e.metaKey && e.keyCode !== 93) {
|
||||
compose = `Command+${keycodes[e.keyCode].toUpperCase()}`;
|
||||
}
|
||||
if (compose) {
|
||||
config.value.global[index].key = compose;
|
||||
}
|
||||
// f1 - f12
|
||||
if (e.keyCode >= 112 && e.keyCode <= 123) {
|
||||
compose = keycodes[e.keyCode].toUpperCase();
|
||||
}
|
||||
if (compose) {
|
||||
config.value.global[index].key = compose;
|
||||
}
|
||||
};
|
||||
|
||||
const addConfig = () => {
|
||||
console.log(config.value);
|
||||
config.value = {
|
||||
...config.value,
|
||||
global: [
|
||||
...config.value.global,
|
||||
{
|
||||
key: "",
|
||||
value: "",
|
||||
}
|
||||
]
|
||||
};
|
||||
};
|
||||
|
||||
watch(
|
||||
config,
|
||||
() => {
|
||||
console.log(config.value);
|
||||
// remote.getGlobal("OP_CONFIG").set("perf", config.value.perf);
|
||||
// remote.getGlobal("OP_CONFIG").set("superPanel", config.value.superPanel);
|
||||
// remote.getGlobal("OP_CONFIG").set("global", config.value.global);
|
||||
ipcRenderer.send("re-register");
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.settings {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
overflow-x: hidden;
|
||||
background: #f3efef;
|
||||
height: calc(~"100vh - 46px");
|
||||
display: flex;
|
||||
.left-menu {
|
||||
width: 200px;
|
||||
height: 100%;
|
||||
.search-container {
|
||||
padding: 10px;
|
||||
}
|
||||
.ant-input-affix-wrapper {
|
||||
border: none;
|
||||
}
|
||||
.ant-menu {
|
||||
background: #F3EFEF;
|
||||
.ant-menu-item-selected {
|
||||
background-color: #E2E2E2;
|
||||
color: #141414;
|
||||
&:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.settings-detail {
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
background: #fff;
|
||||
.setting-item {
|
||||
margin-bottom: 20px;
|
||||
.ant-form-item {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.title {
|
||||
color: #6c9fe2;
|
||||
font-size: 15px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.settings-item-li {
|
||||
padding-left: 20px;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 10px;
|
||||
.label {
|
||||
color: #646464;
|
||||
}
|
||||
.value {
|
||||
width: 300px;
|
||||
text-align: center;
|
||||
border: 1px solid #ddd;
|
||||
color: #6c9fe2;
|
||||
font-size: 14px;
|
||||
height: 24px;
|
||||
font-weight: lighter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.feature-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-top: 10px;
|
||||
font-size: 14px;
|
||||
.item {
|
||||
flex: 1;
|
||||
}
|
||||
.short-cut {
|
||||
margin-left: 20px;
|
||||
}
|
||||
.value {
|
||||
text-align: center;
|
||||
border: 1px solid #ddd;
|
||||
color: #6c9fe2;
|
||||
font-size: 14px;
|
||||
height: 24px;
|
||||
font-weight: lighter;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
.add-global {
|
||||
color: #6c9fe2;
|
||||
margin-top: 20px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
</style>
|
103
feature/src/views/settings/keycode.js
Normal file
103
feature/src/views/settings/keycode.js
Normal file
@ -0,0 +1,103 @@
|
||||
export default {
|
||||
0: "That key has no keycode",
|
||||
3: "break",
|
||||
8: "backspace / delete",
|
||||
9: "tab",
|
||||
12: "clear",
|
||||
13: "enter",
|
||||
16: "shift",
|
||||
17: "ctrl",
|
||||
18: "alt",
|
||||
19: "pause/break",
|
||||
20: "caps lock",
|
||||
21: "hangul",
|
||||
25: "hanja",
|
||||
27: "escape",
|
||||
28: "conversion",
|
||||
29: "non-conversion",
|
||||
32: "space",
|
||||
33: "page up",
|
||||
34: "page down",
|
||||
35: "End",
|
||||
36: "Home",
|
||||
37: "Left",
|
||||
38: "Up",
|
||||
39: "Right",
|
||||
40: "Down",
|
||||
45: "Insert",
|
||||
46: "Delete",
|
||||
48: "0",
|
||||
49: "1",
|
||||
50: "2",
|
||||
51: "3",
|
||||
52: "4",
|
||||
53: "5",
|
||||
54: "6",
|
||||
55: "7",
|
||||
56: "8",
|
||||
57: "9",
|
||||
65: "A",
|
||||
66: "B",
|
||||
67: "C",
|
||||
68: "D",
|
||||
69: "E",
|
||||
70: "F",
|
||||
71: "G",
|
||||
72: "H",
|
||||
73: "I",
|
||||
74: "J",
|
||||
75: "K",
|
||||
76: "L",
|
||||
77: "M",
|
||||
78: "N",
|
||||
79: "O",
|
||||
80: "P",
|
||||
81: "Q",
|
||||
82: "R",
|
||||
83: "S",
|
||||
84: "T",
|
||||
85: "U",
|
||||
86: "V",
|
||||
87: "W",
|
||||
88: "X",
|
||||
89: "Y",
|
||||
90: "Z",
|
||||
112: "F1",
|
||||
113: "F2",
|
||||
114: "F3",
|
||||
115: "F4",
|
||||
116: "F5",
|
||||
117: "F6",
|
||||
118: "F7",
|
||||
119: "F8",
|
||||
120: "F9",
|
||||
121: "F10",
|
||||
122: "F11",
|
||||
123: "F12",
|
||||
186: ";",
|
||||
187: "=",
|
||||
188: ",",
|
||||
189: "-",
|
||||
190: ".",
|
||||
191: "/",
|
||||
192: "`",
|
||||
219: "[",
|
||||
220: "\\",
|
||||
221: "]",
|
||||
222: "'",
|
||||
223: "`",
|
||||
224: "left or right ⌘ key (firefox)",
|
||||
225: "altgr",
|
||||
226: "< /git >, left back slash",
|
||||
230: "GNOME Compose Key",
|
||||
231: "ç",
|
||||
233: "XF86Forward",
|
||||
234: "XF86Back",
|
||||
235: "non-conversion",
|
||||
240: "alphanumeric",
|
||||
242: "hiragana/katakana",
|
||||
243: "half-width/full-width",
|
||||
244: "kanji",
|
||||
251: "unlock trackpad (Chrome/Edge)",
|
||||
255: "toggle touchpad"
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user