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