添加仪表盘
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
|
loading.value = false
|
||||||
if (isRegisterFailed.value == false) {
|
if (!isRegisterFailed.value) {
|
||||||
registerIcon.value = "mdi-check"
|
registerIcon.value = "mdi-check"
|
||||||
disableRegister.value = true
|
disableRegister.value = true
|
||||||
setTimeout(() => {
|
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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-responsive class="rounded mx-auto" max-width="1600px">
|
<v-responsive class="rounded mx-auto" max-width="1600">
|
||||||
<v-app>
|
<v-app>
|
||||||
<v-app-bar>
|
<v-app-bar>
|
||||||
<v-container class="mx-auto d-flex align-center justify-start">
|
<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-btn icon="mdi-account" class="ml-2" id="avatar"></v-btn>
|
||||||
</v-badge>
|
</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>
|
||||||
<v-list-item value="1" @click="showLoginDialog = true" v-if="!userinfoStore.isLogin"
|
<v-list-item :active="false" to="/dashboard/url-management" v-if="userinfoStore.isLogin"
|
||||||
append-icon="mdi-login">
|
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-title>{{ t('$vuetify.user.login') }}</v-list-item-title>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
<v-list-item value="2" :active="false" @click="logout" v-if="userinfoStore.isLogin"
|
<v-list-item :active="false" @click="logout" v-if="userinfoStore.isLogin"
|
||||||
append-icon="mdi-logout">
|
prepend-icon="mdi-logout" append-icon="mdi-chevron-right">
|
||||||
<v-list-item-title>{{ t('$vuetify.user.logout') }}</v-list-item-title>
|
<v-list-item-title>{{ t('$vuetify.user.logout') }}</v-list-item-title>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
<v-list-item value="3" :active="false" @click="showRegisterDialog = true" v-if="!userinfoStore.isLogin"
|
<v-list-item :active="false" @click="showRegisterDialog = true" v-if="!userinfoStore.isLogin"
|
||||||
append-icon="mdi-account-plus">
|
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-title>{{ t('$vuetify.user.register') }}</v-list-item-title>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
</v-list>
|
</v-list>
|
||||||
|
@ -1,45 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<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>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import LoginDialog from "../items/LoginDialog.vue";
|
import DashboardView from "./DashboardView.vue";
|
||||||
import {ref} from "vue";
|
|
||||||
|
|
||||||
const showDialog = ref(true)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<LoginDialog v-model="showDialog"></LoginDialog>
|
<DashboardView></DashboardView>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -1,10 +1,24 @@
|
|||||||
import {createRouter, createWebHistory} from "vue-router";
|
import {createRouter, createWebHistory} from "vue-router";
|
||||||
|
// @ts-ignore
|
||||||
import Login from "./components/views/LoginView.vue";
|
import Login from "./components/views/LoginView.vue";
|
||||||
|
// @ts-ignore
|
||||||
import InputBox from "./components/items/InputBox.vue";
|
import InputBox from "./components/items/InputBox.vue";
|
||||||
|
// @ts-ignore
|
||||||
import IntroView from "./components/views/IntroView.vue";
|
import IntroView from "./components/views/IntroView.vue";
|
||||||
|
// @ts-ignore
|
||||||
import TestView from "./components/views/TestView.vue";
|
import TestView from "./components/views/TestView.vue";
|
||||||
|
// @ts-ignore
|
||||||
import ServiceView from "./components/views/ServiceView.vue";
|
import ServiceView from "./components/views/ServiceView.vue";
|
||||||
|
// @ts-ignore
|
||||||
import NotFound from "./components/items/NotFound.vue";
|
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 = [
|
const routes = [
|
||||||
{
|
{
|
||||||
@ -22,6 +36,19 @@ const routes = [
|
|||||||
}, {
|
}, {
|
||||||
path: '/services',
|
path: '/services',
|
||||||
component: ServiceView
|
component: ServiceView
|
||||||
|
}, {
|
||||||
|
path: '/dashboard',
|
||||||
|
component: DashboardView,
|
||||||
|
children: [{
|
||||||
|
path: 'profile',
|
||||||
|
component: Profile
|
||||||
|
}, {
|
||||||
|
path: 'security',
|
||||||
|
component: Security
|
||||||
|
}, {
|
||||||
|
path: 'url-management',
|
||||||
|
component: UrlManagement
|
||||||
|
}]
|
||||||
}, {
|
}, {
|
||||||
path: '/404',
|
path: '/404',
|
||||||
component: NotFound
|
component: NotFound
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import {useSiteConfigStore} from "../stores/siteconfig-store.ts";
|
import {useSiteConfigStore} from "../stores/siteconfig-store.ts";
|
||||||
import {useUserinfoStore} from "../stores/userinfo-store.ts";
|
import {useUserinfoStore} from "../stores/userinfo-store.ts";
|
||||||
|
|
||||||
interface LoginInfo {
|
export interface LoginInfo {
|
||||||
code: number,
|
code: number,
|
||||||
msg?: string,
|
msg?: string,
|
||||||
value?: {
|
value?: {
|
||||||
@ -10,13 +10,15 @@ interface LoginInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Msg {
|
export interface Msg<T> {
|
||||||
code: number,
|
code: number,
|
||||||
msg?: string,
|
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 useSiteConfig = useSiteConfigStore()
|
||||||
const siteConfig = useSiteConfig.siteConfig
|
const siteConfig = useSiteConfig.siteConfig
|
||||||
const protocol = siteConfig.protocol
|
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 userinfoStore = useUserinfoStore()
|
||||||
const responsePromise = request('login', {
|
const responsePromise = request('login', {
|
||||||
method: 'POST',
|
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', {
|
const responsePromise = request('reg', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({username, password}),
|
body: JSON.stringify({username, password}),
|
||||||
@ -65,20 +67,20 @@ async function register(username: string, password: string): Promise<boolean> {
|
|||||||
})
|
})
|
||||||
try {
|
try {
|
||||||
const response = await responsePromise
|
const response = await responsePromise
|
||||||
const body: Msg = await response.json()
|
const body: Msg<any> = await response.json()
|
||||||
return body.code == 0
|
return body.code == 0
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function logout() {
|
export function logout() {
|
||||||
const userinfoStore = useUserinfoStore()
|
const userinfoStore = useUserinfoStore()
|
||||||
userinfoStore.setToken('')
|
userinfoStore.setToken('')
|
||||||
window.location.reload()
|
window.location.href = '/'
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkLogin(): Promise<boolean> {
|
export async function checkLogin(): Promise<boolean> {
|
||||||
const userinfoStore = useUserinfoStore()
|
const userinfoStore = useUserinfoStore()
|
||||||
if (userinfoStore.isLogin) {
|
if (userinfoStore.isLogin) {
|
||||||
try {
|
try {
|
||||||
@ -87,7 +89,7 @@ async function checkLogin(): Promise<boolean> {
|
|||||||
'Authorization': `Bearer ${userinfoStore.token}`
|
'Authorization': `Bearer ${userinfoStore.token}`
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const body: Msg = await response.json()
|
const body: Msg<any> = await response.json()
|
||||||
return body.code == 0
|
return body.code == 0
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
return false
|
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",
|
register: "REGISTER",
|
||||||
cancel: "CANCEL"
|
cancel: "CANCEL"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
dashboard: {
|
||||||
|
menu: {
|
||||||
|
'url-management': 'URL Management',
|
||||||
|
profile: 'Profile',
|
||||||
|
security: 'Security'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export default en
|
export default en
|
@ -40,6 +40,13 @@ export default interface LocaleInterface {
|
|||||||
register: string,
|
register: string,
|
||||||
cancel: string
|
cancel: string
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
dashboard: {
|
||||||
|
menu: {
|
||||||
|
'url-management': string,
|
||||||
|
profile: string,
|
||||||
|
security: string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// ==================
|
// ==================
|
||||||
// vuetify
|
// vuetify
|
||||||
|
@ -43,6 +43,13 @@ const zhHans: LocaleInterface = {
|
|||||||
register: "注册",
|
register: "注册",
|
||||||
cancel: "取消"
|
cancel: "取消"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
dashboard: {
|
||||||
|
menu: {
|
||||||
|
'url-management': '链接管理',
|
||||||
|
profile: '用户信息',
|
||||||
|
security: '安全性'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export default zhHans
|
export default zhHans
|
@ -5,7 +5,12 @@
|
|||||||
"target": "ES2020",
|
"target": "ES2020",
|
||||||
"useDefineForClassFields": true,
|
"useDefineForClassFields": true,
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
"lib": [
|
||||||
|
"ES2020",
|
||||||
|
"DOM",
|
||||||
|
"DOM.Iterable",
|
||||||
|
"dom"
|
||||||
|
],
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
|
|
||||||
/* Bundler mode */
|
/* Bundler mode */
|
||||||
|
Loading…
Reference in New Issue
Block a user