mirror of https://github.com/veypi/OneAuth.git
update oaer
parent
664bf9c922
commit
7ef7e15e6e
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* user.ts
|
||||||
|
* Copyright (C) 2023 veypi <i@veypi.com>
|
||||||
|
* 2023-10-05 15:37
|
||||||
|
* Distributed under terms of the MIT license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import { Base64 } from 'js-base64'
|
||||||
|
import ajax from './axios'
|
||||||
|
import { Cfg } from './setting'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export default {
|
||||||
|
local: () => Cfg.BaseUrl() + '/user/',
|
||||||
|
register(username: string, password: string, prop?: any) {
|
||||||
|
const data = Object.assign({
|
||||||
|
username: username,
|
||||||
|
password: Base64.encode(password),
|
||||||
|
}, prop)
|
||||||
|
return ajax.post(this.local(), data)
|
||||||
|
},
|
||||||
|
login(username: string, password: string) {
|
||||||
|
return ajax.head(this.local() + username, {
|
||||||
|
typ: 'username',
|
||||||
|
password: Base64.encode(password),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
search(q: string) {
|
||||||
|
return ajax.get(this.local(), { username: q })
|
||||||
|
},
|
||||||
|
get(id: number) {
|
||||||
|
return ajax.get(this.local() + id)
|
||||||
|
},
|
||||||
|
list() {
|
||||||
|
return ajax.get(this.local())
|
||||||
|
},
|
||||||
|
update(id: number, props: any) {
|
||||||
|
return ajax.patch(this.local() + id, props)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
|||||||
|
<template>
|
||||||
|
<div class="w-full px-3">
|
||||||
|
<div class="h-16 flex justify-between items-center">
|
||||||
|
<span style="">我的应用</span>
|
||||||
|
<span @click="Cfg.goto('/')" class="cursor-pointer" style="color:#f36828">应用中心</span>
|
||||||
|
</div>
|
||||||
|
<div class="grid grid-cols-5">
|
||||||
|
<template v-for="(ap, ai) of apps" :key="ai">
|
||||||
|
<div class="mx-2" @click="Cfg.goto(ap.redirect)" v-if="ap.id !== Cfg.uuid.value">
|
||||||
|
<img class="oa_avator" v-if="ap.icon" :src="Cfg.host.value +
|
||||||
|
ap.icon" alt="Avatar" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<hr class="mt-10" style="border:none;border-top:1px solid #777;">
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { modelsApp } from '../models'
|
||||||
|
import { Cfg } from '../api'
|
||||||
|
|
||||||
|
withDefaults(defineProps<{
|
||||||
|
apps: modelsApp[]
|
||||||
|
}>(), {})
|
||||||
|
</script>
|
||||||
|
<style scoped></style>
|
@ -0,0 +1,135 @@
|
|||||||
|
<template>
|
||||||
|
<BaseFrame :class="[isDark ? 'oa_light' : 'oa_dark']" v-model="shown" :is-dark="isDark">
|
||||||
|
<template #title>
|
||||||
|
{{ self.name }}
|
||||||
|
</template>
|
||||||
|
<div class="flex justify-center items-center">
|
||||||
|
<img class="oa_avatar mx-2" :src="Cfg.host.value + usr.icon" alt="Avatar" />
|
||||||
|
</div>
|
||||||
|
<template #main>
|
||||||
|
<div style="height: 100%">
|
||||||
|
<div style="height: calc(100% - 50px)">
|
||||||
|
<div class="w-full px-3">
|
||||||
|
<div class="h-16 flex justify-between items-center">
|
||||||
|
<span style="">我的账户</span>
|
||||||
|
<span @click="shown = false" class="cursor-pointer" style="color:#f36828">账户中心</span>
|
||||||
|
</div>
|
||||||
|
<div class="grid grid-cols-4 gap-4 h-20">
|
||||||
|
<div class="flex items-center justify-center">
|
||||||
|
<img class="oa_avatar mx-2" :src="Cfg.host.value + usr.icon" alt="Avatar" />
|
||||||
|
</div>
|
||||||
|
<div class="col-span-2 text-xs grid grid-cols-1 items-center text-left" style="">
|
||||||
|
<span>昵称:    {{ usr.nickname }}</span>
|
||||||
|
<span>账户:    {{ usr.username }}</span>
|
||||||
|
<span>邮箱:    {{ usr.email }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="">123</div>
|
||||||
|
</div>
|
||||||
|
<hr class="mt-10" style="border:none;border-top:1px solid #777;">
|
||||||
|
</div>
|
||||||
|
<File :usr="usr"></File>
|
||||||
|
<Apps :apps="ofApps"></Apps>
|
||||||
|
</div>
|
||||||
|
<hr style="border:none;border-top:2px solid #777;">
|
||||||
|
<div style="height: 48px">
|
||||||
|
<div @click="evt.emit('logout')"
|
||||||
|
class="w-full h-full flex justify-center items-center cursor-pointer transition duration-500 ease-in-out transform hover:scale-125">
|
||||||
|
<OneIcon class="inline-block" style="font-size: 24px;">
|
||||||
|
logout
|
||||||
|
</OneIcon>
|
||||||
|
<div>
|
||||||
|
退出登录
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</BaseFrame>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import BaseFrame from './frame.vue'
|
||||||
|
import Apps from './components/app.vue'
|
||||||
|
import File from './components/file.vue'
|
||||||
|
import { OneIcon } from '@veypi/one-icon'
|
||||||
|
import { computed, onMounted, ref, watch } from 'vue'
|
||||||
|
import { decode } from 'js-base64'
|
||||||
|
import { api, Cfg } from './api'
|
||||||
|
import evt from './evt'
|
||||||
|
import { modelsApp, modelsUser } from './models'
|
||||||
|
|
||||||
|
let shown = ref(false)
|
||||||
|
let emits = defineEmits<{
|
||||||
|
(e: 'logout'): void
|
||||||
|
(e: 'load', u: modelsUser): void
|
||||||
|
}>()
|
||||||
|
let props = withDefaults(defineProps<{
|
||||||
|
isDark?: boolean
|
||||||
|
}>(), {
|
||||||
|
isDark: false,
|
||||||
|
})
|
||||||
|
onMounted(() => {
|
||||||
|
fetchUserData()
|
||||||
|
})
|
||||||
|
|
||||||
|
let usr = ref<modelsUser>({} as modelsUser)
|
||||||
|
let ofApps = ref<modelsApp[]>([])
|
||||||
|
let self = ref<modelsApp>({} as modelsApp)
|
||||||
|
|
||||||
|
let token = computed(() => Cfg.token.value)
|
||||||
|
watch(token, () => {
|
||||||
|
fetchUserData()
|
||||||
|
})
|
||||||
|
|
||||||
|
function fetchUserData() {
|
||||||
|
let token = Cfg.token.value?.split('.')
|
||||||
|
if (!token || token.length !== 3) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
let data = JSON.parse(decode(token[1]))
|
||||||
|
console.log(data)
|
||||||
|
if (data.id) {
|
||||||
|
api.user.get(data.id).then(e => {
|
||||||
|
console.log(e)
|
||||||
|
usr.value = e
|
||||||
|
ofApps.value = []
|
||||||
|
for (let v of e.Apps) {
|
||||||
|
if (v.Status === 'ok') {
|
||||||
|
ofApps.value.push(v.App)
|
||||||
|
}
|
||||||
|
if (v.App.id === Cfg.uuid.value) {
|
||||||
|
self.value = v.App
|
||||||
|
}
|
||||||
|
}
|
||||||
|
emits('load', e)
|
||||||
|
}).catch(e => {
|
||||||
|
console.log(e)
|
||||||
|
evt.emit('logout')
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
evt.emit('logout')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
evt.on('logout', () => {
|
||||||
|
emits('logout')
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.oa_light {
|
||||||
|
color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.oa_dark {
|
||||||
|
color: #333;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.oa_avatar {
|
||||||
|
vertical-align: middle;
|
||||||
|
width: 2.5rem;
|
||||||
|
height: 2.5rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,28 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@veypi/oaer",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "",
|
|
||||||
"main": "src/index.ts",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"mitt": "^3.0.0",
|
|
||||||
"vue": "^3.2.20"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@veypi/one-icon": "2.0.6",
|
|
||||||
"@vitejs/plugin-vue": "^1.9.3",
|
|
||||||
"autoprefixer": "^9.8.8",
|
|
||||||
"axios": "^0.24.0",
|
|
||||||
"js-base64": "^3.7.2",
|
|
||||||
"naive-ui": "^2.19.11",
|
|
||||||
"postcss": "^7.0.39",
|
|
||||||
"tailwindcss": "npm:@tailwindcss/postcss7-compat@2.1.0",
|
|
||||||
"typescript": "^4.4.3",
|
|
||||||
"vite": "^2.6.4",
|
|
||||||
"vue-tsc": "^0.3.0"
|
|
||||||
},
|
|
||||||
"author": "veypi",
|
|
||||||
"license": "MIT"
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
plugins: {
|
|
||||||
tailwindcss: {},
|
|
||||||
autoprefixer: {},
|
|
||||||
},
|
|
||||||
}
|
|
@ -0,0 +1,10 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
/// <reference types="vite/client" />
|
||||||
|
|
||||||
|
// Mocks all files ending in `.vue` showing them as plain Vue instances
|
||||||
|
declare module '*.vue' {
|
||||||
|
import type { DefineComponent } from 'vue';
|
||||||
|
const component: DefineComponent<{}, {}, any>;
|
||||||
|
export default component;
|
||||||
|
}
|
@ -1,86 +0,0 @@
|
|||||||
import axios from 'axios'
|
|
||||||
import evt from '../evt'
|
|
||||||
import {Cfg} from './setting'
|
|
||||||
|
|
||||||
|
|
||||||
function getQueryVariable(variable: string) {
|
|
||||||
let query = window.location.search.substring(1)
|
|
||||||
let vars = query.split('&')
|
|
||||||
for (let i = 0; i < vars.length; i++) {
|
|
||||||
let pair = vars[i].split('=')
|
|
||||||
if (pair[0] == variable) {
|
|
||||||
return pair[1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
|
|
||||||
function baseRequests(url: string, method: any = 'GET', query: any, data: any, success: any, fail?: Function, header?: any) {
|
|
||||||
let headers = {
|
|
||||||
auth_token: Cfg.token.value || decodeURIComponent(getQueryVariable('token') as string),
|
|
||||||
uuid: Cfg.uuid.value,
|
|
||||||
}
|
|
||||||
if (header) {
|
|
||||||
headers = Object.assign(headers, header)
|
|
||||||
}
|
|
||||||
return axios({
|
|
||||||
url: url,
|
|
||||||
params: query,
|
|
||||||
data: data,
|
|
||||||
method: method,
|
|
||||||
headers: headers,
|
|
||||||
}).then((res: any) => {
|
|
||||||
if ('auth_token' in res.headers) {
|
|
||||||
Cfg.token.value = res.headers.auth_token
|
|
||||||
}
|
|
||||||
if ('redirect_url' in res.headers) {
|
|
||||||
window.location.href = res.headers.redirect_url
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (method === 'HEAD') {
|
|
||||||
success(res.headers)
|
|
||||||
} else {
|
|
||||||
success(res.data)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((e: any) => {
|
|
||||||
if (e.response && e.response.status === 401) {
|
|
||||||
evt.emit('logout')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
console.log(e)
|
|
||||||
if (e.response && e.response.status === 500) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (typeof fail === 'function') {
|
|
||||||
fail(e.response)
|
|
||||||
} else if (e.response && e.response.status === 400) {
|
|
||||||
console.log(400)
|
|
||||||
} else {
|
|
||||||
console.log(e.request)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const ajax = {
|
|
||||||
get(url: '', data = {}, success = {}, fail?: Function, header?: any) {
|
|
||||||
return baseRequests(url, 'GET', data, {}, success, fail, header)
|
|
||||||
},
|
|
||||||
head(url: '', data = {}, success = {}, fail?: Function, header?: any) {
|
|
||||||
return baseRequests(url, 'HEAD', data, {}, success, fail, header)
|
|
||||||
},
|
|
||||||
delete(url: '', data = {}, success = {}, fail?: Function, header?: any) {
|
|
||||||
return baseRequests(url, 'DELETE', data, {}, success, fail, header)
|
|
||||||
},
|
|
||||||
post(url: '', data = {}, success = {}, fail?: Function, header?: any) {
|
|
||||||
return baseRequests(url, 'POST', {}, data, success, fail, header)
|
|
||||||
},
|
|
||||||
put(url: '', data = {}, success = {}, fail?: Function, header?: any) {
|
|
||||||
return baseRequests(url, 'PUT', {}, data, success, fail, header)
|
|
||||||
},
|
|
||||||
patch(url: '', data = {}, success = {}, fail?: Function, header?: any) {
|
|
||||||
return baseRequests(url, 'PATCH', {}, data, success, fail, header)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ajax
|
|
@ -1,65 +0,0 @@
|
|||||||
import evt from '../evt'
|
|
||||||
|
|
||||||
export type SuccessFunction<T> = (e: any) => void;
|
|
||||||
export type FailedFunction<T> = (e: any) => void;
|
|
||||||
|
|
||||||
const Code = {
|
|
||||||
42011: '无操作权限',
|
|
||||||
22031: '资源不存在 或 您无权操作该资源',
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Interface {
|
|
||||||
private readonly method: Function
|
|
||||||
private readonly api: string
|
|
||||||
private readonly data: any
|
|
||||||
private readonly header: any
|
|
||||||
|
|
||||||
constructor(method: Function, api: string, data?: any, headers?: any) {
|
|
||||||
this.method = method
|
|
||||||
this.api = api
|
|
||||||
this.data = data
|
|
||||||
this.header = headers
|
|
||||||
}
|
|
||||||
|
|
||||||
Start(success?: SuccessFunction<any>, fail?: FailedFunction<any>) {
|
|
||||||
const newFail = function (data: any) {
|
|
||||||
if (data) {
|
|
||||||
if (data.code === 40001) {
|
|
||||||
// no login
|
|
||||||
evt.emit('logout')
|
|
||||||
return
|
|
||||||
// @ts-ignore
|
|
||||||
} else if (data.code === 42011 && window.$msg) {
|
|
||||||
// @ts-ignore
|
|
||||||
window.$msg.warning('无权限')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
|
|
||||||
// @ts-ignore
|
|
||||||
if (data && data.code && Code[data.code]) {
|
|
||||||
}
|
|
||||||
if (fail) {
|
|
||||||
fail(data.err)
|
|
||||||
// @ts-ignore
|
|
||||||
} else if (window.$msg) {
|
|
||||||
// @ts-ignore
|
|
||||||
window.$msg.warning(data.err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const newSuccess = function (data: any) {
|
|
||||||
if (Number(data.status) === 1) {
|
|
||||||
if (success) {
|
|
||||||
success(data.content)
|
|
||||||
// @ts-ignore
|
|
||||||
} else if (window.$msg) {
|
|
||||||
// @ts-ignore
|
|
||||||
window.$msg.warning('ok')
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
newFail(data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.method(this.api, this.data, newSuccess, newFail, this.header)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
import {Base64} from 'js-base64'
|
|
||||||
import {Interface} from './interface'
|
|
||||||
import ajax from './ajax'
|
|
||||||
import {Cfg} from './setting'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
local: () => Cfg.BaseUrl() + 'user/',
|
|
||||||
register(username: string, password: string, prop?: any) {
|
|
||||||
const data = Object.assign({
|
|
||||||
username: username,
|
|
||||||
password: Base64.encode(password),
|
|
||||||
}, prop)
|
|
||||||
return new Interface(ajax.post, this.local(), data)
|
|
||||||
},
|
|
||||||
login(username: string, password: string) {
|
|
||||||
return new Interface(ajax.head, this.local() + username, {
|
|
||||||
UidType: 'username',
|
|
||||||
password: Base64.encode(password),
|
|
||||||
})
|
|
||||||
},
|
|
||||||
search(q: string) {
|
|
||||||
return new Interface(ajax.get, this.local(), {username: q})
|
|
||||||
},
|
|
||||||
get(id: number) {
|
|
||||||
return new Interface(ajax.get, this.local() + id)
|
|
||||||
},
|
|
||||||
list() {
|
|
||||||
return new Interface(ajax.get, this.local())
|
|
||||||
},
|
|
||||||
update(id: number, props: any) {
|
|
||||||
return new Interface(ajax.patch, this.local() + id, props)
|
|
||||||
},
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="w-full px-3">
|
|
||||||
<div class="h-16 flex justify-between items-center">
|
|
||||||
<span style="color: #777">我的应用</span>
|
|
||||||
<span @click="Cfg.host.value?goto(Cfg.host.value):redirect('/')" class="cursor-pointer"
|
|
||||||
style="color:#f36828">应用中心</span>
|
|
||||||
</div>
|
|
||||||
<div class="grid grid-cols-5">
|
|
||||||
<template v-for="(ap,ai) of apps"
|
|
||||||
:key="ai">
|
|
||||||
<div class="mx-2" @click="redirect(ap.Host)" v-if="ap.UUID !== Cfg.uuid.value">
|
|
||||||
<n-avatar v-if="ap.Icon" size="2" :src="Cfg.host.value+ ap.Icon" round></n-avatar>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
<hr class="mt-10" style="border:none;border-top:1px solid #777;">
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import {modelsApp} from '../models'
|
|
||||||
import {Cfg} from '../api'
|
|
||||||
|
|
||||||
let props = withDefaults(defineProps<{
|
|
||||||
apps: modelsApp[]
|
|
||||||
}>(), {})
|
|
||||||
|
|
||||||
function goto(url: string) {
|
|
||||||
window.open(url, '_blank')
|
|
||||||
}
|
|
||||||
|
|
||||||
function redirect(url: string) {
|
|
||||||
window.location.href = url
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style scoped>
|
|
||||||
</style>
|
|
@ -1,121 +0,0 @@
|
|||||||
<template>
|
|
||||||
<BaseFrame v-model="shown" :is-dark="isDark">
|
|
||||||
<template #title>
|
|
||||||
{{ self.Name }}
|
|
||||||
</template>
|
|
||||||
<div class="flex justify-center items-center">
|
|
||||||
<n-avatar style="--color: none" :src="Cfg.host.value + usr.Icon"
|
|
||||||
round></n-avatar>
|
|
||||||
</div>
|
|
||||||
<template #main>
|
|
||||||
<div style="height: 100%">
|
|
||||||
<div style="height: calc(100% - 50px)">
|
|
||||||
<div class="w-full px-3">
|
|
||||||
<div class="h-16 flex justify-between items-center">
|
|
||||||
<span style="color: #777">我的账户</span>
|
|
||||||
<span @click="$router.push({name: 'user_setting'});shown=false" class="cursor-pointer"
|
|
||||||
style="color:#f36828">账户中心</span>
|
|
||||||
</div>
|
|
||||||
<div class="grid grid-cols-4 gap-4 h-20">
|
|
||||||
<div class="flex items-center justify-center">
|
|
||||||
<n-avatar size="50" :src="Cfg.host.value+ usr.Icon" round></n-avatar>
|
|
||||||
</div>
|
|
||||||
<div class="col-span-2 text-xs grid grid-cols-1 items-center text-left" style="">
|
|
||||||
<span>昵称:    {{ usr.Nickname }}</span>
|
|
||||||
<span>账户:    {{ usr.Username }}</span>
|
|
||||||
<span>邮箱:    {{ usr.Email }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="">123</div>
|
|
||||||
</div>
|
|
||||||
<hr class="mt-10" style="border:none;border-top:1px solid #777;">
|
|
||||||
</div>
|
|
||||||
<File :usr="usr"></File>
|
|
||||||
<Apps :apps="ofApps"></Apps>
|
|
||||||
</div>
|
|
||||||
<hr style="border:none;border-top:2px solid #777;">
|
|
||||||
<div style="height: 48px">
|
|
||||||
<div @click="evt.emit('logout')"
|
|
||||||
class="w-full h-full flex justify-center items-center cursor-pointer transition duration-500 ease-in-out transform hover:scale-125">
|
|
||||||
<OneIcon :color="isDark?'#eee': '#333'" class="inline-block" style="font-size: 24px;">
|
|
||||||
logout
|
|
||||||
</OneIcon>
|
|
||||||
<div>
|
|
||||||
退出登录
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</BaseFrame>
|
|
||||||
</template>
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import BaseFrame from './frame.vue'
|
|
||||||
import Apps from './components/app.vue'
|
|
||||||
import File from './components/file.vue'
|
|
||||||
import {OneIcon} from '@veypi/one-icon'
|
|
||||||
import {computed, onMounted, ref, watch} from 'vue'
|
|
||||||
import {decode} from 'js-base64'
|
|
||||||
import {api, Cfg} from './api'
|
|
||||||
import evt from './evt'
|
|
||||||
import {modelsApp, modelsUser} from './models'
|
|
||||||
|
|
||||||
let shown = ref(false)
|
|
||||||
let emits = defineEmits<{
|
|
||||||
(e: 'logout'): void
|
|
||||||
(e: 'load', u: modelsUser): void
|
|
||||||
}>()
|
|
||||||
let props = withDefaults(defineProps<{
|
|
||||||
isDark?: boolean
|
|
||||||
}>(), {
|
|
||||||
isDark: false,
|
|
||||||
})
|
|
||||||
onMounted(() => {
|
|
||||||
fetchUserData()
|
|
||||||
})
|
|
||||||
|
|
||||||
let usr = ref<modelsUser>({} as modelsUser)
|
|
||||||
let ofApps = ref<modelsApp[]>([])
|
|
||||||
let self = ref<modelsApp>({} as modelsApp)
|
|
||||||
|
|
||||||
let token = computed(() => Cfg.token.value)
|
|
||||||
watch(token, () => {
|
|
||||||
fetchUserData()
|
|
||||||
})
|
|
||||||
|
|
||||||
function fetchUserData() {
|
|
||||||
let token = Cfg.token.value?.split('.')
|
|
||||||
if (!token || token.length !== 3) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
let data = JSON.parse(decode(token[1]))
|
|
||||||
if (data.ID > 0) {
|
|
||||||
api.user.get(data.ID).Start(e => {
|
|
||||||
usr.value = e
|
|
||||||
ofApps.value = []
|
|
||||||
for (let v of e.Apps) {
|
|
||||||
if (v.Status === 'ok') {
|
|
||||||
ofApps.value.push(v.App)
|
|
||||||
}
|
|
||||||
if (v.App.UUID === Cfg.uuid.value) {
|
|
||||||
self.value = v.App
|
|
||||||
}
|
|
||||||
}
|
|
||||||
emits('load', e)
|
|
||||||
}, e => {
|
|
||||||
console.log(e)
|
|
||||||
evt.emit('logout')
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
evt.emit('logout')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
evt.on('logout', () => {
|
|
||||||
emits('logout')
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
@ -1,72 +0,0 @@
|
|||||||
import {darkTheme} from 'naive-ui/lib/themes'
|
|
||||||
import {BuiltInGlobalTheme} from 'naive-ui/lib/themes/interface'
|
|
||||||
import {lightTheme} from 'naive-ui/lib/themes/light'
|
|
||||||
import {ref} from 'vue'
|
|
||||||
import {useOsTheme, GlobalThemeOverrides} from 'naive-ui'
|
|
||||||
|
|
||||||
interface builtIn extends BuiltInGlobalTheme {
|
|
||||||
overrides: GlobalThemeOverrides
|
|
||||||
me: {
|
|
||||||
lightBox: string,
|
|
||||||
lightBoxShadow: string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let light = lightTheme as builtIn
|
|
||||||
let dark = darkTheme as builtIn
|
|
||||||
let intputNone = {
|
|
||||||
color: 'url(0) no-repeat',
|
|
||||||
colorFocus: 'url(0) no-repeat',
|
|
||||||
colorFocusWarning: 'url(0) no-repeat',
|
|
||||||
colorFocusError: 'url(0) no-repeat',
|
|
||||||
}
|
|
||||||
light.overrides = {
|
|
||||||
Input: Object.assign({}, intputNone),
|
|
||||||
}
|
|
||||||
dark.overrides = {
|
|
||||||
Input: Object.assign({
|
|
||||||
border: '1px solid #aaa',
|
|
||||||
}, intputNone),
|
|
||||||
}
|
|
||||||
light.common.cardColor = '#f4f4f4'
|
|
||||||
light.common.bodyColor = '#eee'
|
|
||||||
dark.common.bodyColor = '#2e2e2e'
|
|
||||||
light.me = {
|
|
||||||
lightBox: '#f4f4f4',
|
|
||||||
lightBoxShadow: '18px 18px 36px #c6c6c6, -18px -18px 36px #fff',
|
|
||||||
}
|
|
||||||
|
|
||||||
dark.me = {
|
|
||||||
lightBox: '#2e2e2e',
|
|
||||||
lightBoxShadow: '21px 21px 42px #272727, -21px -21px 42px #353535',
|
|
||||||
}
|
|
||||||
export const OsThemeRef = useOsTheme()
|
|
||||||
|
|
||||||
let theme = 'light'
|
|
||||||
|
|
||||||
export let Theme = ref(light)
|
|
||||||
|
|
||||||
export let IsDark = ref(false)
|
|
||||||
|
|
||||||
function change(t: string) {
|
|
||||||
if (t === 'dark') {
|
|
||||||
theme = 'dark'
|
|
||||||
Theme.value = dark
|
|
||||||
} else {
|
|
||||||
theme = 'light'
|
|
||||||
Theme.value = light
|
|
||||||
}
|
|
||||||
IsDark.value = theme === 'dark'
|
|
||||||
}
|
|
||||||
|
|
||||||
export function ChangeTheme() {
|
|
||||||
if (IsDark.value) {
|
|
||||||
change('light')
|
|
||||||
} else {
|
|
||||||
change('dark')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (OsThemeRef.value === 'dark') {
|
|
||||||
change('dark')
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
purge: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
|
|
||||||
darkMode: false, // or 'media' or 'class'
|
|
||||||
theme: {
|
|
||||||
extend: {},
|
|
||||||
},
|
|
||||||
variants: {
|
|
||||||
extend: {},
|
|
||||||
},
|
|
||||||
plugins: [],
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "esnext",
|
|
||||||
"useDefineForClassFields": true,
|
|
||||||
"module": "esnext",
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"strict": true,
|
|
||||||
"jsx": "preserve",
|
|
||||||
"sourceMap": true,
|
|
||||||
"resolveJsonModule": true,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"lib": ["esnext", "dom"]
|
|
||||||
},
|
|
||||||
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
import { defineConfig } from 'vite'
|
|
||||||
import vue from '@vitejs/plugin-vue'
|
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
|
||||||
export default defineConfig({
|
|
||||||
plugins: [vue()]
|
|
||||||
})
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue