设置页面

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

@@ -1,13 +1,13 @@
<template> <template>
<!-- <RouteCache /> --> <!-- <RouteCache /> -->
<router-view ></router-view> <router-view v-if="show"></router-view>
<div id="loading" v-if="loading" v-loading="true"></div> <div id="loading" v-if="loading" v-loading="true"></div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import RouteCache from '@/components/RouteCache.vue' import RouteCache from '@/components/RouteCache.vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { computed } from 'vue' import { computed, provide, nextTick, ref } from 'vue'
import { useGlobalStore } from '@/stores' import { useGlobalStore } from '@/stores'
const router = useRouter() const router = useRouter()
const globalStore = useGlobalStore() const globalStore = useGlobalStore()
@@ -22,6 +22,13 @@
window['onClickRegister'] = () => { window['onClickRegister'] = () => {
router.push({ name: 'register' }) router.push({ name: 'register' })
} }
const show = ref(true)
provide('reload', () => {
show.value = false
nextTick(() => {
show.value = true
})
})
</script> </script>
<style lang="less"> <style lang="less">

View File

@@ -0,0 +1,3 @@
<svg width="11" height="7" viewBox="0 0 11 7" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1 1L5.04979 5.04979L9.09958 1" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 223 B

View File

@@ -0,0 +1,5 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.75 9C9.75 8.58579 9.41421 8.25 9 8.25C8.58579 8.25 8.25 8.58579 8.25 9V12C8.25 12.4142 8.58579 12.75 9 12.75C9.41421 12.75 9.75 12.4142 9.75 12V9Z" fill="#0D0D0D"/>
<path d="M9 1.5C4.85786 1.5 1.5 4.85786 1.5 9C1.5 13.1421 4.85786 16.5 9 16.5C13.1421 16.5 16.5 13.1421 16.5 9C16.5 4.85786 13.1421 1.5 9 1.5ZM3 9C3 5.68629 5.68629 3 9 3C12.3137 3 15 5.68629 15 9C15 12.3137 12.3137 15 9 15C5.68629 15 3 12.3137 3 9Z" fill="#0D0D0D"/>
<path d="M9 6.97504C9.47635 6.97504 9.8625 6.58888 9.8625 6.11254C9.8625 5.63619 9.47635 5.25004 9 5.25004C8.52365 5.25004 8.1375 5.63619 8.1375 6.11254C8.1375 6.58888 8.52365 6.97504 9 6.97504Z" fill="#0D0D0D"/>
</svg>

After

Width:  |  Height:  |  Size: 761 B

View File

@@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.6731 1.77832H3.95313C3.1247 1.77832 2.45312 2.44989 2.45312 3.27832V12.7214C2.45312 13.5499 3.1247 14.2214 3.95313 14.2214H6.6731" stroke="black" stroke-width="1.5" stroke-linecap="round"/>
<path d="M13.2461 7.99854L7.18701 7.99853" stroke="black" stroke-width="1.5" stroke-linecap="round"/>
<path d="M10.8088 5.26001L13.5488 8L10.8088 10.74" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 541 B

View File

