import { defineComponent, ref, Transition, TransitionGroup, watch } from 'vue' import ModeSwitch from './ModeSwitch' import icons, { initIcons } from './icons' import { OhVueIcon, addIcons } from 'oh-vue-icons' import { PxHeadset, PxAddBox, PxCheck } from 'oh-vue-icons/icons' import useRouterStore from '@/useRouterStore' import useLayoutStore from '../useLayoutStore' import useUserStore from '@/user/useUserStore' import AvatarCircle from '@/user/AvatarCircle' initIcons() addIcons(PxHeadset, PxAddBox, PxCheck) const Item = defineComponent({ props: { name: { type: String, default: '' }, label: { type: String, default: '' }, idx: { type: Number, default: 0 }, active: { type: Boolean, default: false } }, emits: ['click'], setup(props, ctx) { const hover = ref(false) return () => ( <div class={ 'relative z-10 w-full h-[56px] flex flex-col justify-center items-center text-[13px] cursor-pointer transition-all font-bold ' + (props.active ? 'text-white' : hover.value ? 'text-white' : 'text-white/80') } onMouseenter={() => { hover.value = true }} onMouseleave={() => { hover.value = false }} onClick={() => { ctx.emit('click') }} > <OhVueIcon name={props.name} fill="white" scale={1.2} /> {props.label} </div> ) } }) export default defineComponent(() => { const showEdit = ref(false) const selected = ref(icons[0]) const router = useRouterStore() const layout = useLayoutStore() const user = useUserStore() const label = ref('') watch( selected, (val) => { label.value = val.label }, { immediate: true } ) return () => ( <Transition> {layout.ready && ( <div class="fixed left-6 top-1/2 -translate-y-1/2 h-[600px] z-30"> <div class="w-[56px] h-full rounded-[28px] bg-black/70 backdrop-blur flex flex-col justify-between items-center"> <ModeSwitch /> <div class="w-full h-[64px]" /> <div class="w-full h-0 flex-grow overflow-auto relative no-scrollbar"> <TransitionGroup> {layout.currentMode.pages.map((el, idx) => ( <Item key={idx} name={el.name} label={el.label} idx={idx} active={layout.state.currentPage === idx} onClick={() => { layout.state.currentPage = idx }} /> ))} </TransitionGroup> <Transition> {layout.currentMode.pages.length > 0 && ( <div class="absolute w-full h-[56px] rounded-lg bg-white/40 left-0 transition-all" style={{ transitionDuration: '.3s', top: `${layout.state.currentPage * 56}px` }} /> )} </Transition> </div> <div class="w-full h-4" /> <Item name="px-add-box" label="添加" onClick={() => { showEdit.value = true }} /> <Item name="px-headset" label="反馈" onClick={() => { router.path = 'settings-fallback' }} /> <div class="w-[56px] h-[56px] rounded-full border-white border-[2px] border-solid overflow-hidden cursor-pointer" onClick={() => { if (user.isLogin) { router.path = 'settings-user' } else { router.path = 'global-login' } }} > <AvatarCircle /> </div> </div> {/* 添加页面 */} <Transition name="page-adder"> {showEdit.value && ( <div class="absolute left-[70px] bottom-0 w-56 rounded-lg p-4 bg-white/40 backdrop-blur shadow-lg" v-outside-click={() => { showEdit.value = false }} > <input class="rounded bg-black/10 text-center text-sm w-full py-1" v-model={label.value} maxlength={2} /> <div class="flex flex-wrap gap-1 mt-2"> {icons.map((el) => ( <div class={ 'p-1 rounded cursor-pointer transition-all ' + (selected.value.name === el.name ? 'text-black/80 bg-white shadow' : 'text-black/60 hover:shadow hover:text-black/80 hover:bg-white') } onClick={() => { selected.value = { ...el } }} > <OhVueIcon name={el.name} fill="black" scale={1.3} /> </div> ))} </div> <div class="w-full mt-2 py-1 rounded-lg bg-white text-center text-sm shadow hover:shadow-lg transition-all cursor-pointer" onClick={() => { layout.currentMode.pages.push({ list: [], label: label.value, name: selected.value.name }) }} > <OhVueIcon name="px-check" /> 添加页面 </div> </div> )} </Transition> </div> )} </Transition> ) })