11. 企业后台管理系统(technical-architecture)

alt

1. 架构设计

alt

2. 技术栈说明

  • 前端: React@18 + Ant Design@5 + TypeScript + Vite
  • 初始化工具: vite-init
  • UI框架: Ant Design Pro (企业级UI组件库)
  • 后端: Supabase (BaaS服务)
  • 数据库: PostgreSQL (Supabase内置)
  • 认证: Supabase Auth
  • 文件存储: Supabase Storage
  • 状态管理: React Context + useReducer
  • 路由: React Router@6
  • HTTP客户端: Supabase Client SDK

3. 路由定义

路由 用途
/login 登录页面,用户身份验证
/register 注册页面,新用户注册
/dashboard 仪表盘页面,数据概览展示
/employees 员工管理页面,员工CRUD操作
/departments 部门管理页面,树形结构管理
/approvals 审批流程页面,流程发起和处理
/reports 数据报表页面,多维度数据分析
/settings 系统设置页面,权限和系统配置
/profile 个人中心页面,用户信息管理
/403 无权限页面,权限不足提示
/404 404页面,页面不存在提示

4. API 定义

4.1 认证 API

用户登录

POST /auth/v1/token?grant_type=password

Request:

参数名 参数类型 是否必填 描述
email string true 用户邮箱地址
password string true 用户密码

Response:

{
  "access_token": "eyJhbGc...",
  "token_type": "bearer",
  "expires_in": 3600,
  "refresh_token": "eyJhbGc...",
  "user": {
    "id": "user-id",
    "email": "xxxxxxx@example.com",
    "role": "admin"
  }
}

用户注册

POST /auth/v1/signup

4.2 员工管理 API

获取员工列表

GET /rest/v1/employees

Query Parameters:

参数名 参数类型 是否必填 描述
page number false 页码,默认1
pageSize number false 每页条数,默认20
search string false 搜索关键词
department string false 部门筛选
status string false 状态筛选

创建员工

POST /rest/v1/employees

Request Body:

{
  "name": "张三",
  "email": "zhangsan@example.com",
  "department_id": "dept-id",
  "position": "软件工程师",
  "phone": "xxxxxxx",
  "status": "active",
  "join_date": "2024-01-01"
}

4.3 部门管理 API

获取部门树

GET /rest/v1/departments?select=*&order=parent_id.asc.nullsfirst

创建部门

POST /rest/v1/departments

Request Body:

{
  "name": "技术部",
  "parent_id": "parent-dept-id",
  "manager_id": "manager-user-id",
  "description": "负责产品研发和技术创新"
}

4.4 审批 API

发起审批

POST /rest/v1/approvals

处理审批

PATCH /rest/v1/approvals?id=eq.approval-id

Request Body:

{
  "status": "approved",
  "comment": "同意申请",
  "processed_by": "user-id",
  "processed_at": "2024-01-15T10:00:00Z"
}

5. 服务器架构图

alt

6. 数据模型

6.1 数据模型定义

alt

6.2 数据定义语言 (DDL)

用户表 (users)

