添加仪表盘
This commit is contained in:
parent
92abcad0db
commit
34b406492a
11
src/components/items/Profile.vue
Normal file
11
src/components/items/Profile.vue
Normal file
@ -0,0 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
profile
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -37,7 +37,7 @@ async function tryRegister() {
|
||||
}
|
||||
}
|
||||
loading.value = false
|
||||
if (isRegisterFailed.value == false) {
|
||||
if (!isRegisterFailed.value) {
|
||||
registerIcon.value = "mdi-check"
|
||||
disableRegister.value = true
|
||||
setTimeout(() => {
|
||||
|
11
src/components/items/Security.vue
Normal file
11
src/components/items/Security.vue
Normal file
@ -0,0 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
security
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
13
src/components/items/UrlManagement.vue
Normal file
13
src/components/items/UrlManagement.vue
Normal file
@ -0,0 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import {getUrlsOfCurrentUser, Surl} from "../../script/functions.ts";
|
||||
|
||||
const surls = (await getUrlsOfCurrentUser()).value ?? <Surl[]>[]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-data-table :items="surls"></v-data-table>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
33
src/components/views/DashboardView.vue
Normal file
33
src/components/views/DashboardView.vue
Normal file
@ -0,0 +1,33 @@
|
||||
<script setup lang="ts">
|
||||
import {useLocale} from "vuetify";
|
||||
|
||||
const {t} = useLocale()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-row class="py-5">
|
||||
<v-col cols="auto">
|
||||
<v-sheet elevation="1" class="rounded-lg">
|
||||
<v-list class="rounded-lg">
|
||||
<v-list-item to="/dashboard/url-management" prepend-icon="mdi-link" append-icon="mdi-chevron-right">
|
||||
<v-list-item-title>{{t('$vuetify.dashboard.menu.url-management')}}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item to="/dashboard/profile" prepend-icon="mdi-account" append-icon="mdi-chevron-right">
|
||||
<v-list-item-title>{{t('$vuetify.dashboard.menu.profile')}}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item to="/dashboard/security" prepend-icon="mdi-security" append-icon="mdi-chevron-right">
|
||||
<v-list-item-title>{{t('$vuetify.dashboard.menu.security')}}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-sheet>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-sheet class="border-thin rounded-lg pa-10 overflow-auto">
|
||||
<router-view />
|
||||
</v-sheet>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
@ -35,7 +35,7 @@ function toggleTheme() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-responsive class="rounded mx-auto" max-width="1600px">
|
||||
<v-responsive class="rounded mx-auto" max-width="1600">
|
||||
<v-app>
|
||||
<v-app-bar>
|
||||
<v-container class="mx-auto d-flex align-center justify-start">
|
||||
@ -55,18 +55,22 @@ function toggleTheme() {
|
||||
<v-btn icon="mdi-account" class="ml-2" id="avatar"></v-btn>
|
||||
</v-badge>
|
||||
|
||||
<v-menu open-on-hover activator="#avatar" open-delay="0" close-delay="500" location="bottom" width="150">
|
||||
<v-menu open-on-hover activator="#avatar" open-delay="0" close-delay="500" location="bottom" width="auto">
|
||||
<v-list>
|
||||
<v-list-item value="1" @click="showLoginDialog = true" v-if="!userinfoStore.isLogin"
|
||||
append-icon="mdi-login">
|
||||
<v-list-item :active="false" to="/dashboard/url-management" v-if="userinfoStore.isLogin"
|
||||
prepend-icon="mdi-gauge" append-icon="mdi-chevron-right">
|
||||
<v-list-item-title>Dashboard</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item @click="showLoginDialog = true" v-if="!userinfoStore.isLogin"
|
||||
prepend-icon="mdi-login" append-icon="mdi-chevron-right">
|
||||
<v-list-item-title>{{ t('$vuetify.user.login') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item value="2" :active="false" @click="logout" v-if="userinfoStore.isLogin"
|
||||
append-icon="mdi-logout">
|
||||
<v-list-item :active="false" @click="logout" v-if="userinfoStore.isLogin"
|
||||
prepend-icon="mdi-logout" append-icon="mdi-chevron-right">
|
||||
<v-list-item-title>{{ t('$vuetify.user.logout') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item value="3" :active="false" @click="showRegisterDialog = true" v-if="!userinfoStore.isLogin"
|
||||
append-icon="mdi-account-plus">
|
||||
<v-list-item :active="false" @click="showRegisterDialog = true" v-if="!userinfoStore.isLogin"
|
||||
prepend-icon="mdi-account-plus" append-icon="mdi-chevron-right">
|
||||
<v-list-item-title>{{ t('$vuetify.user.register') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
|
@ -1,45 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import {request} from "../../script/functions.ts";
|
||||
import {ref, watch} from "vue";
|
||||
|
||||
interface Urls {
|
||||
key: string,
|
||||
value: string
|
||||
}
|
||||
|
||||
interface Surls {
|
||||
code: number,
|
||||
msg?: string,
|
||||
value?: Urls[]
|
||||
}
|
||||
|
||||
const urls = ref<Urls[]>([])
|
||||
const selected = ref([])
|
||||
const tableHeaderConfig = ref([
|
||||
{title: 'KEY1', value: 'key', key: 'key'},
|
||||
{title: 'URL', value: 'value', key: 'value'}
|
||||
])
|
||||
|
||||
watch(selected, () => console.log(selected.value))
|
||||
|
||||
async function getSurl() {
|
||||
const requestPromise = request('api/surl/get')
|
||||
try {
|
||||
const request = await requestPromise
|
||||
const body: Surls = await request.json()
|
||||
urls.value = body.value ?? []
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-btn @click="getSurl">get</v-btn>
|
||||
<v-data-table :items="urls" :item-value="item => item" show-select v-model="selected"
|
||||
v-slot:header.data-table-select fixed-header density="compact"
|
||||
:headers="tableHeaderConfig" :header-props="{color: 'purple'}">
|
||||
</v-data-table>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
@ -1,12 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import LoginDialog from "../items/LoginDialog.vue";
|
||||
import {ref} from "vue";
|
||||
|
||||
const showDialog = ref(true)
|
||||
import DashboardView from "./DashboardView.vue";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<LoginDialog v-model="showDialog"></LoginDialog>
|
||||
<DashboardView></DashboardView>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
@ -1,10 +1,24 @@
|
||||
import {createRouter, createWebHistory} from "vue-router";
|
||||
// @ts-ignore
|
||||
import Login from "./components/views/LoginView.vue";
|
||||
// @ts-ignore
|
||||
import InputBox from "./components/items/InputBox.vue";
|
||||
// @ts-ignore
|
||||
import IntroView from "./components/views/IntroView.vue";
|
||||
// @ts-ignore
|
||||
import TestView from "./components/views/TestView.vue";
|
||||
// @ts-ignore
|
||||
import ServiceView from "./components/views/ServiceView.vue";
|
||||
// @ts-ignore
|
||||
import NotFound from "./components/items/NotFound.vue";
|
||||
// @ts-ignore
|
||||
import DashboardView from "./components/views/DashboardView.vue";
|
||||
// @ts-ignore
|
||||
import Profile from "./components/items/Profile.vue";
|
||||
// @ts-ignore
|
||||
import Security from "./components/items/Security.vue";
|
||||
// @ts-ignore
|
||||
import UrlManagement from "./components/items/UrlManagement.vue";
|
||||
|
||||
const routes = [
|
||||
{
|
||||
@ -22,6 +36,19 @@ const routes = [
|
||||
}, {
|
||||
path: '/services',
|
||||
component: ServiceView
|
||||
}, {
|
||||
path: '/dashboard',
|
||||
component: DashboardView,
|
||||
children: [{
|
||||
path: 'profile',
|
||||
component: Profile
|
||||
}, {
|
||||
path: 'security',
|
||||
component: Security
|
||||
}, {
|
||||
path: 'url-management',
|
||||
component: UrlManagement
|
||||
}]
|
||||
}, {
|
||||
path: '/404',
|
||||
component: NotFound
|
||||
|
@ -1,7 +1,7 @@
|
||||
import {useSiteConfigStore} from "../stores/siteconfig-store.ts";
|
||||
import {useUserinfoStore} from "../stores/userinfo-store.ts";
|
||||
|
||||
interface LoginInfo {
|
||||
export interface LoginInfo {
|
||||
code: number,
|
||||
msg?: string,
|
||||
value?: {
|
||||
@ -10,13 +10,15 @@ interface LoginInfo {
|
||||
}
|
||||
}
|
||||
|
||||
interface Msg {
|
||||
export interface Msg<T> {
|
||||
code: number,
|
||||
msg?: string,
|
||||
value?: any
|
||||
value?: T
|
||||
}
|
||||
|
||||
async function request(path: string, init: RequestInit = {}): Promise<Response> {
|
||||
export interface Surl {}
|
||||
|
||||
export async function request(path: string, init: RequestInit = {}): Promise<Response> {
|
||||
const useSiteConfig = useSiteConfigStore()
|
||||
const siteConfig = useSiteConfig.siteConfig
|
||||
const protocol = siteConfig.protocol
|
||||
@ -30,7 +32,7 @@ async function request(path: string, init: RequestInit = {}): Promise<Response>
|
||||
})
|
||||
}
|
||||
|
||||
async function login(username: string, password: string): Promise<boolean> {
|
||||
export async function login(username: string, password: string): Promise<boolean> {
|
||||
const userinfoStore = useUserinfoStore()
|
||||
const responsePromise = request('login', {
|
||||
method: 'POST',
|
||||
@ -54,7 +56,7 @@ async function login(username: string, password: string): Promise<boolean> {
|
||||
}
|
||||
}
|
||||
|
||||
async function register(username: string, password: string): Promise<boolean> {
|
||||
export async function register(username: string, password: string): Promise<boolean> {
|
||||
const responsePromise = request('reg', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({username, password}),
|
||||
@ -65,20 +67,20 @@ async function register(username: string, password: string): Promise<boolean> {
|
||||
})
|
||||
try {
|
||||
const response = await responsePromise
|
||||
const body: Msg = await response.json()
|
||||
const body: Msg<any> = await response.json()
|
||||
return body.code == 0
|
||||
} catch (_) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
function logout() {
|
||||
export function logout() {
|
||||
const userinfoStore = useUserinfoStore()
|
||||
userinfoStore.setToken('')
|
||||
window.location.reload()
|
||||
window.location.href = '/'
|
||||
}
|
||||
|
||||
async function checkLogin(): Promise<boolean> {
|
||||
export async function checkLogin(): Promise<boolean> {
|
||||
const userinfoStore = useUserinfoStore()
|
||||
if (userinfoStore.isLogin) {
|
||||
try {
|
||||
@ -87,7 +89,7 @@ async function checkLogin(): Promise<boolean> {
|
||||
'Authorization': `Bearer ${userinfoStore.token}`
|
||||
}
|
||||
})
|
||||
const body: Msg = await response.json()
|
||||
const body: Msg<any> = await response.json()
|
||||
return body.code == 0
|
||||
} catch (_) {
|
||||
return false
|
||||
@ -97,4 +99,8 @@ async function checkLogin(): Promise<boolean> {
|
||||
}
|
||||
}
|
||||
|
||||
export {request, login, logout, checkLogin, register}
|
||||
export async function getUrlsOfCurrentUser() {
|
||||
const response = await request('api/surl/get')
|
||||
const body: Msg<Surl[]> = await response.json()
|
||||
return body
|
||||
}
|
@ -43,6 +43,13 @@ const en: LocaleInterface = {
|
||||
register: "REGISTER",
|
||||
cancel: "CANCEL"
|
||||
}
|
||||
},
|
||||
dashboard: {
|
||||
menu: {
|
||||
'url-management': 'URL Management',
|
||||
profile: 'Profile',
|
||||
security: 'Security'
|
||||
}
|
||||
}
|
||||
}
|
||||
export default en
|
@ -40,6 +40,13 @@ export default interface LocaleInterface {
|
||||
register: string,
|
||||
cancel: string
|
||||
}
|
||||
},
|
||||
dashboard: {
|
||||
menu: {
|
||||
'url-management': string,
|
||||
profile: string,
|
||||
security: string
|
||||
}
|
||||
}
|
||||
// ==================
|
||||
// vuetify
|
||||
|
@ -43,6 +43,13 @@ const zhHans: LocaleInterface = {
|
||||
register: "注册",
|
||||
cancel: "取消"
|
||||
}
|
||||
},
|
||||
dashboard: {
|
||||
menu: {
|
||||
'url-management': '链接管理',
|
||||
profile: '用户信息',
|
||||
security: '安全性'
|
||||
}
|
||||
}
|
||||
}
|
||||
export default zhHans
|
@ -5,7 +5,12 @@
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"lib": [
|
||||
"ES2020",
|
||||
"DOM",
|
||||
"DOM.Iterable",
|
||||
"dom"
|
||||
],
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
|
Loading…
Reference in New Issue
Block a user