@@ -0,0 +1,8 @@
<svg width="13" height="14" viewBox="0 0 13 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.91235 5.97704C7.35576 5.97704 8.52587 4.80693 8.52587 3.36352C8.52587 1.92011 7.35576 0.75 5.91235 0.75C4.46894 0.75 3.29883 1.92011 3.29883 3.36352C3.29883 4.80693 4.46894 5.97704 5.91235 5.97704Z" stroke="black" stroke-width="1.5" stroke-linecap="round"/>
<path d="M0.75 13.1317C0.75 13.1317 0.75 12.9684 0.75 12.903C0.75 10.5835 2.48146 8.65606 4.73562 8.3457" stroke="black" stroke-width="1.5" stroke-linecap="round"/>
<path d="M8.39466 10.3384C9.01713 10.3384 9.52174 9.83378 9.52174 9.21131C9.52174 8.58884 9.01713 8.08423 8.39466 8.08423C7.77219 8.08423 7.26758 8.58884 7.26758 9.21131C7.26758 9.83378 7.77219 10.3384 8.39466 10.3384Z" fill="black"/>
<path d="M11.5138 10.3384C12.1363 10.3384 12.6409 9.83378 12.6409 9.21131C12.6409 8.58884 12.1363 8.08423 11.5138 8.08423C10.8913 8.08423 10.3867 8.58884 10.3867 9.21131C10.3867 9.83378 10.8913 10.3384 11.5138 10.3384Z" fill="black"/>
<path d="M8.39466 13.4583C9.01713 13.4583 9.52174 12.9537 9.52174 12.3312C9.52174 11.7087 9.01713 11.2041 8.39466 11.2041C7.77219 11.2041 7.26758 11.7087 7.26758 12.3312C7.26758 12.9537 7.77219 13.4583 8.39466 13.4583Z" fill="black"/>
<path d="M11.5138 13.4583C12.1363 13.4583 12.6409 12.9537 12.6409 12.3312C12.6409 11.7087 12.1363 11.2041 11.5138 11.2041C10.8913 11.2041 10.3867 11.7087 10.3867 12.3312C10.3867 12.9537 10.8913 13.4583 11.5138 13.4583Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,4 @@
<svg width="19" height="19" viewBox="0 0 19 19" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.40886 2.76749C8.30078 1.44443 10.2483 1.44443 11.1402 2.76749L11.5451 3.3681C11.9325 3.94273 12.563 4.30679 13.2544 4.35495L13.977 4.4053C15.5687 4.51619 16.5425 6.20275 15.8426 7.63671L15.5249 8.28767C15.221 8.91046 15.221 9.63858 15.5249 10.2614L15.8426 10.9123C16.5425 12.3463 15.5687 14.0328 13.9769 14.1437L13.2544 14.1941C12.563 14.2423 11.9325 14.6063 11.5451 15.1809L11.1402 15.7816C10.2483 17.1046 8.30078 17.1046 7.40886 15.7816L7.00397 15.1809C6.61659 14.6063 5.98602 14.2423 5.29469 14.1941L4.57209 14.1437C2.98033 14.0328 2.00659 12.3463 2.70643 10.9123L3.02413 10.2614C3.32809 9.63858 3.32809 8.91046 3.02413 8.28767L2.70644 7.63671C2.00659 6.20276 2.98033 4.51619 4.57209 4.4053L5.29469 4.35495C5.98602 4.30679 6.61659 3.94273 7.00397 3.3681L7.40886 2.76749Z" stroke="black" stroke-width="1.6875"/>
<circle cx="9.27539" cy="9.27441" r="1.93359" stroke="black" stroke-width="1.6875"/>
</svg>

After

Width:  |  Height:  |  Size: 1014 B

View File

