This commit is contained in:
Rewrite0
2023-05-21 17:24:59 +08:00
parent ff17d3f0cf
commit cca5dfc484
11 changed files with 359 additions and 19 deletions

View File

@@ -2,6 +2,25 @@
<template>
<Suspense>
<RouterView />
<div layout-container>
<ab-topbar />
<main layout-main>
<ab-sidebar />
<div layout-content>
<ab-page-title title="Bangumi List"></ab-page-title>
<div overflow-auto mt-12px>
<RouterView />
</div>
</div>
</main>
</div>
</Suspense>
</template>
<style lang="scss">
@import './style/transition';
@import './style/global';
</style>

16
src/auto-imports.d.ts vendored
View File

@@ -3,13 +3,14 @@ export {}
declare global {
const EffectScope: typeof import('vue')['EffectScope']
const acceptHMRUpdate: typeof import('pinia')['acceptHMRUpdate']
const addBangumi: typeof import('./api/bangumi')['addBangumi']
const afterAll: typeof import('vitest')['afterAll']
const afterEach: typeof import('vitest')['afterEach']
const appRestart: typeof import('./api/program')['appRestart']
const appStart: typeof import('./api/program')['appStart']
const appStatus: typeof import('./api/program')['appStatus']
const appStop: typeof import('./api/program')['appStop']
const apiBangumi: typeof import('./api/bangumi')['apiBangumi']
const apiCheck: typeof import('./api/check')['apiCheck']
const apiConfig: typeof import('./api/config')['apiConfig']
const apiDownload: typeof import('./api/download')['apiDownload']
const apiLog: typeof import('./api/log')['apiLog']
const apiProgram: typeof import('./api/program')['apiProgram']
const assert: typeof import('vitest')['assert']
const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
const autoResetRef: typeof import('@vueuse/core')['autoResetRef']
@@ -46,10 +47,7 @@ declare global {
const effectScope: typeof import('vue')['effectScope']
const expect: typeof import('vitest')['expect']
const extendRef: typeof import('@vueuse/core')['extendRef']
const getABData: typeof import('./api/bangumi')['getABData']
const getABLog: typeof import('./api/debug')['getABLog']
const getActivePinia: typeof import('pinia')['getActivePinia']
const getConfig: typeof import('./api/config')['getConfig']
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope']
const h: typeof import('vue')['h']
@@ -108,12 +106,10 @@ declare global {
const refDefault: typeof import('@vueuse/core')['refDefault']
const refThrottled: typeof import('@vueuse/core')['refThrottled']
const refWithControl: typeof import('@vueuse/core')['refWithControl']
const resetRule: typeof import('./api/debug')['resetRule']
const resolveComponent: typeof import('vue')['resolveComponent']
const resolveRef: typeof import('@vueuse/core')['resolveRef']
const resolveUnref: typeof import('@vueuse/core')['resolveUnref']
const setActivePinia: typeof import('pinia')['setActivePinia']
const setConfig: typeof import('./api/config')['setConfig']
const setMapStoreSuffix: typeof import('pinia')['setMapStoreSuffix']
const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly']

8
src/components.d.ts vendored
View File

@@ -10,11 +10,19 @@ export {}
declare module '@vue/runtime-core' {
export interface GlobalComponents {
AbAdd: typeof import('./basic/ab-add.vue')['default']
AbBangumiCard: typeof import('./components/ab-bangumi-card.vue')['default']
AbButton: typeof import('./basic/ab-button.vue')['default']
AbCheckbox: typeof import('./basic/ab-checkbox.vue')['default']
AbInput: typeof import('./basic/ab-input.vue')['default']
AbPageTitle: typeof import('./basic/ab-page-title.vue')['default']
AbSearch: typeof import('./basic/ab-search.vue')['default']
AbSelect: typeof import('./basic/ab-select.vue')['default']
AbSidebar: typeof import('./views/ab-sidebar.vue')['default']
AbStatus: typeof import('./basic/ab-status.vue')['default']
AbStatusBar: typeof import('./components/ab-status-bar.vue')['default']
AbSwitch: typeof import('./basic/ab-switch.vue')['default']
AbTopbar: typeof import('./views/ab-topbar.vue')['default']
BangumiCard: typeof import('./components/bangumi-card.vue')['default']
copy: typeof import('./basic/ab-switch copy.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']

View File

@@ -0,0 +1,62 @@
<script lang="ts" setup>
import { Menu, MenuButton, MenuItems, MenuItem } from '@headlessui/vue';
import { AddOne, More } from '@icon-park/vue-next';
withDefaults(
defineProps<{
running: boolean;
items: { id: number; icon: any; label: string }[];
}>(),
{
running: false,
}
);
</script>
<template>
<Menu>
<div rel>
<div fx-cer space-x-16px>
<add-one theme="outline" size="24" fill="#fff" is-btn btn-click />
<MenuButton bg-transparent is-btn btn-click>
<more theme="outline" size="24" fill="#fff" />
</MenuButton>
<ab-status :running="running" />
</div>
<MenuItems
abs
top-50px
w-120px
rounded-8px
bg-white
overflow-hidden
shadow
>
<MenuItem v-for="i in items" :key="i.id">
<div
w-full
h-32px
px-12px
fx-cer
justify-between
text-black
is-btn
transition-colors
hover:text-white
hover:bg-primary
class="group"
>
<div text-main>{{ i.label }}</div>
<div text-primary class="group-hover:text-white" transition-colors>
<component :is="i.icon" size="16"></component>
</div>
</div>
</MenuItem>
</MenuItems>
</div>
</Menu>
</template>

View File

@@ -1,19 +1,18 @@
import { appStatus } from '../api/program';
export const programStore = defineStore('program', () => {
const status = ref(false);
const running = ref(false);
const timer = ref<NodeJS.Timer | null>(null);
const getStatus = async () => {
status.value = await appStatus();
running.value = await apiProgram.status();
};
const onUpdate = () => {
getStatus();
timer.value = setInterval(() => getStatus(), 3000);
};
return {
status,
running,
getStatus,
onUpdate,
};

44
src/style/global.scss Normal file
View File

@@ -0,0 +1,44 @@
$scrollbar-color: #372a87;
:root {
--scrollbar-size: 6px;
--scrollbar-color: transparent;
--scrollbar-thumb-color: #{rgba($scrollbar-color, 0.5)};
--scrollbar-thumb-hover-color: #{rgba($scrollbar-color, 1)};
}
::-webkit-scrollbar {
width: var(--scrollbar-size);
height: var(--scrollbar-size);
}
/* 滚动槽--外层轨道 */
::-webkit-scrollbar-track {
background: var(--scrollbar-color);
}
/* 内层轨道(不包含滚动块部分) */
/* 透明度设置为全透明,使得滚动条背景色为网页颜色 */
::-webkit-scrollbar-track-piece {
opacity: 0;
}
/* 滚动条滑块 */
::-webkit-scrollbar-thumb {
border-radius: calc(var(--scrollbar-size) / 2);
background: var(--scrollbar-thumb-color);
&:hover {
background: var(--scrollbar-thumb-hover-color);
}
}
/* 滚动条按钮 */
::-webkit-scrollbar-button {
display: none;
}
/* 横向滚动条和纵向滚动条相交处尖角的颜色 */
::-webkit-scrollbar-corner {
background-color: transparent;
}

16
src/style/transition.scss Normal file
View File

@@ -0,0 +1,16 @@
// transition
.fade {
&-enter-active,
&-leave-active {
position: absolute;
transition: opacity 0.2s ease;
}
&-enter-from,
&-leave-to {
opacity: 0;
}
}
// transition-group

117
src/views/ab-sidebar.vue Normal file
View File

@@ -0,0 +1,117 @@
<script lang="ts" setup>
import {
MenuUnfold,
Home,
Calendar,
Play,
Download,
Log,
Setting,
Logout,
} from '@icon-park/vue-next';
const props = withDefaults(
defineProps<{
open?: boolean;
}>(),
{
open: false,
}
);
const show = ref(props.open);
const toggle = () => (show.value = !show.value);
const items = [
{
id: 1,
icon: Home,
label: 'HomePage',
},
{
id: 2,
icon: Calendar,
label: 'Calendar',
},
{
id: 3,
icon: Play,
label: 'Player',
},
{
id: 4,
icon: Download,
label: 'Downloader',
},
{
id: 5,
icon: Log,
label: 'Log',
},
{
id: 6,
icon: Setting,
label: 'Setting',
},
{
id: 7,
icon: Logout,
label: 'Logout',
},
];
</script>
<template>
<div
:class="[show ? 'w-240px' : 'w-72px']"
bg-theme-col
rounded-12px
text-white
overflow-hidden
transition-width
flex="~ col"
pb-12px
>
<div
@click="toggle"
w-full
h-60px
is-btn
f-cer
bg="#E7E7E7"
text="#2A1C52"
rel
>
<div :class="[!show && 'abs opacity-0']" transition-opacity>
<div text-h1>Menu</div>
</div>
<menu-unfold
theme="outline"
size="24"
fill="#2A1C52"
abs
left="24px"
:class="[show && 'rotate-y-180']"
/>
</div>
<template v-for="i in items" :key="i.id">
<div
:class="[i.label === 'Logout' && 'mt-auto']"
:title="i.label"
fx-cer
px-24px
space-x-42px
h-48px
is-btn
transition-colors
hover:bg="#F1F5FA"
hover:text="#2A1C52"
>
<component :is="i.icon" :size="24" />
<div text-h2>{{ i.label }}</div>
</div>
</template>
</div>
</template>

52
src/views/ab-topbar.vue Normal file
View File

@@ -0,0 +1,52 @@
<script lang="ts" setup>
import { PlayOne, Pause, Refresh, Power, Me } from '@icon-park/vue-next';
const search = ref('');
const { onUpdate } = programStore();
const { running } = storeToRefs(programStore());
const items = [
{
id: 1,
label: 'Start',
icon: PlayOne,
},
{
id: 2,
label: 'Pause',
icon: Pause,
},
{
id: 3,
label: 'Restart',
icon: Refresh,
},
{
id: 4,
label: 'Shutdown',
icon: Power,
},
{
id: 5,
label: 'Profile',
icon: Me,
},
];
onBeforeMount(() => onUpdate());
</script>
<template>
<div h-60px bg-theme-row text-white rounded-12px fx-cer px-24px>
<div text-h1 mr-12px>AutoBangumi</div>
<ab-search v-model:value="search" />
<div ml-auto>
<ab-status-bar :items="items" :running="running"></ab-status-bar>
</div>
</div>
</template>
<style lang="scss" scope></style>

View File

@@ -16,6 +16,8 @@ export default defineConfig({
theme: {
colors: {
primary: '#493475',
running: '#A3D491',
stopped: '#DF7F91',
},
},
rules: [
@@ -31,9 +33,33 @@ export default defineConfig({
background: 'linear-gradient(180deg, #3C239F 0%, #793572 100%)',
},
],
[
'poster-shandow',
{
filter: 'drop-shadow(2px 2px 2px rgba(0, 0, 0, 0.1))',
},
],
[
'poster-pen-active',
{
background: '#B4ABC6',
'box-shadow': '2px 2px 4px rgba(0, 0, 0, 0.25)',
},
],
],
shortcuts: [
[/^wh-(.*)$/, ([, t]) => `w-${t} h-${t}`],
[
'layout-container',
'wh-screen min-w-1024px min-h-768px p-16px space-y-12px flex flex-col',
],
[
'layout-main',
'flex space-x-20px overflow-hidden h-[calc(100vh_-_2_*_16px_-_60px_-_12px)]',
],
['layout-content', 'overflow-hidden h-full grow flex="~ col"'],
['rel', 'relative'],
['abs', 'absolute'],
['fx-cer', 'flex items-center'],
@@ -49,5 +75,7 @@ export default defineConfig({
['input-error', 'border-color-[#CA0E0E]'],
['is-btn', 'cursor-pointer select-none'],
['is-disabled', 'cursor-not-allowed select-none'],
['input-reset', 'bg-transparent min-w-0 flex-1 outline-none'],
['btn-click', 'hover:scale-110 active:scale-100'],
],
});

View File

@@ -23,7 +23,7 @@ export default defineConfig({
}),
Components({
dts: 'src/components.d.ts',
dirs: ['src/basic'],
dirs: ['src/basic', 'src/components', 'src/views'],
}),
],
css: {
@@ -43,9 +43,8 @@ export default defineConfig({
},
},
server: {
host: '0.0.0.0',
proxy: {
'^api/.*': 'http://126.0.0.1:7892',
'^/api/.*': 'http://127.0.0.1:7892',
},
},
});