add setting.
This commit is contained in:
6
package-lock.json
generated
6
package-lock.json
generated
@@ -20,6 +20,7 @@
|
|||||||
"party-js": "^2.2.0",
|
"party-js": "^2.2.0",
|
||||||
"pinia": "^2.0.30",
|
"pinia": "^2.0.30",
|
||||||
"vue": "^3.2.47",
|
"vue": "^3.2.47",
|
||||||
|
"vue-avatar-upload": "^1.1.0",
|
||||||
"vue-chartjs": "^5.2.0",
|
"vue-chartjs": "^5.2.0",
|
||||||
"vue-router": "^4.1.6"
|
"vue-router": "^4.1.6"
|
||||||
},
|
},
|
||||||
@@ -3697,6 +3698,11 @@
|
|||||||
"@vue/shared": "3.2.47"
|
"@vue/shared": "3.2.47"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/vue-avatar-upload": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/vue-avatar-upload/-/vue-avatar-upload-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-mEWpBKm9AxjW6iyrigb/i9UKUYk3iBfSWSJwwNG6QmbxQMF3aXDwUVPFv7i2VK0P6oZyfIybjIt2jVBgoN0WlA=="
|
||||||
|
},
|
||||||
"node_modules/vue-chartjs": {
|
"node_modules/vue-chartjs": {
|
||||||
"version": "5.2.0",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmmirror.com/vue-chartjs/-/vue-chartjs-5.2.0.tgz",
|
"resolved": "https://registry.npmmirror.com/vue-chartjs/-/vue-chartjs-5.2.0.tgz",
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
"party-js": "^2.2.0",
|
"party-js": "^2.2.0",
|
||||||
"pinia": "^2.0.30",
|
"pinia": "^2.0.30",
|
||||||
"vue": "^3.2.47",
|
"vue": "^3.2.47",
|
||||||
|
"vue-avatar-upload": "^1.1.0",
|
||||||
"vue-chartjs": "^5.2.0",
|
"vue-chartjs": "^5.2.0",
|
||||||
"vue-router": "^4.1.6"
|
"vue-router": "^4.1.6"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const [loading, toggle] = useToggle()
|
|||||||
async function init() {
|
async function init() {
|
||||||
toggle(true)
|
toggle(true)
|
||||||
try {
|
try {
|
||||||
const res = await getProfile(route.query.name as string)
|
const res = await getProfile(<string>route.query.name)
|
||||||
profile.value = res.data
|
profile.value = res.data
|
||||||
const acm = res.data.acm_problems_status.problems || {}
|
const acm = res.data.acm_problems_status.problems || {}
|
||||||
const oi = res.data.oi_problems_status.problems || {}
|
const oi = res.data.oi_problems_status.problems || {}
|
||||||
@@ -76,6 +76,7 @@ onMounted(init)
|
|||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.desc {
|
.desc {
|
||||||
|
|||||||
@@ -1,3 +1,69 @@
|
|||||||
<script setup lang="ts"></script>
|
<script setup lang="ts">
|
||||||
<template></template>
|
import VueAvatarUpload from "vue-avatar-upload"
|
||||||
<style scoped></style>
|
import "vue-avatar-upload/lib/style.css"
|
||||||
|
import { isDesktop } from "~/shared/composables/breakpoints"
|
||||||
|
import { useUserStore } from "~/shared/store/user"
|
||||||
|
|
||||||
|
const [showAvatarModal] = useToggle()
|
||||||
|
const userStore = useUserStore()
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<n-grid v-if="userStore.profile" :x-gap="20" :cols="isDesktop ? 3 : 1">
|
||||||
|
<n-gi>
|
||||||
|
<h3>个人信息设置</h3>
|
||||||
|
<n-form>
|
||||||
|
<n-form-item label="头像">
|
||||||
|
<n-button @click="showAvatarModal = true">打开</n-button>
|
||||||
|
<n-modal v-model:show="showAvatarModal" :mask-closable="false">
|
||||||
|
<VueAvatarUpload
|
||||||
|
:avatar="userStore.profile.avatar"
|
||||||
|
@close="showAvatarModal = false"
|
||||||
|
/>
|
||||||
|
</n-modal>
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item label="真名">
|
||||||
|
<n-input />
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item label="骚话">
|
||||||
|
<n-input />
|
||||||
|
</n-form-item>
|
||||||
|
<n-button>更改信息</n-button>
|
||||||
|
</n-form>
|
||||||
|
</n-gi>
|
||||||
|
<n-gi>
|
||||||
|
<h3>更改密码</h3>
|
||||||
|
<n-form>
|
||||||
|
<n-form-item label="旧密码">
|
||||||
|
<n-input type="password" />
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item label="新密码">
|
||||||
|
<n-input type="password" />
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item label="确认新密码">
|
||||||
|
<n-input type="password" />
|
||||||
|
</n-form-item>
|
||||||
|
<n-button>更改密码</n-button>
|
||||||
|
</n-form>
|
||||||
|
</n-gi>
|
||||||
|
<n-gi>
|
||||||
|
<h3>更改邮箱</h3>
|
||||||
|
<n-form>
|
||||||
|
<n-form-item label="当前密码">
|
||||||
|
<n-input type="password" />
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item label="旧邮箱">
|
||||||
|
<n-input />
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item label="新邮箱">
|
||||||
|
<n-input />
|
||||||
|
</n-form-item>
|
||||||
|
<n-button>更改邮箱</n-button>
|
||||||
|
</n-form>
|
||||||
|
</n-gi>
|
||||||
|
</n-grid>
|
||||||
|
</template>
|
||||||
|
<style scoped>
|
||||||
|
h3 {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -89,11 +89,8 @@ function run() {
|
|||||||
<n-space v-if="isDesktop" justify="space-between" align="center">
|
<n-space v-if="isDesktop" justify="space-between" align="center">
|
||||||
<n-menu mode="horizontal" :options="menus" :value="active" />
|
<n-menu mode="horizontal" :options="menus" :value="active" />
|
||||||
<n-space>
|
<n-space>
|
||||||
<n-button circle @click="toggleDark()">
|
<n-button v-if="$route.name === 'learn'" type="primary" @click="run">
|
||||||
<template #icon>
|
运行
|
||||||
<n-icon v-if="isDark"><i-ep-sunny /></n-icon>
|
|
||||||
<n-icon v-else> <i-ep-moon /></n-icon>
|
|
||||||
</template>
|
|
||||||
</n-button>
|
</n-button>
|
||||||
<div v-if="userStore.isFinished">
|
<div v-if="userStore.isFinished">
|
||||||
<n-dropdown
|
<n-dropdown
|
||||||
@@ -108,8 +105,11 @@ function run() {
|
|||||||
<n-button @click="toggleSignup(true)">注册</n-button>
|
<n-button @click="toggleSignup(true)">注册</n-button>
|
||||||
</n-space>
|
</n-space>
|
||||||
</div>
|
</div>
|
||||||
<n-button v-if="$route.name === 'learn'" type="primary" @click="run">
|
<n-button circle @click="toggleDark()">
|
||||||
运行
|
<template #icon>
|
||||||
|
<n-icon v-if="isDark"><i-ep-sunny /></n-icon>
|
||||||
|
<n-icon v-else> <i-ep-moon /></n-icon>
|
||||||
|
</template>
|
||||||
</n-button>
|
</n-button>
|
||||||
</n-space>
|
</n-space>
|
||||||
</n-space>
|
</n-space>
|
||||||
@@ -133,6 +133,12 @@ function run() {
|
|||||||
</template>
|
</template>
|
||||||
</n-button>
|
</n-button>
|
||||||
</n-dropdown>
|
</n-dropdown>
|
||||||
|
<n-button circle @click="toggleDark()">
|
||||||
|
<template #icon>
|
||||||
|
<n-icon v-if="isDark"><i-ep-sunny /></n-icon>
|
||||||
|
<n-icon v-else> <i-ep-moon /></n-icon>
|
||||||
|
</template>
|
||||||
|
</n-button>
|
||||||
</n-space>
|
</n-space>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import { PROBLEM_PERMISSION, STORAGE_KEY, USER_TYPE } from "utils/constants"
|
import { PROBLEM_PERMISSION, STORAGE_KEY, USER_TYPE } from "utils/constants"
|
||||||
import storage from "utils/storage"
|
import storage from "utils/storage"
|
||||||
|
import { Profile, User } from "~/utils/types"
|
||||||
import { getProfile } from "../api"
|
import { getProfile } from "../api"
|
||||||
|
|
||||||
export const useUserStore = defineStore("user", () => {
|
export const useUserStore = defineStore("user", () => {
|
||||||
const profile = ref()
|
const profile = ref<Profile | null>(null)
|
||||||
const [isFinished] = useToggle(false)
|
const [isFinished] = useToggle(false)
|
||||||
const user = computed(() => profile?.value?.user ?? {})
|
const user = computed<User>(() => profile!.value!.user)
|
||||||
const isAuthed = computed(() => !!user.value.email)
|
const isAuthed = computed(() => !!user.value.email)
|
||||||
const isAdminRole = computed(
|
const isAdminRole = computed(
|
||||||
() =>
|
() =>
|
||||||
@@ -28,7 +29,7 @@ export const useUserStore = defineStore("user", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function clearProfile() {
|
function clearProfile() {
|
||||||
profile.value = {}
|
profile.value = null
|
||||||
storage.clear()
|
storage.clear()
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user