@@ -0,0 +1,34 @@
<svg width="18" height="13" viewBox="0 0 18 13" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_n_692_30137)">
<path d="M14.1922 7.86884C15.1626 6.8473 15.4839 5.58249 15.8809 4.28415C15.9364 4.1025 15.959 3.91214 15.945 3.72254L15.76 1.19999C15.727 0.749411 15.4047 0.372032 14.9647 0.26874L14.2145 0.0926218C14.1812 0.0848104 14.1471 0.0808921 14.113 0.0808993C11.5893 0.0814305 9.05569 -0.0851513 6.6376 0.0893913C5.05504 0.202548 3.62996 1.08793 3.0211 2.56473C2.95266 2.73066 2.74058 3.33271 2.74106 3.46776L2.75196 6.51746C2.75251 6.67298 2.67121 6.81713 2.53792 6.89694L0.958446 7.84263C0.915651 7.86826 0.889546 7.91454 0.889725 7.96447C0.890124 8.07621 1.01361 8.14388 1.10778 8.08398L2.16799 7.40964C2.38037 7.27455 2.66002 7.41962 2.67245 7.67132L2.76518 9.54984L2.77334 11.8342C2.77421 12.0781 2.97261 12.2755 3.21647 12.2753L5.29787 12.2729C5.55742 12.2726 5.75463 12.0403 5.71286 11.784L5.37608 9.71745C5.37352 9.70169 5.37243 9.68568 5.37671 9.67032C5.38393 9.64442 5.39803 9.60614 5.40506 9.56942C5.41219 9.53216 5.42374 9.49297 5.45097 9.46659C5.47163 9.44658 5.49928 9.43537 5.52808 9.43534L9.6298 9.43068C9.89861 9.43037 10.1059 9.66831 10.0687 9.93443L9.81285 11.7635C9.77563 12.0296 9.98292 12.2676 10.2517 12.2673L12.7476 12.2644C12.8771 12.2643 12.9816 12.1592 12.9812 12.0297L12.9706 9.07613C12.9702 8.94553 13.0271 8.82104 13.1296 8.74029C13.4912 8.45529 13.8743 8.20332 14.1922 7.86884Z" fill="#272727"/>
<path d="M16.9689 8.63445C18.729 1.99586 16.9384 0.0927843 14.123 0.0959828L15.0919 6.48998C15.2358 6.43615 15.317 6.46736 15.3396 6.48969C15.7923 7.11527 15.5346 8.53918 15.3492 9.17294C15.0405 11.0824 15.9378 11.9107 16.6669 12.1803C16.8842 12.2607 17.094 12.0939 17.1212 11.8641L17.1937 11.2521C17.2225 11.0093 17.0039 10.7773 16.8926 10.5592C16.6655 10.1145 16.8233 9.16971 16.9689 8.63445Z" fill="#272727"/>
<path d="M0.861304 8.40801C0.764736 8.51498 0.58841 8.47735 0.543626 8.34022L0.408584 7.92673C0.363724 7.78937 0.484462 7.65523 0.625813 7.6854L1.05205 7.77636C1.1934 7.80652 1.24923 7.97834 1.1525 8.08548L0.861304 8.40801Z" fill="#272727"/>
</g>
<path d="M17.043 5.93021C17.0438 5.93021 17.0446 5.93021 17.0777 5.93017C17.1108 5.93013 17.1762 5.93006 17.2733 5.93962" stroke="#E4E5D7" stroke-width="0.187554" stroke-linecap="round"/>
<path d="M17.043 6.30082C17.0438 6.30082 17.0446 6.30081 17.0777 6.30078C17.1108 6.30074 17.1762 6.30067 17.2733 6.31022" stroke="#E4E5D7" stroke-width="0.187554" stroke-linecap="round"/>
<path d="M12.393 1.62356C11.6861 0.960209 10.0414 0.0322616 8.74643 1.6277C8.19193 2.46239 7.80275 4.03743 10.0856 5.88913C10.5515 6.26701 11.4827 6.88377 12.1553 6.60499C12.3639 6.48891 12.6836 6.27077 12.6629 5.67769L12.6103 3.94013" stroke="#E4E5D7" stroke-width="0.281331" stroke-linecap="round"/>
<path d="M15.6617 2.4319C15.8624 2.43177 15.9885 2.62095 15.9892 2.8036C15.9898 2.98623 15.8651 3.17571 15.6643 3.17604C15.5537 3.17616 15.4649 3.10285 15.4109 3.03179C15.3545 2.95765 15.3137 2.8585 15.3132 2.75847C15.3129 2.65183 15.3586 2.56581 15.4295 2.50931C15.4974 2.45537 15.5827 2.43199 15.6617 2.4319Z" stroke="#E4E5D7" stroke-width="0.234443"/>
<path d="M14.4761 2.43312C14.6879 2.43298 14.8265 2.63062 14.8272 2.82823C14.8275 2.94411 14.7707 3.04327 14.6993 3.1106C14.6288 3.17686 14.5316 3.2231 14.4321 3.22321C14.3223 3.22324 14.2397 3.16682 14.1904 3.08579C14.1447 3.01068 14.1283 2.91761 14.1279 2.82902C14.1272 2.63136 14.2643 2.43336 14.4761 2.43312Z" stroke="#E4E5D7" stroke-width="0.234443"/>
<path d="M12.4615 11.4724C12.4612 11.3826 12.5337 11.3098 12.6235 11.3097C12.7133 11.3096 12.7864 11.3823 12.7867 11.4721L12.7888 12.0503C12.7888 12.0762 12.7679 12.0972 12.742 12.0972L12.5106 12.0975C12.4847 12.0975 12.4637 12.0766 12.4636 12.0507L12.4615 11.4724Z" fill="#E4E5D7"/>
<path d="M4.33481 11.6446C4.33436 11.5164 4.43797 11.4123 4.56625 11.4121C4.69452 11.412 4.79888 11.5158 4.79934 11.6441L4.80083 12.06C4.80092 12.0859 4.78 12.1069 4.7541 12.107L4.38336 12.1074C4.35746 12.1074 4.33639 12.0864 4.3363 12.0605L4.33481 11.6446Z" fill="#E4E5D7"/>
<path d="M4.99442 11.3379C4.98887 11.2355 5.06744 11.1481 5.16992 11.1428C5.27239 11.1376 5.35996 11.2164 5.36551 11.3188L5.40304 12.0119C5.40445 12.0378 5.38462 12.0598 5.35876 12.0612L5.08132 12.0755C5.05546 12.0768 5.03336 12.0569 5.03196 12.031L4.99442 11.3379Z" fill="#E4E5D7"/>
<path d="M12.0006 11.7974C12.0003 11.7076 12.0728 11.6347 12.1626 11.6346C12.2524 11.6345 12.3254 11.7072 12.3257 11.797L12.3267 12.0509C12.3267 12.0768 12.3058 12.0978 12.2799 12.0978L12.0485 12.0981C12.0226 12.0981 12.0016 12.0772 12.0015 12.0513L12.0006 11.7974Z" fill="#E4E5D7"/>
<defs>
<filter id="filter0_n_692_30137" x="0.398438" y="0.00955702" width="17.2695" height="12.2656" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feTurbulence type="fractalNoise" baseFrequency="21.327169418334961 21.327169418334961" stitchTiles="stitch" numOctaves="3" result="noise" seed="4152" />
<feColorMatrix in="noise" type="luminanceToAlpha" result="alphaNoise" />
<feComponentTransfer in="alphaNoise" result="coloredNoise1">
<feFuncA type="discrete" tableValues="1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "/>
</feComponentTransfer>
<feComposite operator="in" in2="shape" in="coloredNoise1" result="noise1Clipped" />
<feFlood flood-color="#3B3B3B" result="color1Flood" />
<feComposite operator="in" in2="noise1Clipped" in="color1Flood" result="color1" />
<feMerge result="effect1_noise_692_30137">
<feMergeNode in="shape" />
<feMergeNode in="color1" />
</feMerge>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -0,0 +1,64 @@
<template>
<el-dropdown trigger="click" placement="bottom-end">
<div class="title">
<span class="label">{{ title }}</span>
<span class="icon"><svg-icon name="arrow-bottom" size="10" color="#000" /></span>
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item
v-for="item in list"
:key="item.value"
:disabled="item.value === modelValue"
@click="onItemClick(item.value)"
style="--el-font-size-base: 1.4rem; --el-text-color-regular: #000"
>
<span>{{ item.label }}</span>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
<script setup lang="ts">
import { onMounted, ref, computed, watch, nextTick } from 'vue'
const props = defineProps({
modelValue: {
type: String,
default: ''
},
list: {
type: [Array, Object],
default: () => []
},
icon: {
type: String,
default: ''
}
})
const title = computed(() => {
return props.list.find((v) => v.value === props.modelValue)?.label || '---'
})
const emit = defineEmits(['update:modelValue', 'change'])
const onItemClick = (value: string) => {
emit('update:modelValue', value)
emit('change', value)
}
</script>
<style lang="less" scoped>
.title {
user-select: none;
cursor: pointer;
display: flex;
align-items: center;
font-size: 1.4rem;
color: #000;
> .label {
// min-width: 7rem;
}
> .icon {
margin-left: 1.6rem;
}
}
</style>

