设置页面

This commit is contained in:
2026-02-23 14:45:35 +08:00
parent 1e21e3b408
commit e6cba6f031
20 changed files with 530 additions and 63 deletions

View File

@@ -0,0 +1,52 @@
<template>
<div>
<div class="label">User Name</div>
<div class="value">张三</div>
</div>
<div>
<div class="label">Email</div>
<div class="value">zhangsan@example.com</div>
</div>
<div>
<div class="label">Language</div>
<dropdown-menu v-model="locale" :list="langs" @change="changeLang" />
</div>
<div>
<div class="label">Log out on this device</div>
<button class="logout-btn" @click="logout">Log out</button>
</div>
</template>
<script setup lang="ts">
import { computed, ref, onBeforeUnmount, inject } from 'vue'
import dropdownMenu from '@/components/dropdown-menu.vue'
import { useUserInfoStore } from '@/stores'
import { useI18n } from 'vue-i18n'
const { locale } = useI18n()
const reload = inject('reload')
const userInfoStore = useUserInfoStore()
const langs = ref([
{ label: 'English', value: 'ENGLISH' },
{ label: '中文', value: 'CHINESE_SIMPLIFIED' }
])
const changeLang = (value: string) => {
locale.value = value
reload()
}
const logout = () => {
userInfoStore.logOut()
}
</script>
<style lang="less" scoped>
.logout-btn {
cursor: pointer;
height: 3.7rem;
width: 9.6rem;
border-radius: 3.7rem;
border: none;
background-color: #ff7a51;
color: #fff;
font-size: 1.4rem;
}
</style>

View File

@@ -0,0 +1,33 @@
<template>
<div>
<div class="label">User Agreement</div>
<button @click="onClickUserAgreement">View</button>
</div>
<div>
<div class="label">Privacy Policy</div>
<button @click="onClickPrivacy">View</button>
</div>
</template>
<script setup lang="ts">
import { computed, ref, onBeforeUnmount, inject } from 'vue'
const onClickUserAgreement = () => {
console.log('onClickUserAgreement')
}
const onClickPrivacy = () => {
console.log('onClickPrivacy')
}
</script>
<style lang="less" scoped>
button {
width: 10rem;
height: 3.73rem;
background-color: transparent;
border: 0.01rem solid #b5b5b5;
color: #000;
font-size: 1.4rem;
border-radius: 3rem;
}
</style>

View File

@@ -0,0 +1,75 @@
<template>
<div>
<div class="label">Region</div>
<dropdown-menu v-model="region" :list="regions" @change="changeRegion" />
</div>
<div>
<div class="label">Role</div>
<dropdown-menu v-model="role" :list="roles" @change="changeRole" />
</div>
<div>
<div class="label">Current Agent Profile</div>
<div class="group">
<span class="icon"><svg-icon name="xiang" size="20" color="#000" /></span>
<dropdown-menu v-model="agent" :list="agents" @change="changeAgent" />
</div>
</div>
<div>
<div class="label">Current Notification Frequency</div>
<div class="value">36 times per hour</div>
</div>
</template>
<script setup lang="ts">
import { computed, ref, onBeforeUnmount, inject } from 'vue'
import dropdownMenu from '@/components/dropdown-menu.vue'
import { useUserInfoStore } from '@/stores'
import { useI18n } from 'vue-i18n'
const { locale } = useI18n()
const region = ref('China')
const regions = ref([
{ label: 'United States', value: 'United States' },
{ label: 'Singapore', value: 'Singapore' },
{ label: 'Australia', value: 'Australia' },
{ label: 'South Korea', value: 'South Korea' },
{ label: 'China', value: 'China' },
{ label: 'Italy', value: 'Italy' },
{ label: 'France', value: 'France' },
{ label: 'Japan', value: 'Japan' },
{ label: 'Canada', value: 'Canada' },
{ label: 'Germany', value: 'Germany' }
])
const changeRegion = (value: string) => {
console.log(value)
}
const role = ref('Designer')
const roles = ref([
{ label: 'Designer', value: 'Designer' },
{ label: 'Student', value: 'Student' },
{ label: 'Teacher', value: 'Teacher' },
{ label: 'Parent', value: 'Parent' }
])
const changeRole = (value: string) => {
console.log(value)
}
const agent = ref('Partner')
const agents = ref([
{ label: 'Partner', value: 'Partner' },
{ label: 'Observer', value: 'Observer' },
{ label: 'Mentor', value: 'Mentor' }
])
const changeAgent = (value: string) => {
console.log(value)
}
</script>
<style lang="less" scoped>
.group {
display: flex;
align-items: center;
justify-content: center;
gap: 1rem;
}
</style>

View File

@@ -0,0 +1,126 @@
<template>
<el-dialog
class="setting"
v-model="showDialog"
align-center
:show-close="false"
width="70rem"
style="border-radius: 2rem; padding: 3.8rem; --el-dialog-padding-primary: 1rem"
>
<template #header="{ close }">
<div class="setting-header">
<div class="title">Setting</div>
<span class="close" @click="close">
<svg-icon name="close" size="10" color="#000" />
</span>
</div>
</template>
<div class="setting-box">
<div class="left">
<div
v-for="v in navs"
:key="v.icon"
:class="{ active: nav === v.icon }"
@click="nav = v.icon"
>
<span class="icon"><svg-icon :name="v.icon" size="18" color="#000" /></span>
<span class="label">{{ v.label }}</span>
</div>
</div>
<div class="view">
<component :is="navs.find((v) => v.icon === nav).component" />
</div>
</div>
</el-dialog>
</template>
<script setup lang="ts">
import General from './General.vue'
import Profile from './Profile.vue'
import LearnMore from './LearnMore.vue'
import MyEvent from '@/utils/myEvent'
import { computed, ref, onBeforeUnmount, shallowRef } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useI18n } from 'vue-i18n'
const { t: $t } = useI18n()
const route = useRoute()
const router = useRouter()
const showDialog = ref(false)
const openSetting = () => {
showDialog.value = true
}
MyEvent.add('openSettingDialog', openSetting)
onBeforeUnmount(() => {
MyEvent.remove('openSettingDialog', openSetting)
})
const nav = ref('setting')
const navs = shallowRef([
{ icon: 'setting', label: 'General', component: General },
{ icon: 'profile', label: 'Profile', component: Profile },
{ icon: 'learn-more', label: 'Learn more', component: LearnMore }
])
</script>
<style lang="less" scoped>
.setting-header {
margin-top: 0.2rem;
display: flex;
align-items: center;
justify-content: space-between;
padding-bottom: 3.3rem;
border-bottom: 0.1rem solid rgba(0, 0, 0, 0.1);
> .title {
font-family: Semibold;
font-size: 1.6rem;
color: #000;
}
}
.setting-box {
width: 100%;
height: 50rem;
display: flex;
> .left {
margin-top: 1.8rem;
> div {
width: 16.4rem;
height: 3.4rem;
display: flex;
align-items: center;
// justify-content: center;
cursor: pointer;
&.active {
background: rgba(0, 0, 0, 0.04);
border-radius: 1rem;
}
> .icon {
margin: 0 1rem;
}
> .label {
color: #000;
font-size: 1.4rem;
}
}
}
> .view {
margin-left: 3.5rem;
flex: 1;
overflow-y: auto;
&::v-deep(> div) {
display: flex;
align-items: center;
justify-content: space-between;
height: 6rem;
border-bottom: 0.1rem solid rgba(0, 0, 0, 0.1);
&:last-child {
border-bottom: none;
}
> .value,
> .label {
font-size: 1.4rem;
color: #000;
}
}
}
}
</style>