react_后台管理_项目

news/2024/7/24 1:06:06 标签: react.js, 前端, 前端框架

目录

1.运行项目

2. 项目结构

①项目顶部导航栏

②项目左侧导航栏

③主页面-路由切换区


本项目使用的是 react+ts+scss 技术栈。

1.运行项目

在当前页面顶部下载本项目,解压后使用编辑器打开,然后再终端输入命令:

npm i

下载依赖后,运行项目:

npm run start

此时项目运行起来了,可以再浏览器看到运行效果:

2. 项目结构

在做自己的项目时,对于这个项目目录我们只需要更改以下几个文件:

src目录下的文件和App.tsx,可以根据自己项目需要进行更改。

①项目顶部导航栏

header.tsx:

import logo from '../../assets/images/logo.svg';
import './header.scss';

function Header() {
  return (
    <div className="headerAll">
      <header className="headerBox">
       <img src={logo} alt="logo" className='headerImg' />
       <div className="headerText">后台管理系统</div>
       <div className="circle">zh</div>
      </header>
      <header className="headerBoxPlaceholder">
      </header>
    </div>
  );
}

export default Header;

header.scss:

.headerBox {
  width: 100vw;
  height: 56px;
  background-color: #FFF;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 9;
  min-width: 1140px;
  overflow: auto;

  .headerImg {
    width: 30px;
    height: 30px;
    position: absolute;
    top: 13px;
    left: 17px;
  }

  .headerText {
    font-size: 20px;
    position: absolute;
    top: 14px;
    left: 57px;
    font-weight: bold;
  }

  .navText {
    font-size: 16px;
    position: absolute;
    top: 16px;
    left: 218px;
  }

  .circle {
    width: 28px;
    height: 28px;
    line-height: 28px;
    border-radius: 50%;
    background-color: #19edcd;
    position: absolute;
    top: 14px;
    right: 14px;
    font-size: 12px;
    color: #FFF;
    text-align: center;
  }
}

.headerBoxPlaceholder {
  width: 100vw;
  height: 56px;
  box-shadow: 0px 4px 10px 0px rgba(78, 89, 105, 0.06);
}
②项目左侧导航栏

leftNavigation.tsx:

使用左侧导航图标使用svg,方便切换状态时换色,以及后期更改主题色。

import { ReactComponent as IconEducationGroup } from '../../assets/images/icon-education-group.svg';
import { ReactComponent as IconEduGroup } from '../../assets/images/icon-edu-group.svg';
import { ReactComponent as IconSet } from '../../assets/images/icon-set.svg';
import Arrow from "../../assets/images/icon-arrow.png";
import './leftNavigation.scss';
import { useState } from 'react';