View File

@@ -1,70 +1,46 @@
// 每一个存储的模块命名规则use开头store结尾 // 每一个存储的模块命名规则use开头store结尾
import router from '@/router'
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { ref, computed } from 'vue' import { ref, computed } from 'vue'
import { removeLocal, setLocal } from '@/utils/local' import { removeLocal, setLocal } from '@/utils/local'
import MyEvent from '@/utils/myEvent' import MyEvent from '@/utils/myEvent'
export const useUserInfoStore = defineStore('userInfo', () => { export const useUserInfoStore = defineStore('userInfo', () => {
const state = ref({ const state = ref({
userInfo: {}, userInfo: {},
token: '', token: '',
generateParams: {
stylist: '',
sex: '',
stylistImage: ''
}
})
// getters })
const getUserInfo = computed(() => state.value.userInfo)
// actions // getters
const setUserInfo = (data: any) => { const getUserInfo = computed(() => state.value.userInfo)
state.value.userInfo = data
}
const setToken = (data: string) => { // actions
state.value.token = data const setUserInfo = (data: any) => {
// setLocal(data, 'token') state.value.userInfo = data
} }
const getGenerateParams = () => { const setToken = (data: string) => {
return state.value.generateParams state.value.token = data
} // setLocal(data, 'token')
}
const setGenerateParams = (data: any) => { const logOut = async () => {
state.value.generateParams = data // 处理退出登录的一些逻辑
} state.value.token = ''
state.value.userInfo = {}
// removeLocal('token')
// MyEvent.emit('clear-generate-state')
// MyEvent.emit('clear-client-state')
// MyEvent.emit('clearAllCache')
router.push({ name: 'login' })
return ""
}
const resetGenerateParams = () => { return {
state.value.generateParams = { state,
stylist: '', getUserInfo,
sex: '', setToken,
stylistImage: '' setUserInfo,
} logOut
} }
const logOut = () => {
// 处理退出登录的一些逻辑
return new Promise((resolve) => {
state.value.token = ''
state.value.userInfo = {}
removeLocal('token')
resetGenerateParams()
MyEvent.emit('clear-generate-state')
MyEvent.emit('clear-client-state')
MyEvent.emit('clearAllCache')
resolve('')
})
}
return {
state,
getUserInfo,
setToken,
setUserInfo,
setGenerateParams,
getGenerateParams,
resetGenerateParams,
logOut
}
}) })

View File

@@ -15,12 +15,14 @@
<div class="bottom-view"><router-view></router-view></div> <div class="bottom-view"><router-view></router-view></div>
</div> </div>
</div> </div>
<setting />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue' import { computed } from 'vue'
import LeftNav from './left-nav.vue' import LeftNav from './left-nav.vue'
import TopNav from './top-nav.vue' import TopNav from './top-nav.vue'
import setting from './setting/index.vue'
import { useGlobalStore } from '@/stores' import { useGlobalStore } from '@/stores'
const globalStore = useGlobalStore() const globalStore = useGlobalStore()
const loading = computed(() => globalStore.state.loading) const loading = computed(() => globalStore.state.loading)

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>

View File

@@ -12,13 +12,38 @@
<span class="link"></span> <span class="link"></span>
<span class="icon" @click="onShop"><svg-icon name="shop" size="21" /></span> <span class="icon" @click="onShop"><svg-icon name="shop" size="21" /></span>
</div> </div>
<img class="pic" src="@/assets/images/pic.jpg" /> <el-popover
placement="bottom-end"
popper-style="width:auto; min-width: 22rem; padding: 0.8rem; border-radius: 1.4rem;"
>
<template #reference>
<img class="pic" src="@/assets/images/pic.jpg" />
</template>
<div class="menu-box">
<div>
<span class="label">{{ email }}</span>
</div>
<p></p>
<div class="btn" @click="onSetting">
<span class="icon"><svg-icon name="setting" size="18" /></span>
<span class="label">Settings</span>
</div>
<div class="btn" @click="onLogout">
<span class="icon"><svg-icon name="logout" size="18" /></span>
<span class="label">Log out</span>
</div>
</div>
</el-popover>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import MyEvent from '@/utils/myEvent'
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { useUserInfoStore } from '@/stores'
const userInfoStore = useUserInfoStore()
const email = computed(() => userInfoStore.state.userInfo.email || '------')
const route = useRoute() const route = useRoute()
const topNavStyle = computed(() => route.meta.topNavStyle) const topNavStyle = computed(() => route.meta.topNavStyle)
const router = useRouter() const router = useRouter()
@@ -37,6 +62,12 @@
loading.value = false loading.value = false
}, 1500) }, 1500)
} }
const onSetting = () => {
MyEvent.emit('openSettingDialog')
}
const onLogout = () => {
userInfoStore.logOut()
}
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@@ -68,7 +99,7 @@
height: 4.3rem; height: 4.3rem;
margin-right: 1rem; margin-right: 1rem;
background-color: rgba(255, 252, 244, 1); background-color: rgba(255, 252, 244, 1);
border: 1px solid #FFCF90; border: 1px solid #ffcf90;
border-radius: 0.8rem; border-radius: 0.8rem;
> .credits { > .credits {
flex: 1; flex: 1;
@@ -78,7 +109,7 @@
> .link { > .link {
height: 100%; height: 100%;
width: 0; width: 0;
border-right: 1px solid #FFCF90; border-right: 1px solid #ffcf90;
} }
> .icon { > .icon {
cursor: pointer; cursor: pointer;
@@ -88,10 +119,46 @@
animation: loading 0.6s linear infinite; animation: loading 0.6s linear infinite;
} }
} }
> .pic { .pic {
width: 4.65rem; width: 4.65rem;
height: 4.65rem; height: 4.65rem;
border-radius: 50%; border-radius: 50%;
} }
} }
.menu-box {
user-select: none;
> * {
margin-bottom: 0.4rem;
&:last-child {
margin-bottom: 0;
}
}
> div {
height: 3.7rem;
display: flex;
align-items: center;
// justify-content: center;
&.btn {
cursor: pointer;
}
&.btn:hover {
background-color: rgba(0, 0, 0, 0.06);
}
> .label {
font-size: 1.4rem;
color: #000;
margin-left: 0.8rem;
}
> .icon {
margin-left: 1rem;
--svg-icon-color: #000;
}
}
> p {
width: 100%;
height: 0;
border-bottom: 0.1rem solid #e5e5e5;
}
}
</style> </style>

