login page

This commit is contained in:
Rewrite0
2023-05-24 23:16:45 +08:00
parent 1a486a064e
commit 9b72b45be2
18 changed files with 197 additions and 150 deletions

View File

@@ -2,25 +2,7 @@
<template>
<Suspense>
<div layout-container>
<ab-topbar />
<main layout-main>
<ab-sidebar />
<div layout-content>
<ab-page-title :title="$route.name"></ab-page-title>
<div overflow-auto mt-12px flex-grow>
<RouterView v-slot="{ Component }">
<KeepAlive>
<component :is="Component" />
</KeepAlive>
</RouterView>
</div>
</div>
</main>
</div>
<RouterView></RouterView>
</Suspense>
</template>

View File

@@ -2,8 +2,20 @@ import axios from 'axios';
import type { Auth, Logout, Update } from '#/auth';
export const apiAuth = {
async login() {
const { data } = await axios.post<Auth>('api/v1/auth/login');
async login(username: string, password: string) {
const { data } = await axios.post<Auth>(
'api/v1/auth/login',
{
username,
password,
},
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
}
);
return data;
},
@@ -17,8 +29,11 @@ export const apiAuth = {
return data;
},
async update() {
const { data } = await axios.post<Update>('api/v1/auth/update');
async update(username: string, password: string) {
const { data } = await axios.post<Update>('api/v1/auth/update', {
username,
password,
});
return data;
},
};

View File

@@ -136,6 +136,7 @@ declare global {
const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue']
const useAsyncState: typeof import('@vueuse/core')['useAsyncState']
const useAttrs: typeof import('vue')['useAttrs']
const useAuth: typeof import('./hooks/auth')['useAuth']
const useBangumiStore: typeof import('./store/bangumi')['useBangumiStore']
const useBase64: typeof import('@vueuse/core')['useBase64']
const useBattery: typeof import('@vueuse/core')['useBattery']

View File

@@ -17,11 +17,11 @@ defineEmits(['click']);
const buttonSize = computed(() => {
switch (props.size) {
case 'big':
return 'rounded-10px text-h1 w-276px h-55px';
return 'rounded-10px text-h1 w-276px h-55px text-h1';
case 'normal':
return 'rounded-6px w-170px h-36px';
case 'small':
return 'rounded-6px w-86px h-28px';
return 'rounded-6px w-86px h-28px text-main';
}
});
</script>
@@ -50,26 +50,4 @@ const buttonSize = computed(() => {
@include bg-mouse-event(#943c61, #521e2a, #9c8a93);
}
}
.size {
&-normal {
border-radius: 6px;
width: 171px;
height: 36px;
}
&-big {
font-size: 24px;
border-radius: 10px;
width: 276px;
height: 55px;
}
&-small {
font-size: 12px;
border-radius: 6px;
width: 86px;
height: 28px;
}
}
</style>

1
src/components.d.ts vendored
View File

@@ -37,6 +37,7 @@ declare module '@vue/runtime-core' {
ConfigParser: typeof import('./views/config-parser.vue')['default']
ConfigProxy: typeof import('./views/config-proxy.vue')['default']
copy: typeof import('./basic/ab-switch copy.vue')['default']
Login: typeof import('./pages/login.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
}

41
src/hooks/auth.ts Normal file
View File

@@ -0,0 +1,41 @@
import type { User } from '#/auth';
export const useAuth = createSharedComposable(() => {
const token = useLocalStorage('token', '');
const user = reactive<User>({
username: '',
password: '',
});
const isLogin = computed(() => token.value !== '');
const login = async () => {
const res = await apiAuth.login(user.username, user.password);
console.log(res);
};
const logout = async () => {
apiAuth.logout();
};
const refresh = async () => {
const res = await apiAuth.refresh();
};
const update = async () => {
const res = await apiAuth.update(user.username, user.password);
console.log(res);
};
return {
token,
user,
isLogin,
login,
logout,
refresh,
update,
};
});

View File

@@ -1,22 +1,23 @@
<script lang="ts" setup>
const { data } = storeToRefs(useBangumiStore());
const { getAll } = useBangumiStore();
onBeforeMount(() => getAll());
definePage({
name: 'Bangumi List',
});
</script>
<script lang="ts" setup></script>
<template>
<div flex="~ wrap" space-y-12px space-x-50px>
<ab-bangumi-card
v-for="i in data"
:key="i.id"
:poster="i.poster_link"
:name="i.official_title"
:season="i.season"
></ab-bangumi-card>
<div layout-container>
<ab-topbar />
<main layout-main>
<ab-sidebar />
<div layout-content>
<ab-page-title :title="$route.name"></ab-page-title>
<div overflow-auto mt-12px flex-grow>
<RouterView v-slot="{ Component }">
<KeepAlive>
<component :is="Component" />
</KeepAlive>
</RouterView>
</div>
</div>
</main>
</div>
</template>

View File

@@ -0,0 +1,22 @@
<script lang="ts" setup>
const { data } = storeToRefs(useBangumiStore());
const { getAll } = useBangumiStore();
onBeforeMount(() => getAll());
definePage({
name: 'Bangumi List',
});
</script>
<template>
<div flex="~ wrap" space-y-12px space-x-50px>
<ab-bangumi-card
v-for="i in data"
:key="i.id"
:poster="i.poster_link"
:name="i.official_title"
:season="i.season"
></ab-bangumi-card>
</div>
</template>

39
src/pages/login.vue Normal file
View File

@@ -0,0 +1,39 @@
<script lang="ts" setup>
const { user, login } = useAuth();
definePage({
name: 'Login',
});
</script>
<template>
<div f-cer layout-container>
<ab-container title="Login" w-365px>
<div space-y-16px>
<ab-label label="Username">
<input
v-model="user.username"
type="text"
placeholder="username"
ab-input
/>
</ab-label>
<ab-label label="Password">
<input
v-model="user.password"
type="text"
placeholder="password"
ab-input
/>
</ab-label>
<div line></div>
<div flex="~ justify-end">
<ab-button size="small" @click="login">Login</ab-button>
</div>
</div>
</ab-container>
</div>
</template>

122
src/router-type.d.ts vendored
View File

@@ -39,156 +39,110 @@ import type {
declare module 'vue-router/auto/routes' {
export interface RouteNamedMap {
'Bangumi List': RouteRecordInfo<
'Bangumi List',
'/',
Record<never, never>,
Record<never, never>
>;
Calendar: RouteRecordInfo<
'Calendar',
'/calendar',
Record<never, never>,
Record<never, never>
>;
Config: RouteRecordInfo<
'Config',
'/config',
Record<never, never>,
Record<never, never>
>;
Downloader: RouteRecordInfo<
'Downloader',
'/downloader',
Record<never, never>,
Record<never, never>
>;
Log: RouteRecordInfo<
'Log',
'/log',
Record<never, never>,
Record<never, never>
>;
Player: RouteRecordInfo<
'Player',
'/player',
Record<never, never>,
Record<never, never>
>;
'/': RouteRecordInfo<'/', '/', Record<never, never>, Record<never, never>>,
'Bangumi List': RouteRecordInfo<'Bangumi List', '/bangumi', Record<never, never>, Record<never, never>>,
'Calendar': RouteRecordInfo<'Calendar', '/calendar', Record<never, never>, Record<never, never>>,
'Config': RouteRecordInfo<'Config', '/config', Record<never, never>, Record<never, never>>,
'Downloader': RouteRecordInfo<'Downloader', '/downloader', Record<never, never>, Record<never, never>>,
'Log': RouteRecordInfo<'Log', '/log', Record<never, never>, Record<never, never>>,
'Player': RouteRecordInfo<'Player', '/player', Record<never, never>, Record<never, never>>,
'Login': RouteRecordInfo<'Login', '/login', Record<never, never>, Record<never, never>>,
}
}
declare module 'vue-router/auto' {
import type { RouteNamedMap } from 'vue-router/auto/routes';
import type { RouteNamedMap } from 'vue-router/auto/routes'
export type RouterTyped = _RouterTyped<RouteNamedMap>;
export type RouterTyped = _RouterTyped<RouteNamedMap>
/**
* Type safe version of `RouteLocationNormalized` (the type of `to` and `from` in navigation guards).
* Allows passing the name of the route to be passed as a generic.
*/
export type RouteLocationNormalized<
Name extends keyof RouteNamedMap = keyof RouteNamedMap
> = RouteLocationNormalizedTypedList<RouteNamedMap>[Name];
export type RouteLocationNormalized<Name extends keyof RouteNamedMap = keyof RouteNamedMap> = RouteLocationNormalizedTypedList<RouteNamedMap>[Name]
/**
* Type safe version of `RouteLocationNormalizedLoaded` (the return type of `useRoute()`).
* Allows passing the name of the route to be passed as a generic.
*/
export type RouteLocationNormalizedLoaded<
Name extends keyof RouteNamedMap = keyof RouteNamedMap
> = RouteLocationNormalizedLoadedTypedList<RouteNamedMap>[Name];
export type RouteLocationNormalizedLoaded<Name extends keyof RouteNamedMap = keyof RouteNamedMap> = RouteLocationNormalizedLoadedTypedList<RouteNamedMap>[Name]
/**
* Type safe version of `RouteLocationResolved` (the returned route of `router.resolve()`).
* Allows passing the name of the route to be passed as a generic.
*/
export type RouteLocationResolved<
Name extends keyof RouteNamedMap = keyof RouteNamedMap
> = RouteLocationResolvedTypedList<RouteNamedMap>[Name];
export type RouteLocationResolved<Name extends keyof RouteNamedMap = keyof RouteNamedMap> = RouteLocationResolvedTypedList<RouteNamedMap>[Name]
/**
* Type safe version of `RouteLocation` . Allows passing the name of the route to be passed as a generic.
*/
export type RouteLocation<
Name extends keyof RouteNamedMap = keyof RouteNamedMap
> = RouteLocationTypedList<RouteNamedMap>[Name];
export type RouteLocation<Name extends keyof RouteNamedMap = keyof RouteNamedMap> = RouteLocationTypedList<RouteNamedMap>[Name]
/**
* Type safe version of `RouteLocationRaw` . Allows passing the name of the route to be passed as a generic.
*/
export type RouteLocationRaw<
Name extends keyof RouteNamedMap = keyof RouteNamedMap
> =
export type RouteLocationRaw<Name extends keyof RouteNamedMap = keyof RouteNamedMap> =
| RouteLocationAsString<RouteNamedMap>
| RouteLocationAsRelativeTypedList<RouteNamedMap>[Name]
| RouteLocationAsPathTypedList<RouteNamedMap>[Name];
| RouteLocationAsPathTypedList<RouteNamedMap>[Name]
/**
* Generate a type safe params for a route location. Requires the name of the route to be passed as a generic.
*/
export type RouteParams<Name extends keyof RouteNamedMap> =
RouteNamedMap[Name]['params'];
export type RouteParams<Name extends keyof RouteNamedMap> = RouteNamedMap[Name]['params']
/**
* Generate a type safe raw params for a route location. Requires the name of the route to be passed as a generic.
*/
export type RouteParamsRaw<Name extends keyof RouteNamedMap> =
RouteNamedMap[Name]['paramsRaw'];
export type RouteParamsRaw<Name extends keyof RouteNamedMap> = RouteNamedMap[Name]['paramsRaw']
export function useRouter(): RouterTyped;
export function useRoute<
Name extends keyof RouteNamedMap = keyof RouteNamedMap
>(name?: Name): RouteLocationNormalizedLoadedTypedList<RouteNamedMap>[Name];
export function useRouter(): RouterTyped
export function useRoute<Name extends keyof RouteNamedMap = keyof RouteNamedMap>(name?: Name): RouteLocationNormalizedLoadedTypedList<RouteNamedMap>[Name]
export const useLink: UseLinkFnTyped<RouteNamedMap>;
export const useLink: UseLinkFnTyped<RouteNamedMap>
export function onBeforeRouteLeave(
guard: NavigationGuard<RouteNamedMap>
): void;
export function onBeforeRouteUpdate(
guard: NavigationGuard<RouteNamedMap>
): void;
export function onBeforeRouteLeave(guard: NavigationGuard<RouteNamedMap>): void
export function onBeforeRouteUpdate(guard: NavigationGuard<RouteNamedMap>): void
export const RouterLink: RouterLinkTyped<RouteNamedMap>;
export const RouterLinkProps: RouterLinkPropsTyped<RouteNamedMap>;
export const RouterLink: RouterLinkTyped<RouteNamedMap>
export const RouterLinkProps: RouterLinkPropsTyped<RouteNamedMap>
// Experimental Data Fetching
export function defineLoader<
P extends Promise<any>,
Name extends keyof RouteNamedMap = keyof RouteNamedMap,
isLazy extends boolean = false
isLazy extends boolean = false,
>(
name: Name,
loader: (route: RouteLocationNormalizedLoaded<Name>) => P,
options?: _DefineLoaderOptions<isLazy>
): _DataLoader<Awaited<P>, isLazy>;
options?: _DefineLoaderOptions<isLazy>,
): _DataLoader<Awaited<P>, isLazy>
export function defineLoader<
P extends Promise<any>,
isLazy extends boolean = false
isLazy extends boolean = false,
>(
loader: (route: RouteLocationNormalizedLoaded) => P,
options?: _DefineLoaderOptions<isLazy>
): _DataLoader<Awaited<P>, isLazy>;
options?: _DefineLoaderOptions<isLazy>,
): _DataLoader<Awaited<P>, isLazy>
export {
_definePage as definePage,
_HasDataLoaderMeta as HasDataLoaderMeta,
_setupDataFetchingGuard as setupDataFetchingGuard,
_stopDataFetchingScope as stopDataFetchingScope,
} from 'unplugin-vue-router/runtime';
} from 'unplugin-vue-router/runtime'
}
declare module 'vue-router' {
import type { RouteNamedMap } from 'vue-router/auto/routes';
import type { RouteNamedMap } from 'vue-router/auto/routes'
export interface TypesConfig {
beforeRouteUpdate: NavigationGuard<RouteNamedMap>;
beforeRouteLeave: NavigationGuard<RouteNamedMap>;
beforeRouteUpdate: NavigationGuard<RouteNamedMap>
beforeRouteLeave: NavigationGuard<RouteNamedMap>
$route: RouteLocationNormalizedLoadedTypedList<RouteNamedMap>[keyof RouteNamedMap];
$router: _RouterTyped<RouteNamedMap>;
$route: RouteLocationNormalizedLoadedTypedList<RouteNamedMap>[keyof RouteNamedMap]
$router: _RouterTyped<RouteNamedMap>
RouterLink: RouterLinkTyped<RouteNamedMap>;
RouterLink: RouterLinkTyped<RouteNamedMap>
}
}

View File

@@ -4,4 +4,11 @@ const router = createRouter({
history: createWebHashHistory(),
});
router.beforeEach((to) => {
const { isLogin } = useAuth();
if (!isLogin.value && to.path !== '/login') {
return { name: 'Login' };
}
});
export { router };

View File

@@ -11,3 +11,8 @@ export interface Logout {
export interface Update {
message: 'update success';
}
export interface User {
username: string;
password: string;
}

View File

@@ -18,6 +18,7 @@ export default defineConfig({
primary: '#493475',
running: '#A3D491',
stopped: '#DF7F91',
page: '#F0F0F0',
},
},
rules: [
@@ -52,7 +53,7 @@ export default defineConfig({
[
'layout-container',
'wh-screen min-w-1024px min-h-768px p-16px space-y-12px flex flex-col bg-[#F0F0F0]',
'wh-screen min-w-1024px min-h-768px p-16px space-y-12px flex flex-col bg-page',
],
[
'layout-main',