likes
comments
collection
share

「10」next-shopping:admin页面布局、用户组件调整

作者站长头像
站长
· 阅读数 2

我们先来调整一下C端页面,把app/(normal-layout) 改名叫app/(client-layout),虽然对实际没有影响,但是对开发者更好识别

我们现在可以把layout抽成通用的:

新建components/Layouts/ClientLayout.jsx

import { Navbar } from '@/components'

export default function Layout({ children }) {
  return (
    <>
      <Navbar />
      {children}
    </>
  )
}

这是客户端的页面通用布局,header部分需要nav

新建components/Layouts/DashboardLayout.jsx

export default function Layout({ children }) {
  return <div>{children} </div>
}

目前仅最简单的包一层,后面会添加NavFooter

新建components/Layouts/ProfileLayout.jsx

export default function Layout({ children }) {
  return <div>{children}</div>
}

这个个人中心也是组简单的布局

components/index.js中导出

export { default as Icons } from './share/Icons'
export { default as Loading } from './share/Loading'
export { default as DisplayError } from './share/DisplayError'
export { default as Navbar } from './Navbar'
export { default as User } from './User'
export { default as Cart } from './Cart'
export { default as Search } from './Search'
export { default as ClientLayout } from './Layouts/ClientLayout'
export { default as DashboardLayout } from './Layouts/DashboardLayout'
export { default as ProfileLayout } from './Layouts/ProfileLayout'

然后我们用ClientLayout来代替app/(main)/(client-layout)/layout.js的布局

'use client'

import { ClientLayout } from '@/components'
import { useRefreshToken } from '@/hooks'

export default function Layout({ children }) {
  useRefreshToken()
  return (
    <>
      <ClientLayout>{children}</ClientLayout>
    </>
  )
}

效果如下:

「10」next-shopping:admin页面布局、用户组件调整

然后我们新建app/(dashboard-layout)/layout.js

'use client'

import { DashboardLayout } from '@/components'

export default function Layout({ children }) {
  return (
    <>
      <DashboardLayout>{children}</DashboardLayout>
    </>
  )
}

新建app/(dashboard-layout)/dashboard/page.jsx

export default function Page() {
  return <div>这是管理页面</div>
}

效果如下:

「10」next-shopping:admin页面布局、用户组件调整

注销页面

我们先来实现两个通用组件BoxLinkArrowLink

新建components/share/BoxLink.jsx

import Link from 'next/link'
import { useRouter } from 'next/navigation'
import { Icons } from '@/components'

export default function BoxLink({ children, path, name }) {
  const router = useRouter()

  return (
    <div
      className={`transition-colors hover:bg-gray-200 px-3 ${
        router.asPath === path ? 'border-r-4 border-red-600' : 'border-r-4 border-white'
      }`}
    >
      <Link href={path}>
        <span className="flex justify-between mx-4 py-4 gap-x-2 border-t border-gray-300">
          {children}
          <span className="ml-auto mr-3">{name}</span>
          <Icons.ArrowLeft className="icon" />
        </span>
      </Link>
    </div>
  )
}

新建components/share/ArrowLink.jsx

import Link from 'next/link'
import { Icons } from '@/components'

export default function ArrowLink({ children, path }) {
  return (
    <Link href={path}>
      <span className="inline-flex items-center text-blue-400 text-sm max-w-max">
        <span className="uppercase">{children}</span>
        <Icons.ArrowLeft className="icon text-blue-400" />
      </span>
    </Link>
  )
}

然后我们来写退出登录组件:

新建components/Logout.jsx

import { useRouter } from 'next/navigation'
import { useDispatch } from 'react-redux'
import { userLogout } from '@/store/slices/authSlice'
import { Icons } from '@/components'
import alert from '@/utils/alert'

export default function Logout() {
  const dispatch = useDispatch()
  const router = useRouter()

  const handleLogout = () => {
    router.push('/')
    dispatch(userLogout())
    alert('success', '退出成功')
  }

  return (
    <div className="transition-colors hover:bg-gray-200 px-3">
      <div
        role="button"
        className="flex justify-between cursor-pointer py-4 gap-x-2 mx-4  border-t border-gray-300"
        onClick={() => handleLogout()}
      >
        <Icons.Logout className="icon text-black" />
        <span className="ml-auto mr-3">其他组织者</span>
      </div>
    </div>
  )
}

先在components/index.js中导出组件:

export { default as Icons } from './share/Icons'
export { default as Loading } from './share/Loading'
export { default as DisplayError } from './share/DisplayError'
export { default as Navbar } from './Navbar'
export { default as User } from './User'
export { default as Cart } from './Cart'
export { default as Search } from './Search'
export { default as ClientLayout } from './Layouts/ClientLayout'
export { default as DashboardLayout } from './Layouts/DashboardLayout'
export { default as ProfileLayout } from './Layouts/ProfileLayout'
export { default as ArrowLink } from './share/ArrowLink'
export { default as BoxLink } from './share/BoxLink'
export { default as Logout } from './Lagout'

现在来修改User组件,我们先看看当前的效果:

「10」next-shopping:admin页面布局、用户组件调整

修改components/User.jsx

import Image from 'next/image'
import Link from 'next/link'
import { useState } from 'react'

import { useSelector } from 'react-redux'
import { BoxLink, Icons, Logout } from './index'

export default function User() {
  const { user } = useSelector(state => state.auth)

  const [isOpen, setIsOpen] = useState(false)

  if (!user) {
    return (
      <div className="flex items-center gap-x-2 lg:border lg:border-gray-300 lg:rounded-md lg:py-2 lg:px-3 text-sm">
        <Link href="/login">
          <span className="flex items-center gap-x-1">
            <Icons.Login className="icon" />
            登录
          </span>
        </Link>
        <span className="hidden lg:block lg:border lg:border-gray-300 lg:h-6"></span>
        <Link href="/register">
          <span className="hidden lg:block px-2">注册</span>
        </Link>
      </div>
    )
  }

  return (
    <>
      <div className="lg:hidden">
        <Link href="/profile">
          <span>
            <Icons.User className="icon" />
          </span>
        </Link>
      </div>
      <div
        className={`hidden lg:cursor-pointer lg:relative lg:flex lg:rounded lg:p-1.5 lg:transition ${isOpen && 'bg-red-100'}`}
        onClick={() => setIsOpen(!isOpen)}
      >
        <Icons.User className="icon" />
        <Icons.ArrowDown className="icon" />
        <div
          className={` bg-white shadow-md rounded overflow-hidden absolute top-full left-0 w-60
                   border border-gray-100 ${isOpen ? 'block' : 'hidden'}`}
        >
          <BoxLink path="/profile" name={user.name} className="border-t-0">
            <div className="realative w-6 h-6">
              <Image src={'/avatar.png'} alt="user" width={200} height={200} />
            </div>
          </BoxLink>
          <Logout />
        </div>
      </div>
    </>
  )
}

主要是用BoxLink套了一层,省略很多代码,然后把退出登录的逻辑单独抽出来的Logout.jsx

代码地址:github.com/liyunfu1998…