function LeftNavigation() {
  // 左侧导航,一级按钮
  let navText = ['企业信息', '组织管理', '系统设置'];
  // 二级导航按钮,比如企业信息没有子级则二级导航为空数组
  let navTextChild = [[], ['组织架构', '部门设置'], ["日志设置", '通知设置']];
  // 当前选中的是哪个按钮,0是一级按钮,-1代表它没有子级选中的就是它本身
  const [currentBtn, setCurrentBtn] = useState([0, -1]);
  // 如果存在子层级,子层级展开还是合并,0合并,1展开
  const [childShow, setChildShow] = useState([1, 1, 1, 1]);

  /**
   * 判断按钮背景颜色
   * @param index 索引
   * @param flag 标志
   * @param indexChild 二级索引
   * @returns 返回className
   */
  function changeBGColor(index: number, flag: string, indexChild?: number): string {
    if (flag === 'one') {
      if (navTextChild[index].length === 0) {
        if (currentBtn[0] === index && navTextChild[index].length === 0) return 'first-order-tag bg-color'
      }
    } else {
      if (navTextChild[index].length !== 0 && currentBtn[0] === index && currentBtn[1] === indexChild) return 'first-order-tag bg-color'
    }
    return 'first-order-tag';
  }

  /**
   * 点击导航按钮进行页面切换
   * @param indexOne 一级索引
   * @param indexTwo 二级索引
   */
  function changeNavClick(indexOne: number, indexTwo?: number): void {
    if (navTextChild[indexOne].length === 0) { setCurrentBtn([indexOne, -1]) }
    if (indexTwo !== undefined && navTextChild[indexOne].length !== 0) {
      setCurrentBtn([indexOne, indexTwo])
    }

    if (indexTwo === undefined && navTextChild[indexOne].length !== 0) {
      updateItem(indexOne, childShow[indexOne] === 1 ? 0 : 1)
    }
  }

  /**
   * 只更新数组中的一个数值,数组[1]的值
   * @param indexFlag 一级索引
   * @param newValue 新的数值
   */
  function updateItem(indexFlag: number, newValue: number) {
    setChildShow(prevItems =>
      prevItems.map((item, index) => {
        if (index === indexFlag) {
          return newValue;
        }
        return item;
      })
    );
  }

  return (
    <div className="leftNavigationAll">
      <div className="leftNavigationBox">

        {navText.map((item, index) => (
          <div key={index}>
            {/* 第一层级 */}
            <div key={index} className={changeBGColor(index, 'one')} onClick={() => changeNavClick(index)}>
              <div className={currentBtn[0] === index ? 'navTextStyle-selected' : 'navTextStyle'}> {item}</div>
              {index === 0 && <IconEducationGroup className="icon-svg" stroke={currentBtn[0] === index ? '#00B498' : '#505553'} />}
              {index === 1 && <IconEduGroup className="icon-svg" stroke={currentBtn[0] === index ? '#00B498' : '#505553'} />}
              {index === 2 && <IconSet className="icon-svg" stroke={currentBtn[0] === index ? '#00B498' : '#505553'} fill={currentBtn[0] === index ? '#00B498' : '#505553'} />}
              {navTextChild[index].length !== 0 && <img alt="箭头" src={Arrow} className={childShow[index] === 1 ? 'arrow' : 'arrowHidden'}></img>}
            </div>

            {/* 第二层级 */}
            <div className={childShow[index] === 1 ? 'showDiv' : 'hiddenDiv'}>
              {navTextChild[index].length !== 0 && navTextChild[index].map((itemChild, indexChild) => (
                <div key={indexChild} className={changeBGColor(index, 'two', indexChild)} onClick={() => changeNavClick(index, indexChild)}>
                  <div className={(currentBtn[1] === indexChild && currentBtn[0] === index) ? 'navTextStyle-selected' : 'navTextStyle'}> {itemChild}</div>
                </div>
              ))}
            </div>
          </div>
        ))}

      </div>
    </div>
  );
}

export default LeftNavigation;

leftNavigation.scss:

.bg-color {
  background-color: #E8FAF8;
}

.showDiv {
  display: block;
}

.hiddenDiv {
  display: none;
}

.leftNavigationBox {
  z-index: 8;
  width: 200px;
  height: 100vh;
  min-height: 400px;
  background-color: #FFF;
  position: fixed;
  top: 0;
  left: 0;
  padding-top: 72px;
  padding-left: 8px;
  padding-right: 8px;
  box-sizing: border-box;

  .first-order-tag {
    width: 184px;
    height: 40px;
    // background-color: #E8FAF8;
    margin-bottom: 4px;
    border-radius: 6px;
    position: relative;
    cursor: pointer;

    &:hover {
      background-color: #F2F5F4;
    }

    .arrow {
      width: 12px;
      height: 12px;
      position: absolute;
      right: 16px;
      top: 14px;
      transform: rotateZ(180deg);
    }

    .arrowHidden {
      width: 12px;
      height: 12px;
      position: absolute;
      right: 16px;
      top: 14px;
      // transform: rotateZ(180deg);
    }

    .icon-svg {
      width: 18px;
      height: 18px;
      position: absolute;
      left: 12px;
      top: 11px;
    }

    .navTextStyle {
      font-size: 14px;
      color: #505553;
      position: absolute;
      left: 42px;
      top: 9px;
    }

    .navTextStyle-selected {
      font-size: 14px;
      color: #00B498;
      position: absolute;
      left: 42px;
      top: 9px;
    }
  }
}
③主页面-路由切换区

App.tsx:

所有路由写在这里,然后再左侧导航栏进行切换。