View File

@@ -104,6 +104,9 @@
.then((res) => { .then((res) => {
if (res) { if (res) {
userInfoStore.setToken(res) userInfoStore.setToken(res)
userInfoStore.setUserInfo({
email: formData.email
})
router.push({ name: 'mainInput' }) router.push({ name: 'mainInput' })
} }
}) })

View File

@@ -111,6 +111,9 @@
.then((res) => { .then((res) => {
if (res) { if (res) {
userInfoStore.setToken(res) userInfoStore.setToken(res)
userInfoStore.setUserInfo({
email: formData.email
})
router.push({ name: 'nuic' }) router.push({ name: 'nuic' })
} }
}) })

View File

@@ -25,7 +25,7 @@
<div class="bg-2"></div> <div class="bg-2"></div>
<div class="bg-1"></div> <div class="bg-1"></div>
</div> </div>
<img class="loading-img" :class="{ loading }" src="@/assets/images/nuic/xiang.png" /> <img class="loading-img" :class="{ loading }" src="@/assets/images/nuic/xiang.gif" />
<div class="loading-tip" :class="{ loading }">{{ $t('Nuic.loadingTip') }}</div> <div class="loading-tip" :class="{ loading }">{{ $t('Nuic.loadingTip') }}</div>
</div> </div>
</template> </template>
@@ -167,7 +167,7 @@
top: 50%; top: 50%;
left: 50%; left: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
width: 14.4rem; width: 60rem;
height: auto; height: auto;
opacity: 0; opacity: 0;
&.loading { &.loading {