Commit f6ea7b35 authored by 罗超's avatar 罗超

完成菜單改造和用戶彈窗

parent b175dc6b
......@@ -12,4 +12,7 @@ export default defineComponent({
<style lang="sass">
@import url('./css/font.sass')
@import url('//at.alicdn.com/t/c/font_3734871_9agx0gqqibi.css')
body
font-family: '-apple-system','BlinkMacSystemFont','Segoe UI','Roboto','Helvetica Neue','Arial','Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol','Noto Color Emoji','MicrosoftJhengHeiBoldFix','Microsoft JhengHei' !important
color: var(--q-dark)
</style>
<template>
<div>
<p>{{ title }}</p>
<ul>
<li v-for="todo in todos" :key="todo.id" @click="increment">{{ todo.id }} - {{ todo.content }}</li>
</ul>
<p>Count: {{ todoCount }} / {{ meta.totalCount }}</p>
<p>Active: {{ active ? 'yes' : 'no' }}</p>
<p>Clicks on todos: {{ clickCount }}</p>
<p>前端之神:罗超</p>
<img src="../assets/images/lg-logo.png" style="height:200px;filter: grayscale(100%);"/>
<div class="q-mt-lg text-h3 text-grey-4 text-center">歡迎使用JVS同業預定系統</div>
</div>
</template>
......
<template>
<q-item :to="menu.MenuUrl" clickable v-ripple :active="currentPath == menu.MenuUrl" v-if="!menu.SubList || menu.SubList.length == 0" :key="menu.MenuId">
<q-item-section avatar style="min-width: 30px">
<q-icon :name="menu.MenuIcon" size="20px" />
<q-expansion-item class="demo" :class="{ 'nav-parent': activeParent }">
<template v-slot:header>
<q-item-section>
<div class="row items-center nav-group">
<svg-icon :icon="menu.icon" :size="18" color="nav"></svg-icon>
<span class="q-ml-sm" :class="{ 'parent-name': activeParent }">{{ menu.name }}</span>
</div>
</q-item-section>
</template>
<template v-if="menu.childs">
<q-item active-class="nav-active" :active="x.id == activeMenu" @click="checkMenuHandler(x.id)" class="q-ml-md rounded-borders q-mr-md q-pl-md sunzi" clickable v-ripple v-for="(x, i) in menu.childs" :key="i">
<q-item-section>
<div class="row items-center nav-item">
<svg-icon icon="Design/Circle.svg" :size="8" color="nav"></svg-icon>
<span class="q-ml-sm">{{ x.name }}</span>
</div>
</q-item-section>
<q-item-section>{{ menu.MenuName }}</q-item-section>
</q-item>
<q-expansion-item class="diy-group-items" v-else :label="menu.MenuName" :icon="menu.MenuIcon">
<q-item class="q-ml-md" style="padding-left:38px;" :to="y.MenuUrl" clickable v-ripple :active="currentPath == y.MenuUrl" v-for="(y, yi) in menu.SubList" :key="yi">
<q-item-section>{{ y.MenuName }}</q-item-section>
</q-item>
</template>
</q-expansion-item>
</template>
<script>
import { defineComponent,inject } from 'vue'
<script lang="ts">
import { Menu, MENU_KEYS } from '../../utils/menus'
import { computed, defineComponent, inject, PropType, provide, reactive, toRefs,ref, watch } from 'vue'
import svgIcon from '../global/svg-icon.vue'
export default defineComponent({
components:{svgIcon},
name: 'nav-item',
props: {
menu: {
type: Object,
type: Object as PropType<Menu>,
required: true
}
},
setup() {
let currentPath=inject('currentPath')
return {currentPath}
setup(props) {
const activeMenu = inject(MENU_KEYS) as any
const data = reactive({
activeParent: computed(() => {
if (props.menu.childs) {
let temp = props.menu.childs.find(x => x.id == activeMenu.value)
return temp ? true : false
} else {
return props.menu.id == activeMenu.value
}
})
})
const methods = {
checkMenuHandler(id: number) {
activeMenu.value = id
}
}
return { ...toRefs(data), ...methods, activeMenu }
}
})
</script>
\ No newline at end of file
<style></style>
<style>
.navs-list .diy-group-items .q-item__section--avatar{
min-width: 30px !important;
}
.navs-list .q-item.q-router-link--active, .q-item--active{
color:var(--q-primary) !important;
}
</style>
\ No newline at end of file
<template>
<q-list>
<nav-item v-for="(x,i) in menus" :menu="x" :key="i"></nav-item>
<q-list style="color:#9d9da6">
<nav-item :menu="x" v-for="x in menus"></nav-item>
</q-list>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { defineComponent,ref,reactive, toRefs, provide } from 'vue'
import navItem from './nav-item.vue'
import { useMenus, Menu, MENU_KEYS } from '../../utils/menus'
export default defineComponent({
components: { navItem },
name: 'navs',
props: {
menus: {
type: Array,
required: true
}
setup() {
const activeMenu=ref(0)
provide(MENU_KEYS, activeMenu)
const data = reactive({
menus: [] as Menu[]
})
data.menus = useMenus.getMenus()
return {...toRefs(data)}
}
})
</script>
<style></style>
<style>
.nav-list .nav-group:hover span,
.nav-list .nav-item:hover span,
.nav-list .nav-item.active span,
.nav-list .nav-group.active span,
.parent-name{
color: #FFFFFF !important;
}
.nav-list .nav-group.active .svg-icon-nav g [fill],
.nav-group:hover .svg-icon-nav g [fill],
.nav-item:hover .svg-icon-nav g [fill],
.nav-list .nav-item.active .svg-icon-nav g [fill],
.nav-active .svg-icon-nav g [fill],
.nav-parent .svg-icon-nav g [fill]{
fill: #FFFFFF !important;
/* color: #FFFFFF !important; */
}
.nav-list .q-focus-helper{
opacity: 0 !important;
}
.nav-active{
color:#FFF !important;
transition: color 0.2s ease;
background-color: #2A2A3C;
}
</style>
<template>
<q-card flat class="bg-white q-pa-none q-py-sm" style="width: 275px; shadow: 0px 0px 50px 0px rgba(82, 63, 105, 0.15)">
<div class="q-px-sm">
<div class="q-pa-sm row">
<q-avatar size="50px" rounded class="bg-blue-2 cursor-pointer q-mr-md">
<img :src="user.photo" v-if="user?.photo" />
<span class="text-primary text-h6" v-else>{{ user?.name.substring(0, 1) }}</span>
</q-avatar>
<div class="col column">
<div class="col row items-center">
<span class="text-weight-bold text-subtitle1 q-mr-md">{{ user?.name }}</span>
<span class="bg-green-11 text-green-14 rounded-borders q-px-sm">已認證</span>
</div>
<div class="f12 text-grey-6 f12">{{ user?.account }}</div>
</div>
</div>
</div>
<q-separator color="grey-3" class="q-my-sm" />
<q-list class="q-px-md text-subtitle2">
<q-item clickable v-ripple class="rounded-borders lang-demo">
<q-item-section>{{ $t('userMenu.mypro') }}</q-item-section>
</q-item>
<q-item clickable v-ripple class="rounded-borders lang-demo">
<q-item-section>
<div class="row items-center">
<div class="q-mr-md">{{ $t('userMenu.myfinace') }}</div>
<q-badge rounded class="din bg-red-2 text-red-14 text-weight-bold" label="3" />
</div>
</q-item-section>
</q-item>
<q-item clickable v-ripple class="rounded-borders lang-demo">
<q-item-section>{{ $t('userMenu.fapiao') }}</q-item-section>
</q-item>
</q-list>
<q-separator color="grey-3" class="q-my-sm" />
<q-list class="q-px-md text-subtitle2">
<q-item clickable v-ripple class="rounded-borders lang-demo">
<q-item-section>
<div class="row">
<div class="col">{{ $t('userMenu.lang') }}</div>
<div class="lang-box bg-grey-2 q-px-sm rounded-borders">
<span>{{currentLang.langName}}</span>
<q-popup-proxy class="no-shadow">
<q-card class="q-pa-sm" flat dark>
<q-list>
<q-item class="rounded-borders" clickable v-ripple v-for="(x,i) in langs" @click="getLanguage(x)">
<q-item-section>
<div class="row">
<div class="f12 dark col">{{x.langName}}</div>
</div>
</q-item-section>
</q-item>
</q-list>
</q-card>
</q-popup-proxy>
</div>
</div>
</q-item-section>
</q-item>
<q-item clickable v-ripple class="rounded-borders lang-demo" @click="signOut">
<q-item-section>{{ $t('userMenu.signOut') }}</q-item-section>
</q-item>
</q-list>
</q-card>
</template>
<script lang="ts">
import { defineComponent, ref, reactive, toRefs, provide } from 'vue'
import { getLangs } from "../../utils/tools";
import { SitLang } from '../../@types';
import { useI18n } from 'vue-i18n'
import { dispatchAction } from '../../store/utils';
import { UserActionsType } from '../../store/modules/user/actions';
export default defineComponent({
name: 'user-info',
props: {
user: {
type: Object,
require: true
}
},
setup(props) {
const {locale,t } = useI18n();
const data=reactive({
currentLang: {} as SitLang,
langs:[] as SitLang[],
})
data.langs=getLangs()
if(data.langs && data.langs.length>0){
data.currentLang = data.langs.find(x=> x.langLocale==locale.value) ?? {};
}
// 切换语言
const methods = {
getLanguage (val:SitLang) {
locale.value = val.langLocale??''
data.currentLang=val
localStorage.setItem('lanuage', val.langLocale??'')
window.location.reload()
},
signOut(){
dispatchAction<UserActionsType>('user', 'setUserSignout', null)
window.location.reload()
}
}
return {...toRefs(data),...methods}
}
})
</script>
<style>
.lang-demo:hover .lang-box{
background: unset !important;
}
.lang-demo:hover .q-item__section{
color:var(--q-primary) !important;
}
</style>
......@@ -38,9 +38,7 @@
font-family: 'din'
.Poppins
font-family: 'Poppins'
body
font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji,MicrosoftJhengHeiBoldFix,"\5FAE\8EDF\6B63\9ED1\9AD4",Microsoft JhengHei
color: var(--q-dark)
.no-underline
text-decoration: none !important
.change-a-primary
......
......@@ -9,6 +9,13 @@ export default {
lanuage:"系統語言",
loginout:'登錄信息失效,請重新登錄',
timeout:'當前網絡環境異常,請求超時',
userMenu:{
mypro:'個人檔案',
myfinace:'請求書',
fapiao:'索取發票',
lang:'系統語言',
signOut:'登出'
},
menu:{
hotel:{
first:'酒店預訂',
......
......@@ -9,9 +9,12 @@
</q-btn>
<div class="mobile-only q-ml-md text-dark text-h6 text-weight-bold">JVS</div>
</div>
<q-avatar size="40px" rounded class="bg-blue-2">
<img src="https://cdn.quasar.dev/logo-v2/svg/logo-mono-white.svg" v-if="userInfo.photo" />
<q-avatar size="40px" rounded class="bg-blue-2 cursor-pointer">
<img :src="userInfo.photo" v-if="userInfo.photo" />
<span class="text-primary text-h6" v-else>{{ userInfo.name.substring(0, 1) }}</span>
<q-popup-proxy :offset="[0,15]" class="no-shadow">
<user-info :user="userInfo"></user-info>
</q-popup-proxy>
</q-avatar>
</q-toolbar-title>
</q-toolbar>
......@@ -23,29 +26,8 @@
<div class="text-white text-weight-bold text-subtitle1 q-ml-md">{{ $t('siteName') }}</div>
</div>
<q-scroll-area :thumb-style="scrollStyle.thumbStyle" :bar-style="scrollStyle.barStyle" class="col nav-list q-pl-lg">
<q-list style="color:#9d9da6">
<q-expansion-item class="demo" :class="{'nav-parent':activeParent==x.id}" v-for="(x, i) in menus" :key="i">
<template v-slot:header>
<q-item-section>
<div class="row items-center nav-group">
<svg-icon :icon="x.icon" :size="18" color="nav"></svg-icon>
<span class="q-ml-sm" :class="{'parent-name':activeParent==x.id}">{{ x.name }}</span>
</div>
</q-item-section>
</template>
<q-item active-class="nav-active" :active="y.id==activeMenu" @click="checkMenuHandler(x.id,y.id)" class="q-ml-md rounded-borders q-mr-md q-pl-md sunzi" clickable v-ripple v-for="(y, yi) in x.childs" :key="yi">
<q-item-section>
<div class="row items-center nav-item">
<svg-icon icon="Design/Circle.svg" :size="8" color="nav"></svg-icon>
<span class="q-ml-sm">{{ y.name }}</span>
</div>
</q-item-section>
</q-item>
</q-expansion-item>
</q-list>
<navs></navs>
</q-scroll-area>
<!-- drawer content -->
</q-drawer>
<q-page-container class="q-pa-md">
......@@ -64,37 +46,28 @@
<script lang="ts">
import { reactive, ref, toRefs } from 'vue'
import { dispatchAction, getStoreGetter } from '../store/utils'
import { getStoreGetter } from '../store/utils'
import { UserGetter } from '../store/modules/user/getters'
import svgIcon from '../components/global/svg-icon.vue'
import useScrollModule from '../module/scrollbar/scrollModule'
import { useMenus, Menu } from '../utils/menus'
import Navs from '../components/layout/navs.vue'
import userInfo from "../components/layout/userInfo.vue";
export default {
components: { svgIcon },
components: { svgIcon, Navs,userInfo },
setup() {
const leftDrawerOpen = ref(false)
const data = reactive({
userInfo: {} as any,
leftDrawerOpen: false,
scrollStyle: {} as any,
menus: [] as Menu[],
activeMenu:0,
activeParent:0
scrollStyle: {} as any
})
data.userInfo = getStoreGetter<UserGetter>('user', 'getUser')
data.scrollStyle = useScrollModule().scrollStyle
data.menus = useMenus.getMenus()
const methods = {
toggleLeftDrawer() {
data.leftDrawerOpen = !data.leftDrawerOpen
},
checkMenuHandler(p:number,id:number){
data.activeMenu=id
data.activeParent=p
console.log(data)
}
}
console.log(data.userInfo.accountId)
return {
...toRefs(data),
...methods
......@@ -102,30 +75,4 @@ export default {
}
}
</script>
<style>
.nav-list .nav-group:hover span,
.nav-list .nav-item:hover span,
.nav-list .nav-item.active span,
.nav-list .nav-group.active span,
.parent-name{
color: #FFFFFF !important;
}
.nav-list .nav-group.active .svg-icon-nav g [fill],
.nav-group:hover .svg-icon-nav g [fill],
.nav-item:hover .svg-icon-nav g [fill],
.nav-list .nav-item.active .svg-icon-nav g [fill],
.nav-active .svg-icon-nav g [fill],
.nav-parent .svg-icon-nav g [fill]{
fill: #FFFFFF !important;
/* color: #FFFFFF !important; */
}
.nav-list .q-focus-helper{
opacity: 0 !important;
}
.nav-active{
color:#FFF !important;
transition: color 0.2s ease;
background-color: #2A2A3C;
}
</style>
......@@ -126,7 +126,6 @@ import useMetaModule from '../../module/meta/metaModule'
import { useI18n } from 'vue-i18n'
import { getLangs } from "../../utils/tools";
import { SitLang } from '../../@types';
import {ref } from 'vue';
export default defineComponent({
setup() {
//TODO: 缺陷,验证与提交应该使用Form表单来完成,不应该进行单个验证
......@@ -146,7 +145,7 @@ export default defineComponent({
}
// 切换语言
const getLanguage = (val) => {
const getLanguage = (val:any) => {
locale.value = val.langLocale;
localStorage.setItem('lanuage', val.langLocale)
}
......
......@@ -36,9 +36,9 @@ const userActions = {
const loginUser = {}
setStoreState('user', 'userDetail', loginUser)
//清除token
const token = {}
const expireTime = 1 + new Date().getTime()
setStoreState('user', 'token', { ...token, expireTime })
// const token = {}
// const expireTime = 1 + new Date().getTime()
setStoreState('user', 'token', { })
//清除菜单权限
setStoreState('user', 'menuList', [])
......
......@@ -98,5 +98,5 @@ const useMenus={
return menus
}
}
export {useMenus, type Menu}
\ No newline at end of file
const MENU_KEYS='Current_Menu_Cehck'
export {useMenus, type Menu,MENU_KEYS}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment