mirror of
https://github.com/rubickCenter/rubick
synced 2025-12-16 23:54:19 +08:00
✨ 支持 template 模板 list 模式
This commit is contained in:
23
tpl/.gitignore
vendored
Normal file
23
tpl/.gitignore
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Log files
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
24
tpl/README.md
Normal file
24
tpl/README.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# tpl
|
||||
|
||||
## Project setup
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
### Compiles and hot-reloads for development
|
||||
```
|
||||
npm run serve
|
||||
```
|
||||
|
||||
### Compiles and minifies for production
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Lints and fixes files
|
||||
```
|
||||
npm run lint
|
||||
```
|
||||
|
||||
### Customize configuration
|
||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
||||
3
tpl/babel.config.js
Normal file
3
tpl/babel.config.js
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
presets: ["@vue/cli-plugin-babel/preset"],
|
||||
};
|
||||
13227
tpl/package-lock.json
generated
Normal file
13227
tpl/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
56
tpl/package.json
Normal file
56
tpl/package.json
Normal file
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"name": "tpl",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^3.6.5",
|
||||
"vue": "^3.0.0",
|
||||
"vue-router": "^4.0.0-0",
|
||||
"vuex": "^4.0.0-0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^4.18.0",
|
||||
"@typescript-eslint/parser": "^4.18.0",
|
||||
"@vue/cli-plugin-babel": "~4.5.0",
|
||||
"@vue/cli-plugin-eslint": "~4.5.0",
|
||||
"@vue/cli-plugin-router": "~4.5.0",
|
||||
"@vue/cli-plugin-typescript": "~4.5.0",
|
||||
"@vue/cli-plugin-vuex": "~4.5.0",
|
||||
"@vue/cli-service": "~4.5.0",
|
||||
"@vue/compiler-sfc": "^3.0.0",
|
||||
"@vue/eslint-config-prettier": "^6.0.0",
|
||||
"@vue/eslint-config-typescript": "^7.0.0",
|
||||
"eslint": "^6.7.2",
|
||||
"eslint-plugin-prettier": "^3.3.1",
|
||||
"eslint-plugin-vue": "^7.0.0",
|
||||
"prettier": "^2.2.1",
|
||||
"typescript": "~4.1.5"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
"env": {
|
||||
"node": true
|
||||
},
|
||||
"extends": [
|
||||
"plugin:vue/vue3-essential",
|
||||
"eslint:recommended",
|
||||
"@vue/typescript/recommended",
|
||||
"@vue/prettier",
|
||||
"@vue/prettier/@typescript-eslint"
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2020
|
||||
},
|
||||
"rules": {}
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions",
|
||||
"not dead"
|
||||
]
|
||||
}
|
||||
BIN
tpl/public/favicon.ico
Normal file
BIN
tpl/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
17
tpl/public/index.html
Normal file
17
tpl/public/index.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
||||
25
tpl/src/App.vue
Normal file
25
tpl/src/App.vue
Normal file
@@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<router-view />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
const router = useRouter();
|
||||
window.rubick.onPluginEnter(({ code }) => {
|
||||
const current = window.exports[code];
|
||||
router.push({
|
||||
name: current.mode,
|
||||
params: {
|
||||
code,
|
||||
},
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
6
tpl/src/main.ts
Normal file
6
tpl/src/main.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { createApp } from "vue";
|
||||
import App from "./App.vue";
|
||||
import router from "./router";
|
||||
import store from "./store";
|
||||
|
||||
createApp(App).use(store).use(router).mount("#app");
|
||||
23
tpl/src/router/index.ts
Normal file
23
tpl/src/router/index.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router";
|
||||
import List from "../views/List.vue";
|
||||
import Doc from "../views/Doc.vue";
|
||||
|
||||
const routes: Array<RouteRecordRaw> = [
|
||||
{
|
||||
path: "/list",
|
||||
name: "list",
|
||||
component: List,
|
||||
},
|
||||
{
|
||||
path: "/doc",
|
||||
name: "doc",
|
||||
component: Doc,
|
||||
},
|
||||
];
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(),
|
||||
routes,
|
||||
});
|
||||
|
||||
export default router;
|
||||
10
tpl/src/shims-vue.d.ts
vendored
Normal file
10
tpl/src/shims-vue.d.ts
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
/* eslint-disable */
|
||||
declare module '*.vue' {
|
||||
import type { DefineComponent } from 'vue'
|
||||
const component: DefineComponent<{}, {}, any>
|
||||
export default component
|
||||
}
|
||||
|
||||
interface Window {
|
||||
rubick: any;
|
||||
}
|
||||
8
tpl/src/store/index.ts
Normal file
8
tpl/src/store/index.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { createStore } from "vuex";
|
||||
|
||||
export default createStore({
|
||||
state: {},
|
||||
mutations: {},
|
||||
actions: {},
|
||||
modules: {},
|
||||
});
|
||||
7
tpl/src/views/Doc.vue
Normal file
7
tpl/src/views/Doc.vue
Normal file
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<div class="home">
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
</script>
|
||||
135
tpl/src/views/List.vue
Normal file
135
tpl/src/views/List.vue
Normal file
@@ -0,0 +1,135 @@
|
||||
<template>
|
||||
<div class="list-container">
|
||||
<div class="options" v-show="!!(lists || []).length">
|
||||
<div
|
||||
:key="index"
|
||||
:class="currentSelect === index ? 'active op-item' : 'op-item'"
|
||||
v-for="(item, index) in lists"
|
||||
@click="select(item)"
|
||||
>
|
||||
<img class="icon" :src="item.icon" />
|
||||
<div class="content">
|
||||
<div class="title">{{ item.title }}</div>
|
||||
<div class="desc">{{ decodeURIComponent(item.description) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { useRoute } from "vue-router";
|
||||
import { ref, onBeforeUnmount } from "vue";
|
||||
const { ipcRenderer } = window.require("electron");
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
const itemHeight = 60;
|
||||
const itemMaxNum = 10;
|
||||
const defaultHeight = 60;
|
||||
|
||||
const code = route.params.code;
|
||||
const current = window.exports[code];
|
||||
window.rubick.setExpendHeight(defaultHeight);
|
||||
|
||||
const lists = ref([]);
|
||||
current.args.enter &&
|
||||
current.args.enter({ code: code, type: "", payload: [] }, (lists) => {
|
||||
lists.value = lists;
|
||||
});
|
||||
|
||||
const currentSelect = ref(0);
|
||||
ipcRenderer.on(`changeCurrent`, (e, result) => {
|
||||
if (
|
||||
currentSelect.value + result > lists.value.length - 1 ||
|
||||
lists.value + result < 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
currentSelect.value = currentSelect.value + result;
|
||||
});
|
||||
window.rubick.setSubInput(({ text }) => {
|
||||
current.args.search &&
|
||||
current.args.search({ code, type: "", payload: [] }, text, (result) => {
|
||||
lists.value = result || [];
|
||||
const height = lists.value.length > itemMaxNum ? itemMaxNum * itemHeight : itemHeight * lists.value.length
|
||||
window.rubick.setExpendHeight(defaultHeight + height);
|
||||
});
|
||||
}, "搜索");
|
||||
|
||||
const select = (item) => {
|
||||
current.args.select && current.args.select({code, type: '', payload: [] }, item);
|
||||
};
|
||||
|
||||
const onKeydownAction = (e) => {
|
||||
if (e.code === "Enter") {
|
||||
return select(lists.value[currentSelect.value]);
|
||||
}
|
||||
let index = 0;
|
||||
if (e.code === "ArrowDown") {
|
||||
index = 1;
|
||||
}
|
||||
if (e.code === "ArrowUp") {
|
||||
index = -1;
|
||||
}
|
||||
if (!lists.value.length) return;
|
||||
if (
|
||||
currentSelect.value + index > lists.value.length - 1 ||
|
||||
currentSelect.value + index < 0
|
||||
)
|
||||
return;
|
||||
currentSelect.value = currentSelect.value + index;
|
||||
};
|
||||
|
||||
window.addEventListener("keydown", onKeydownAction);
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener("keydown", onKeydownAction);
|
||||
});
|
||||
|
||||
</script>
|
||||
<style>
|
||||
.options {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 99;
|
||||
max-height: calc(100vh);
|
||||
overflow: auto;
|
||||
}
|
||||
.options::-webkit-scrollbar {
|
||||
width: 0;
|
||||
}
|
||||
.op-item {
|
||||
padding: 0 10px;
|
||||
height: 60px;
|
||||
max-height: 500px;
|
||||
overflow: auto;
|
||||
background: #fafafa;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
text-align: left;
|
||||
}
|
||||
.icon {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 100%;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.title {
|
||||
width: 500px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.desc {
|
||||
color: #999;
|
||||
width: 500px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.op-item.active {
|
||||
background: #dee2e8;
|
||||
}
|
||||
</style>
|
||||
39
tpl/tsconfig.json
Normal file
39
tpl/tsconfig.json
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"strict": true,
|
||||
"jsx": "preserve",
|
||||
"importHelpers": true,
|
||||
"moduleResolution": "node",
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"sourceMap": true,
|
||||
"baseUrl": ".",
|
||||
"types": [
|
||||
"webpack-env"
|
||||
],
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"src/*"
|
||||
]
|
||||
},
|
||||
"lib": [
|
||||
"esnext",
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"scripthost"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx",
|
||||
"src/**/*.vue",
|
||||
"tests/**/*.ts",
|
||||
"tests/**/*.tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
13
tpl/vue.config.js
Normal file
13
tpl/vue.config.js
Normal file
@@ -0,0 +1,13 @@
|
||||
const path = require("path");
|
||||
|
||||
module.exports = {
|
||||
css: { // 配置css模块
|
||||
loaderOptions: { // 向预处理器 Loader 传递配置选项
|
||||
less: { // 配置less(其他样式解析用法一致)
|
||||
javascriptEnabled: true // 设置为true
|
||||
}
|
||||
}
|
||||
},
|
||||
outputDir: path.join(__dirname, "../public/tpl"),
|
||||
publicPath: process.env.NODE_ENV === "production" ? "" : "/",
|
||||
};
|
||||
Reference in New Issue
Block a user