EasyNav
EasyNav是一个现代化的企业内部导航门户系统,支持用户认证、快速检索链接和响应式设计,帮助企业集中管理各类系统和资源链接。
1. 项目背景 我们公司内部有非常多的页面需要管理,一直没有找到一款称心如意的软件 这款软件需要认证用户信息,可以通过注册登录或者企业微信登录或者其他方式方式进行认证 认证完成主页需要当前登录用户的用户名水印 以及简洁的主页,支持快速检索链接并且直接Enter快速访问 所以基于以上的契机就有了这款EasyNav 这里面有丝滑的流程,以及简单的操作方式。可以快速帮助公司内部进行提效#### 2. 项目明细# 公司导航门户一个现代化的企业内部导航门户系统,用于集中管理和展示公司各类系统和资源的链接。- 项目地址:https://github.com/starslink/EasyNav- demo地址:https://easynav.icu- 用户名:admin 密码:admin123## 功能特点- 🔐 用户认证与授权 - 邮箱注册与验证 <img width="1920" alt="image" src="https://github.com/user-attachments/assets/fe2cdb7c-7f97-49dd-8c65-6ed7b266354c"> - JWT token 认证 <img width="1920" alt="image" src="https://github.com/user-attachments/assets/c8491af7-0794-4847-a1f8-f012dbe83fc4"> - 管理员权限控制- 📱 响应式设计 - 支持桌面和移动设备 - 流畅的动画效果 - 现代化的 UI/UX- 🎯 导航管理 - 分组管理 <img width="1920" alt="image" src="https://github.com/user-attachments/assets/ab10a804-50c3-46cd-820e-4e509bfdf202"> - 二级分类 <img width="1920" alt="image" src="https://github.com/user-attachments/assets/56a26a07-c1db-4594-9f88-0ac53adca159"> - 链接排序 <img width="1920" alt="image" src="https://github.com/user-attachments/assets/5a6ad313-766f-446b-b334-e60878f7a4da"> - 灵活的搜索功能 <img width="1920" alt="image" src="https://github.com/user-attachments/assets/fe3e8272-115a-4394-9fc5-b42770f8b901">- 🛠 管理功能 - 分组 CRUD - 链接 CRUD - 二级分类管理 - 排序管理## 技术栈### 前端- React 18- TypeScript- Tailwind CSS- Framer Motion- React Icons- Axios- React Router### 后端- Node.js- Express- SQLite/MySQL- JWT- Nodemailer- bcrypt### 部署- Docker- Kubernetes- Nginx## 项目结构.├── backend/ # 后端项目│ ├── src/│ │ ├── db/ # 数据库相关│ │ ├── middleware/ # 中间件│ │ ├── routes/ # 路由│ │ └── utils/ # 工具函数│ └── docs/ # 文档├── frontend/ # 前端项目│ ├── src/│ │ ├── components/ # React 组件│ │ ├── hooks/ # 自定义 Hooks│ │ ├── services/ # API 服务│ │ └── types/ # TypeScript 类型└── k8s/ # Kubernetes 配置
## 快速开始### 环境要求- Node.js >= 18- npm >= 9- MySQL (可选,默认使用 SQLite)### 安装依赖bash# 后端cd backendnpm install# 前端cd frontendnpm install
### 环境配置1. 后端配置 (backend/.env)envPORT=3000JWT_SECRET=your-secret-keySMTP_HOST=smtp.gmail.comSMTP_PORT=587SMTP_SECURE=falseSMTP_USER=your-email@gmail.comSMTP_PASS=your-app-specific-passwordSMTP_FROM=Company Portal <noreply@company.com>FRONTEND_URL=http://localhost:5173# 数据库配置DB_TYPE=sqlite # 或 mysqlDB_NAME=database.sqlite# MySQL 配置(如果使用 MySQL)DB_HOST=localhostDB_PORT=3306DB_USER=rootDB_PASSWORD=root
2. 前端配置 (frontend/.env)envVITE_API_URL=http://localhost:3000/api
### 启动开发服务器bash# 后端cd backendnpm run dev# 前端cd frontendnpm run dev
## 部署### Docker 部署1. 构建镜像bash# 后端docker build -t nav-portal-backend ./backend# 前端docker build -t nav-portal-frontend ./frontend
2. 使用 Docker Compose 启动yamlversion: '3'services: frontend: image: nav-portal-frontend ports: - "80:80" depends_on: - backend environment: - VITE_API_URL=http://localhost:3000/api backend: image: nav-portal-backend ports: - "3000:3000" environment: - JWT_SECRET=your-secret-key - DB_TYPE=mysql - DB_HOST=db - DB_USER=root - DB_PASSWORD=root depends_on: - db db: image: mysql:8 environment: - MYSQL_ROOT_PASSWORD=root - MYSQL_DATABASE=nav_portal volumes: - mysql-data:/var/lib/mysqlvolumes: mysql-data:
### Kubernetes 部署项目包含完整的 Kubernetes 配置文件,位于 k8s/
目录:- frontend.yaml
- backend.yaml
- mysql-deployment.yaml 已经删除(需要自己安装数据库信息)
- ingress.yaml(或者traefik.yaml)
使用 kubectl 部署:bashkubectl apply -f k8s/
## 数据库设计### users 表sqlCREATE TABLE users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE NOT NULL, email TEXT UNIQUE NOT NULL, password TEXT, is_active BOOLEAN DEFAULT FALSE, verification_token TEXT, wework_userid TEXT UNIQUE, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, modified_at DATETIME DEFAULT CURRENT_TIMESTAMP);
### groups 表sqlCREATE TABLE groups ( id TEXT PRIMARY KEY, name TEXT NOT NULL, icon TEXT NOT NULL, sort_order INTEGER DEFAULT 100, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, modified_at DATETIME DEFAULT CURRENT_TIMESTAMP);
### subgroups 表sqlCREATE TABLE subgroups ( id TEXT PRIMARY KEY, name TEXT NOT NULL, group_id TEXT NOT NULL, sort_order INTEGER DEFAULT 100, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, modified_at DATETIME DEFAULT CURRENT_TIMESTAMP);
### links 表sqlCREATE TABLE links ( id TEXT PRIMARY KEY, title TEXT NOT NULL, subtitle TEXT NOT NULL, url TEXT NOT NULL, icon TEXT NOT NULL, group_id TEXT NOT NULL, subgroup_id TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, modified_at DATETIME DEFAULT CURRENT_TIMESTAMP);
## API 文档### 认证相关#### 注册POST /api/auth/registerContent-Type: application/json{ "username": "string", "email": "string", "password": "string"}
#### 登录POST /api/auth/loginContent-Type: application/json{ "username": "string", "password": "string"}
#### 验证邮箱GET /api/auth/verify-email?token=string
### 分组管理#### 获取所有分组GET /api/groupsAuthorization: Bearer <token>
#### 创建分组POST /api/groupsAuthorization: Bearer <token>Content-Type: application/json{ "id": "string", "name": "string", "icon": "string", "sort_order": number}
#### 更新分组PUT /api/groups/:idAuthorization: Bearer <token>Content-Type: application/json{ "name": "string", "icon": "string", "sort_order": number}
#### 删除分组DELETE /api/groups/:idAuthorization: Bearer <token>
### 链接管理#### 获取所有链接GET /api/linksAuthorization: Bearer <token>
#### 获取分组链接GET /api/links/group/:groupIdAuthorization: Bearer <token>
#### 创建链接POST /api/linksAuthorization: Bearer <token>Content-Type: application/json{ "id": "string", "title": "string", "subtitle": "string", "url": "string", "icon": "string", "group_id": "string", "subgroup_id": "string"}
#### 更新链接PUT /api/links/:idAuthorization: Bearer <token>Content-Type: application/json{ "title": "string", "subtitle": "string", "url": "string", "icon": "string", "group_id": "string", "subgroup_id": "string"}
#### 删除链接DELETE /api/links/:idAuthorization: Bearer <token>
## 安全性- 密码加密:使用 bcrypt 进行密码哈希- JWT 认证:使用 JWT 进行用户认证- CORS 保护:配置适当的 CORS 策略- 环境变量:敏感信息通过环境变量配置- SQL 注入防护:使用参数化查询- XSS 防护:React 默认转义 + CSP- 邮箱验证:新用户需要验证邮箱## 性能优化### 前端- 路由懒加载- 组件按需加载- 图片懒加载- 缓存静态资源- Gzip 压缩- Tree Shaking- 代码分割### 后端- 数据库索引- 连接池- 缓存策略- 请求限流- 响应压缩## 贡献指南1. Fork 项目2. 创建特性分支3. 提交改动4. 推送到分支5. 创建 Pull Request## 许可证木兰宽松许可证