add setting.

This commit is contained in:
2023-02-17 08:41:58 +08:00
parent 2ea6cc7385
commit 86315f63dc
6 changed files with 95 additions and 14 deletions

6
package-lock.json generated
View File

@@ -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",

View File

@@ -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"
}, },

View File

@@ -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 {

View File

@@ -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>

View File

@@ -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>

View File

@@ -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 {