import './App.scss';
import Header from './pages/navigation/header';
import LeftNavigation from './pages/navigation/leftNavigation';
import Home from './pages/home';
import { Route, Routes } from 'react-router-dom'

function App() {
  return (
    <div className="App">
      <Header />
      <LeftNavigation />
      {/* 2. 使用路由组件,渲染路由,并且传入路由配置 */}
      <Routes>
        {/* comopnent替换为 element */}
        <Route path='/' element={<Home />}></Route>
      </Routes>

    </div>
  );
}

export default App;

home / index.tsx:

import './index.scss';
function Home() {
  return (
    <div className='homeBox'>
      <div className='homeBoxText'>应用主页</div>
    </div>
  );
}

export default Home;

以上就是项目的主要内容,可以将此项目当作基础框架进行二次开发。


http://www.niftyadmin.cn/n/5546821.html

相关文章

视觉导航和激光导航哪个更准确

关于视觉导航和激光导航哪个更准确的问题&#xff0c;并没有一个绝对的答案&#xff0c;因为这取决于具体的应用场景和需求。以下是对两者准确性的详细分析&#xff1a; 激光导航的准确性 优点&#xff1a; 高精度&#xff1a;激光导航通过激光扫描器发射激光束&#xff0c;…

python-23-零基础自学python open()和replace()函数运用

学习内容&#xff1a;《python编程&#xff1a;从入门到实践》第二版练习10-2 知识点&#xff1a; 打开文件&#xff0c;replace()替换文件内容&#xff0c;open(), 练习内容&#xff1a; 练习10-2:C语言学习笔记 可使用方法replace()将字符串中的特定单词都替换为另一个单…

gif压缩大小但不改变画质的最佳方法,7个gif压缩免费工具别错过!

你会不会也碰到过当你需要在自媒体平台上上传gif文件时&#xff0c;你会发现网页端最大限制为15MB&#xff0c;而手机端最大限制为5MB。那么如何在不不改变画质的同时压缩gif大小呢&#xff1f;如今&#xff0c;由于其特殊的动画以及快速传输的特点&#xff0c;gif文件已经成为…

整车行业APS项目难点(我的APS项目九)

一、成功案例少&#xff0c;从业人员少&#xff0c;顾问经验少。 二、服务器架构基本全自研&#xff0c;试错过程长&#xff0c;但生产环境对架构要求高。 三、数据体量大&#xff08;包含产品BOM&#xff09;&#xff0c;对数据质量要求极高、配置BOM技术壁垒高。 四、AI算…

垃圾回收器详解

Java 虚拟机&#xff08;JVM&#xff09;提供了多种垃圾回收器&#xff08;Garbage Collector, GC&#xff09;&#xff0c;以适应不同的应用需求。选择合适的垃圾回收器对于应用程序的性能和响应时间至关重要。本文将介绍四种主要的 Java 垃圾回收器&#xff1a;Serial GC、Pa…

服务器安装多个Tomcat

服务器安装多个Tomcat 因为申请了一个域名&#xff0c;然后想设置一个二级域名&#xff0c;让不同的二级域名访问到不同的项目&#xff0c;例如blog.booleandev.xyz访问到博客项目&#xff0c;www.booleandev.xyz访问到主页&#xff0c;网上找了找资料&#xff0c;发现一般是使…

“郑商企航”暑期社会实践赴美丽美艳直播基地开展调研

马常旭文化传媒网讯&#xff08;记者张明辉报道&#xff09;导读&#xff1a;2024 年 7 月 3 日&#xff0c;商学院暑期社会实践团“郑商企航”在河南省郑州市新密市岳村镇美丽美艳直播基地&#xff0c;展开了一场意义非凡的考察活动&#xff0c;团队成员深度调研了直播基地的产…

第二章 基础知识(4) - 日志记录

在默认日志级别&#xff0c;Blazor项目中默认提供如下日志记录提供程序&#xff1a; 在服务器上&#xff08;Blazor Server&#xff09;&#xff0c;日志记录仅发生在 LogLevel.Information 或更高级别的 Development 环境中的服务器端 .NET 控制台。 在客户端上&#xff08;B…