-- 创建用户表
CREATE TABLE users (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  email VARCHAR(255) UNIQUE NOT NULL,
  password_hash VARCHAR(255) NOT NULL,
  role VARCHAR(50) DEFAULT 'employee',
  status VARCHAR(20) DEFAULT 'active',
  last_login_at TIMESTAMP WITH TIME ZONE,
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
  updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- 创建索引
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_role ON users(role);

员工表 (employees)

-- 创建员工表
CREATE TABLE employees (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  name VARCHAR(100) NOT NULL,
  email VARCHAR(255) UNIQUE NOT NULL,
  department_id UUID REFERENCES departments(id),
  position VARCHAR(100),
  phone VARCHAR(20),
  status VARCHAR(20) DEFAULT 'active',
  join_date DATE,
  manager_id UUID REFERENCES employees(id),
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
  updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- 创建索引
CREATE INDEX idx_employees_department ON employees(department_id);
CREATE INDEX idx_employees_status ON employees(status);
CREATE INDEX idx_employees_manager ON employees(manager_id);

部门表 (departments)

-- 创建部门表
CREATE TABLE departments (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  name VARCHAR(100) NOT NULL,
  parent_id UUID REFERENCES departments(id),
  manager_id UUID REFERENCES employees(id),
  description TEXT,
  sort_order INTEGER DEFAULT 0,
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
  updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- 创建索引
CREATE INDEX idx_departments_parent ON departments(parent_id);
CREATE INDEX idx_departments_manager ON departments(manager_id);

审批表 (approvals)

-- 创建审批表
CREATE TABLE approvals (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  submitter_id UUID REFERENCES employees(id) NOT NULL,
  approver_id UUID REFERENCES employees(id),
  type VARCHAR(50) NOT NULL,
  title VARCHAR(200) NOT NULL,
  content TEXT,
  attachments JSONB,
  status VARCHAR(20) DEFAULT 'pending',
  comment TEXT,
  submit_time TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
  process_time TIMESTAMP WITH TIME ZONE,
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- 创建索引
CREATE INDEX idx_approvals_submitter ON approvals(submitter_id);
CREATE INDEX idx_approvals_approver ON approvals(approver_id);
CREATE INDEX idx_approvals_status ON approvals(status);
CREATE INDEX idx_approvals_type ON approvals(type);

权限配置表 (permissions)

-- 创建角色表
CREATE TABLE roles (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  name VARCHAR(50) UNIQUE NOT NULL,
  description TEXT,
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- 创建权限表
CREATE TABLE permissions (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  role_id UUID REFERENCES roles(id),
  resource VARCHAR(100) NOT NULL,
  action VARCHAR(50) NOT NULL,
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- 创建用户角色关联表
CREATE TABLE user_roles (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID REFERENCES users(id),
  role_id UUID REFERENCES roles(id),
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- 创建索引
CREATE INDEX idx_permissions_role ON permissions(role_id);
CREATE INDEX idx_permissions_resource ON permissions(resource);
CREATE INDEX idx_user_roles_user ON user_roles(user_id);
CREATE INDEX idx_user_roles_role ON user_roles(role_id);

权限设置

-- 授权匿名用户基本访问权限
GRANT SELECT ON departments TO anon;
GRANT SELECT ON employees TO anon;

-- 授权认证用户完整权限
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO authenticated;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO authenticated;

-- 创建行级安全策略
ALTER TABLE employees ENABLE ROW LEVEL SECURITY;
ALTER TABLE departments ENABLE ROW LEVEL SECURITY;
ALTER TABLE approvals ENABLE ROW LEVEL SECURITY;

-- 员工数据访问策略
CREATE POLICY "Employees can view own data" ON employees
  FOR SELECT USING (auth.uid() = id);

CREATE POLICY "Managers can view department employees" ON employees
  FOR SELECT USING (
    EXISTS (
      SELECT 1 FROM departments 
      WHERE departments.id = employees.department_id 
      AND departments.manager_id = auth.uid()
    )
  );

7. 关键技术实现

7.1 RBAC权限控制

  • 基于角色的访问控制模型
  • 支持菜单级权限和数据级权限
  • 动态权限验证,支持运行时权限变更
  • 前端路由守卫和后端API权限双重验证

7.2 树形结构处理

  • 部门管理采用邻接表模型存储树形结构
  • 支持无限层级嵌套
  • 提供递归查询获取完整树结构
  • 支持拖拽调整部门层级关系

7.3 表格组件优化

  • 基于Ant Design Table组件二次封装
  • 支持虚拟滚动处理大数据量
  • 集成搜索、筛选、排序、分页功能
  • 支持列配置和自定义渲染

7.4 表单验证机制

  • 统一的表单验证规则配置
  • 支持同步和异步验证
  • 实时验证反馈
  • 错误信息国际化支持

7.5 数据缓存策略

  • React Query进行服务端状态管理
  • 智能缓存和失效策略
  • 增量数据更新
  • 离线数据支持

7.6 性能优化

  • 代码分割和懒加载
  • 图片和资源压缩
  • CDN加速静态资源
  • 接口请求合并和防抖处理
20大项目拆解:从PRD到架构 文章被收录于专栏

想独立做出一个完整的项目却不知从何下手?本专栏是你的终极路线图。我们由浅入深,通过20个经典项目案例,手把手带你走过产品构思、需求撰写、功能设计、技术选型、架构搭建的全过程。从“音乐播放器”到“企业后台”,你将逐步建立对软件系统的完整认知,完成从理论到实践、从单一技能到复合能力的飞跃。

全部评论

相关推荐

从年头开始,就一直在忙忙碌碌,背八股,投简历,找实习。我人生的第一场面试是腾讯的实习岗面试,大概是三月份吧,那时候我lc几乎就没怎么刷,八股也是被的稀稀拉拉。一上来面试官还没让做自我介绍就甩了五道编程题给我做,但我一道都不会做,他没有开摄像头,我看着空白的函数段和在屏幕中那个窘迫的我,手心一直在冒汗,过了大概25分钟,他问我遇到了什么问题,我说“不好意思面试官,这里面的题,我哪一道都没有思路”就这样,我说完本次面试唯一的一句话后,结束了这场面试,关闭会议后我坐在电脑屏幕前发呆了很久,其实也没有感到难过,只是大脑一片空白后面也陆陆续续收到其他的一些面试,然后我不知道我哪来的自信,我就偏偏要去大厂,投递的全是叫得上名儿的大厂,结果不是笔试没过就是面试中答不上来,但是后面所有的面试官都很好,会耐心的指出我的不足或者可以改进的地方,让我每次面试后都有所进步。到了四月末,为了不拖我秋招的进度,我在boss上也开始投递一些中厂,然后顺利地拿到了offer,但我清楚的知道,我不属于那里,我不是没有资格去更高的平台,只是我还没有准备好而已。五月份我一个人从佛山出发,坐动车到了深圳这座城市,租到了满意的房子,买了一口小电锅,开始我的实习生活。深圳真的很奇幻,一边是密密麻麻的城中村,回家走在路上感觉能被电鸡创死,一边是高楼耸立的CBD,全是英文牌坊的商场,感觉每一次出地铁口都是在开盲盒。我开始逐渐适应一个人的生活,一个人自己给自己做饭,一个人吃烤肉,无聊的时候一个人去唱k,去逛展,甚至用dy开游戏直播,但有时候也会半夜emo躺床上在某个瞬间觉得自己咋这么惨入职第一天,看到自己工位上挂着“前端开发实习生-XXX”的时候,有一种不真实的感觉,我咋就开始上班了,像小孩儿装大人一样,第一个月收到工资还觉得哇撒好多,后面就在想快快给我涨工资。整个实习大概持续了三个月半吧,这里非常感谢我的mt,他不仅制定了简而有序的培养方案,还在工作与生活上给予了我非常多的支持,最开始的一个月,那个规划表里面真的是按天为单位去罗列我要干什么的,我完成一项就在上面打一个勾然后mt帮我去检验成果,后面他就慢慢放手,提醒我要开始进行思维的转换,要开始学着主动,自己去沟通,有风险只要及时暴露给他,他帮我兜底。这段时间我真的成长非常快,不仅仅是敲代码,像业务流程,技术选型,排查问题,遇到需要跨团队解决问题的能力都有所提升,到后面我好像就是一个“正式员工”了,干的还算不错,+2说如果转正要给我涨工资。mt经常与我one one一些我在工作上暴露的一些问题和他看到我进步的地方,真的是亦师亦友,从入职欢迎的那一顿饭到最后我离职欢送的那一段饭,前前后后我的mt请我吃了得五六顿饭了,平日也是带着我和前端同事一起吃饭,希望我能够在大家面前多刷刷脸,告诉我同事之间的关系也很重要,他忙的时候会给我发消息给我推荐哪里好吃。mt最后一次跟我one one就是我提离职准备秋招了,他希望我能够留下来,问我的意愿是怎么样的。“我还是说想去到一个更好的平台发展”他笑着点点头,和我们最后一顿饭碰杯一样说道“预祝你顺利拿到大厂offer,前程似锦”在公司的最后一天晚上,mt帮我记录了我在公司的最后几个瞬间,拍了好多照片,我带着这段回忆和经历重返了校园不知道大家有没有这种感觉 ,实习或者工作后回到学校会觉得不真实,好像自己已经离开了很久了不再属于这里了,外面被拷打了一番感觉岁月静好哈哈,回来去测mbti,从i/enfp变成了esfp?所以本就持怀疑态度的我再也信这玩意儿了。短暂歇了一段时间就开始准备秋招了,诚实讲相比于准备实习,秋招的整个阶段都比较浮躁,不知道是八股滚了一遍又一遍的原因还是时间线确实太长了,面试前其实不想做太多的复习。但是心态上就比实习那时候更加的平和,能过就过,不过拉倒,基本上有面试的中大厂一面都可以过,就是在二面上栽跟头。说实话秋招除了能力真的挺看运气的,看合不合面试官眼缘,问的问题是不是刚刚好都会答,但是越努力越幸运嘛,还是得在每次面试后总结面经,然后相应得拓宽自己的知识范围。期间加了几个秋招群,发现应聘大厂的真的是人才扎堆,硕士满天,92横飞,很担心最后横向自己的履历比不过别人。面试期间比较抓马的一幕是,我携程(上海)已经hr面后泡了1个月了,然后我在面哈啰的时候一个021(上海)开头的电话打过来,我以为是oc电话,但是又出于对面试官的尊重没有马上接听,面试结束后赶紧打了过去,结果是之前在boss上面投递的另外一家公司的笔试提醒......好在几天后携程真的打过来了,真是命运捉弄秋招人,没想到是秋招的第一家面的公司最后给到了offer,这时候已经接近12月了,终于是松了口气结束了秋招。最后总结一下吧,感觉写到这里回头看写的就像流水账,其实从选方向到实习到秋招,我非常感谢我坚持了我自己认为对的事情,身边没有一个同学选择前端,但是我觉得用户能直接与我做的界面流畅交互让我觉得有成就感,我也喜欢好看的东西,我乐意与UI打交道,我选择了。对于我拒绝了实习转正,别人也不明白明明待遇还不错为什么还要离开,我选择了。在我实习和秋招在大厂面试吃瘪的时候,有时会收到一些质疑,我选择继续,实习不行秋招,秋招不行春招。希望在未来,我也能坚持自己的想法,大步向前。
牛客80849854...:看完了,真不容易夸夸自己吧太棒了您
2025年终总结
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务