支持 template 模板 list 模式

This commit is contained in:
muwoo
2021-12-17 17:47:51 +08:00
parent afca4f2b5a
commit 8bcc5d409c
30 changed files with 13784 additions and 28 deletions

25
tpl/src/App.vue Normal file
View 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
View 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
View 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
View 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
View File

@@ -0,0 +1,8 @@
import { createStore } from "vuex";
export default createStore({
state: {},
mutations: {},
actions: {},
modules: {},
});

7
tpl/src/views/Doc.vue Normal file
View File

@@ -0,0 +1,7 @@
<template>
<div class="home">
</div>
</template>
<script lang="ts">
</script>

135
tpl/src/views/List.vue Normal file
View 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>