mirror of
https://github.com/EstrellaXD/Auto_Bangumi.git
synced 2026-07-16 11:41:25 +08:00
layout
This commit is contained in:
21
src/App.vue
21
src/App.vue
@@ -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
16
src/auto-imports.d.ts
vendored
@@ -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
8
src/components.d.ts
vendored
@@ -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']
|
||||
|
||||
62
src/components/ab-status-bar.vue
Normal file
62
src/components/ab-status-bar.vue
Normal 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>
|
||||
@@ -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
44
src/style/global.scss
Normal 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
16
src/style/transition.scss
Normal 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
117
src/views/ab-sidebar.vue
Normal 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
52
src/views/ab-topbar.vue
Normal 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>
|
||||
@@ -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'],
|
||||
],
|
||||
});
|
||||
|
||||
@@ -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',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user