SpringBoot+Vue3 企业云盘系统设计:文件上传+共享权限+收藏分类+5GB空间控制——从“网盘孤岛”到“企业知识底座”

SpringBoot+Vue3 企业云盘系统设计:文件上传+共享权限+收藏分类+5GB空间控制------从"网盘孤岛"到"企业知识底座"

🌐 文档地址http://ruoyioffice.com | 📦 源码1https://gitcode.com/zhouzhongyan/ruoyi-office-vben.git | 📦 源码2https://gitcode.com/zhouzhongyan/ruoyi-office.git | 📦 源码3https://github.com/yuqing2026/ruoyi-office.git | 💬 微信:17156169080(备注「RuoYi Office」)
很多企业都有文件管理需求,但真正用起来时,最常见的状态却是:制度文档在网盘、会议纪要在群文件、模板在个人桌面、部门资料在共享盘、审批附件在流程系统。文件明明都"在线化"了,知识却依然是碎片化的。RuoYi Office 的企业云盘不是单纯提供一个上传下载页面,而是通过"文件主数据 + 分享权限 + 收藏视图 + 存储统计"把文件管理变成了企业协同办公的底层能力。

▲ 企业云盘架构全景:前台以我的文件、共享文件、我的收藏为入口,后台由文件主表、权限表、收藏表和统一存储服务协同支撑,兼顾个人管理与团队共享

引言:企业云盘到底难在哪?

"上传个文件还不简单吗?"如果只是个人网盘,这句话没错;但一旦进入企业场景,问题马上变得复杂。

文件不只是"存进去"就完了:企业需要知道文件属于谁、归属哪个部门、是不是共享过、能不能收藏、谁有管理权限。

共享不是简单发链接:有些文件只允许查看,有些允许协作者管理;有些共享的是单个文件,有些共享的是文件夹,还要决定子目录是否继承权限。

空间和权限要可控:如果没有存储配额控制,企业云盘很快就会变成"员工私人影视库";如果没有所有者约束,任何人都能分享别人文件,安全边界会瞬间失守。

视图不是只有"我的文件":员工还会关心"别人共享给我的文件""我收藏过的高频文档",如果系统只有目录树,没有多视图切换,使用体验会很差。

文件系统必须和 OA 场景打通:制度、模板、公文附件、会议纪要、审批材料,最终都应该在企业统一平台里沉淀,而不是继续散落在多个系统。

典型问题 传统做法 后果
文件散落在多个系统 群文件、个人盘、共享目录混用 找不到最新版,知识碎片化
权限过粗 只有"能看/不能看" 协作效率低,安全边界也不清晰
共享无法继承 文件夹下子文件都要手动配权限 运维成本极高
无空间控制 文件随便传 存储失控,系统越跑越重
收藏能力缺失 靠路径记忆常用文档 高频资料反复找不到

本文就从 RuoYi Office 的企业云盘模块出发,拆解一套真正适合企业协作的文件管理设计。


一、业务设计:云盘不是网盘,而是协同底座

1.1 企业云盘的三类核心视图

RuoYi Office 没把云盘只做成一个目录页,而是抽象成三种视图:

视图 作用
我的文件 管理自己拥有的文件和文件夹
共享文件 查看别人共享给我的内容
我的收藏 快速访问高频使用文件

这三个视图解决的是三种完全不同的场景:

  • 管理自己的资料
  • 协同处理别人共享的资料
  • 快速复用常用资料

1.2 共享权限为什么必须独立建模?

企业云盘最核心的不是文件本身,而是"谁能以什么方式接触到文件"。

RuoYi Office 专门设计了 oa_file_permission 来表达共享关系:

字段维度 含义
分享对象 按人员 / 按组织
权限级别 仅查看 / 可管理
继承策略 是否向子文件夹继承
路径信息 共享路径、根分享 ID

这样共享就从"发一个文件链接"升级成了"有治理能力的协同授权"。

1.3 文件主数据和二进制内容为什么分离?

系统里真正的"文件"其实有两部分:

  1. 二进制内容:真正的 PDF、Word、图片、视频。
  2. 元数据:名称、大小、后缀、类别、所有者、所属部门、共享状态等。

RuoYi Office 通过 FileApi 把内容写入统一文件存储,再把元数据写入 oa_file_info。这种做法让云盘既能复用已有存储能力,又能在业务层实现权限和统计。


二、系统设计:三张表如何协同支撑企业云盘?

2.1 模块组成

企业云盘位于 OA → 企业云盘 目录下,核心由三部分组成:

模块 功能定位 面向角色
文件主表 描述文件/文件夹元数据 全体员工
共享权限表 描述分享对象和权限 文件所有者 / 协作者
收藏表 记录个人收藏关系 全体员工

2.2 核心设计决策

决策点 方案 理由
文件建模 文件和文件夹共用一张表 目录树结构统一,前端查询简单
fileType 0=文件夹, 1=文件 便于区分目录节点与叶子节点
存储内容 交给基础设施 FileApi 避免业务模块重复造存储轮子
空间限制 单文件 100MB、总空间 5GB 保证企业盘可控,不滥用
分享模型 独立权限表 便于支持多对象、多权限级别
收藏逻辑 独立表 + 物理删除 避免唯一索引冲突

2.3 数据结构关系

表名 职责 关键字段
oa_file_info 文件/文件夹元数据 parent_id, file_type, file_name, file_url, owner_id, is_shared
oa_file_permission 文件共享权限 file_id, share_type, target_id, permission, inherit_permission, share_path, root_share_id
oa_file_favorite 个人收藏 file_id, user_id

三、客户端功能实现:PC 主控台 + 移动端随身取用

企业云盘的「治理能力」(上传配额、批量整理、分享给组织/人员、文件夹继承等)主要体现在 PC 端的 Vue3 / Vben 管理中台;移动端则沿用同一套 OA 文件接口,把工作场景延伸到通勤、外出审批、现场确认等碎片化时间------一端治理、多端消费,避免再在微信群、个人盘里复制一份附件。

下方先覆盖 PC,再单独说明移动端能力边界与交互差异。

3.1 企业云盘主页面(PC)

▲ 企业云盘主页面:左侧展示存储空间、文件视图和按分类筛选,右侧是当前文件列表与操作区,同时具备"个人盘"和"团队协作空间"的双重属性

这个页面非常像大家熟悉的网盘产品,但它多了典型的企业属性:

  • 左侧不只是目录树,还有空间统计、共享文件、我的收藏、分类筛选。
  • 右侧不只是上传下载,还有打开、重命名、收藏、分享、删除等协作操作。
  • 文件所有者、是否共享、创建时间等元数据都直接可见。

3.2 文件分享弹窗

▲ 文件分享弹窗:支持按人员或按组织分享,权限可设为仅查看或可管理,并可选择是否向子文件夹继承权限,这才是真正适合企业协作的共享模型

从这个弹窗就能看出它不是"发个链接"那么简单:

  • 分享对象可以是员工,也可以是组织。
  • 权限分为"仅查看"和"可管理"。
  • 文件夹共享可以选择是否把权限继承到子节点。
  • 支持备注,方便说明分享背景。

3.3 为什么这一页比普通网盘更像企业系统?

因为普通网盘关注的是"你自己怎么存",企业云盘更关注的是"团队如何在安全边界内协作"。

3.4 移动端企业云盘(UniApp)

移动端实现位于 ruoyi-office-uniapp,页面 pages-oa/file ,调用与 PC 一致的后端能力(/oa/file/... 列表、共享树根、共享子路径、收藏列表等)。数据模型与安全策略与上文三张表完全一致 ,只是把界面压缩成适合做「单手操作」的流程。

▲ 移动端企业云盘:顶部 我的文件 / 共享文件 / 我的收藏 与 PC 三类视图对齐;列表区展示图标、文件名、所有者与大小,文件夹进入下级,文件可走下载或系统预览链路

移动端当前重点能力与交互要点:

能力 说明
三视图 Tab 与 PC「我的文件、共享文件、我的收藏」一一对应,切换 Tab 会重置导航栈并回到各视图根级,避免路径串台。
面包屑 进入子文件夹后展示可横向滚动的层级面包屑;点击某一节可快速回到上层,与共享目录下的 rootShareId / parentId 状态联动。
共享目录语义 与 PC 相同:根级拉共享清单,进入文件夹后调用「共享子文件」接口沿继承路径下钻;保证员工在手机上看到的树与桌面端同源。
收藏视图 根级列出收藏条目;若收藏的是文件夹,进入子层时退回「我的文件」侧查询接口罗列子节点,兼顾收藏入口与目录浏览。
下拉刷新 列表支持 scroll-view 下拉刷新,弱网下也便于让用户主动重试加载。
文件取用 文件夹点击进层级;文件点击在无地址时提示「暂不支持预览」。有 fileUrl 时:H5 可走新窗口打开直链(与 PC window.open 思路一致);小程序 / AppdownloadFile + openDocument,由系统预览器接管常见 Office / PDF(具体格式支持取决于运行平台)。
图标与可读性 按后缀区分 PDF、Office、图片、压缩包等与文件夹样式,在长列表里快速扫一眼即可定位类型。
深链 Tab(实现细节) 页面 onLoad 支持 `?tab=my

与 PC 有意区分的定位(可自行截屏配文说明):

  • 上传新建、分享弹窗(按人员/组织、查看/管理、继承子目录)、重命名删除、左侧空间环形统计与分类筛选等「管理类」交互,仍以 PC 为主;移动端不写第二套表单,可避免小屏校验与权限控件维护成本翻倍。
  • 若产品后续要在 App 内补齐「拍照上传」「转发到会话」等能力,仍可复用同一套 uploadFile 配额校验与 FileApi 存储,只要把入口收到独立页或浮动按钮即可。

▲ 共享视图下钻或面包屑导航:与 PC「共享路径」语义同源,便于在手机上核对他人共享的资料结构


四、后端核心实现

4.1 上传文件:先校验配额,再交给统一存储服务

FileInfoServiceImpl.uploadFile() 的开头几步非常关键:

java 复制代码
public Long uploadFile(MultipartFile file, Long parentId) throws Exception {
    long maxSize = 100 * 1024 * 1024; // 100MB
    if (file.getSize() > maxSize) {
        throw new IllegalArgumentException("上传文件不能超过100M,请压缩后上传");
    }

    Long userId = SecurityFrameworkUtils.getLoginUserId();
    long maxStorageSize = 5L * 1024 * 1024 * 1024; // 5GB
    Long tenantId = TenantContextHolder.getTenantId();
    Long usedSize = fileInfoMapper.selectTotalFileSizeByOwnerId(userId, tenantId);

    if (usedSize + file.getSize() > maxStorageSize) {
        throw new IllegalArgumentException("存储空间不足");
    }

    byte[] content = IoUtil.readBytes(file.getInputStream());
    String fileUrl = fileApi.createFile(content, file.getOriginalFilename(),
            "oa/cloud", file.getContentType());
}

这里体现了三个企业级设计点:

  1. 单文件限制,防止大文件滥用。
  2. 用户级总空间限制,防止整体存储失控。
  3. 二进制内容交给统一存储服务,不在业务库里硬塞大对象。

4.2 文件元数据建模:目录树、分类、所有者都在一张表里

上传完内容后,系统继续写入元数据:

java 复制代码
FileInfoDO fileInfo = new FileInfoDO();
fileInfo.setParentId(parentId);
fileInfo.setFileType(1); // 1表示文件(0表示文件夹)
fileInfo.setFileName(originalFilename);
fileInfo.setFileExtension(fileExtension);
fileInfo.setFileSuffix(fileSuffix);
fileInfo.setFileCategory(fileCategory);
fileInfo.setFileSize(file.getSize());
fileInfo.setFileUrl(fileUrl);
fileInfo.setOwnerId(userId);
fileInfo.setOwnerName(systemService.getUserNickname(userId));
fileInfoMapper.insert(fileInfo);

这说明云盘的关键不是"存了个 URL",而是把企业管理真正关心的元信息一起结构化存下来。

4.3 分享文件:只有所有者才能分享

FileShareServiceImpl.shareFile() 的第一步不是插入权限,而是先做所有权校验:

java 复制代码
public Integer shareFile(FileShareReqVO shareReqVO) {
    FileInfoDO fileInfo = fileInfoMapper.selectById(shareReqVO.getFileId());
    if (fileInfo == null) {
        throw ServiceExceptionUtil.exception(FILE_INFO_NOT_EXISTS);
    }

    Long currentUserId = SecurityFrameworkUtils.getLoginUserId();
    if (!fileInfo.getOwnerId().equals(currentUserId)) {
        throw ServiceExceptionUtil.exception(FILE_SHARE_NOT_OWNER);
    }
    // ...
}

这条规则非常重要。企业协作可以灵活,但权限边界不能模糊。

4.4 分享记录不仅保存权限,还要计算共享路径

这段逻辑决定了共享视图能不能正确展示目录层级:

java 复制代码
if (existingPermission != null) {
    existingPermission.setPermission(target.getPermission());
    existingPermission.setInheritPermission(shareReqVO.getInheritPermission());
    filePermissionMapper.updateById(existingPermission);
} else {
    FilePermissionDO permission = new FilePermissionDO();
    permission.setFileId(shareReqVO.getFileId());
    permission.setShareType(target.getShareType());
    permission.setTargetId(target.getTargetId());
    permission.setPermission(target.getPermission());
    permission.setInheritPermission(shareReqVO.getInheritPermission());
    calculateSharePath(permission, fileInfo);
    filePermissionMapper.insert(permission);
}

这不是简单的"授权一条记录",而是在为后续共享目录浏览、继承权限和根共享节点定位打基础。

4.5 共享路径计算:支持"共享文件夹里的子文件"正确定位

calculateSharePath() 体现了共享目录语义:

java 复制代码
private void calculateSharePath(FilePermissionDO permission, FileInfoDO fileInfo) {
    List<String> pathParts = new ArrayList<>();
    FileInfoDO current = fileInfo;

    while (current != null && current.getParentId() != 0) {
        pathParts.add(0, current.getFileName());
        FilePermissionDO parentShare = filePermissionMapper.selectByFileIdAndTarget(
                current.getId(), permission.getShareType(), permission.getTargetId());
        if (parentShare != null && parentShare.getRootShareId() == null) {
            permission.setRootShareId(current.getId());
            break;
        }
        current = fileInfoMapper.selectById(current.getParentId());
    }
}

这意味着员工点开"共享文件"时,不会只看到一堆散乱文件,而能沿着共享路径继续下钻。

4.6 收藏逻辑:物理删除比逻辑删除更稳

收藏取消时,代码选择了物理删除:

java 复制代码
public void unfavoriteFile(Long fileId, Long userId) {
    Long tenantId = TenantContextHolder.getTenantId();
    fileFavoriteMapper.physicalDeleteByFileIdAndUserId(fileId, userId, tenantId);
}

为什么这么做?因为收藏关系通常带唯一索引,如果只是逻辑删除,后面再次收藏时很容易撞唯一约束。这个细节非常工程化。


五、前端交互实现:企业云盘为什么更好用?

5.1 三种视图共用一个页面状态机

前端通过 viewMode 区分 list / shared / favorite

typescript 复制代码
const viewMode = ref<'favorite' | 'list' | 'shared'>('list');
const currentParentId = ref<number>(0);
const pathStack = ref<Array<{ id: number; name: string }>>([
  { id: 0, name: '我的文件' },
]);
const sharedFileState = ref({
  rootShareId: 0,
  parentId: 0,
});

这让"我的文件""共享文件""我的收藏"三种完全不同的业务视图,可以在一个统一页面里自然切换。

5.2 下载逻辑很克制:文件直接打开,文件夹禁止下载

typescript 复制代码
function handleDownload(row: FileApi.FileInfo) {
  if (row.fileType === 0) {
    message.warning('文件夹不支持下载');
    return;
  }
  if (row.fileUrl) {
    window.open(row.fileUrl, '_blank');
  }
}

这段逻辑很朴素,但非常符合用户心智:文件夹不是下载对象,文件才是。

5.3 存储统计让云盘更像"可治理资源"

页面里直接展示了:

  • 已用空间
  • 总空间
  • 文件数量
  • 共享文件数量

这种设计会让员工天然意识到"企业云盘不是无限资源",从产品层面就完成了一次轻量治理。


六、RuoYi Office 的创新设计

6.1 把"个人盘"和"团队协作盘"做在同一页面

不强迫用户在多个入口间切换,是企业级产品体验非常重要的一点。

6.2 分享权限不是布尔值,而是完整权限模型

按人员、按组织、仅查看、可管理、是否继承,这让云盘真正具备团队协作能力。

6.3 文件元数据天然带组织属性

所有者、部门、共享状态、分类都在元数据层显式保存,为后续统计、治理、审计和 AI 知识化打下基础。

6.4 云盘能力天生适合与 OA / AI 结合

一旦企业云盘建好,后续制度库、审批附件、知识库、AI 文档摘要、在线预览等能力都更容易叠加。


七、数据结构

7.1 oa_file_info

字段 含义 设计要点
parent_id 父节点ID 目录树基础
file_type 文件/文件夹 0=文件夹, 1=文件
file_name 文件名 展示与检索核心字段
file_category 文件分类 支撑按文档、图片、视频等筛选
file_url 文件地址 指向统一存储服务
owner_id 所有者 权限与统计基础
is_shared 是否共享 快速标记共享状态

7.2 oa_file_permission

字段 含义 设计要点
share_type 分享类型 按人员 / 按组织
target_id 目标对象 用户或部门标识
permission 权限级别 仅查看 / 可管理
inherit_permission 是否继承 文件夹共享关键字段
share_path 共享路径 共享视图导航基础
root_share_id 根共享节点 共享目录树定位

7.3 oa_file_favorite

字段 含义 设计要点
file_id 文件ID 指向被收藏文件
user_id 用户ID 个人收藏关系

八、技术亮点总结

设计要点 实现方式 价值
存储与业务解耦 FileApi + 元数据表 易扩展、易治理
共享权限建模 oa_file_permission 真正支持团队协作
文件夹权限继承 inheritPermission + 路径计算 降低授权维护成本
用户空间限制 100MB 单文件 + 5GB 总空间 防止滥用
收藏独立建模 oa_file_favorite 高频资料快速访问
多视图统一页面 我的文件 / 共享文件 / 我的收藏 用户体验更自然
移动端轻量化入口 UniApp:pages-oa/file,复用 OA 接口 + Tab/面包屑/refresh PC 治理、掌上查阅,避免多端重复建模

九、快速体验

9.1 操作路径

  • PC 企业云盘OA → 企业云盘
  • 移动端(UniApp) :工作台或 OA 菜单进入 企业云盘 (具体入口以各端菜单配置为准;页面路径 pages-oa/file

9.2 推荐体验流程(PC)

  1. 上传一个测试文档到"我的文件"。
  2. 新建一个文件夹并整理资料目录。
  3. 对某个文件发起分享,分别尝试"按人员分享"和"按组织分享"。
  4. 在分享弹窗里切换"仅查看/可管理"权限。
  5. 收藏一个常用文件,切换到"我的收藏"视图查看。
  6. 查看左侧空间统计和分类筛选效果。

9.3 源码仓库

类型 路径
前端 ruoyi-office-vben/apps/web-antd/src/views/oa/file
后端 ruoyi-office/yudao-module-oa/.../service/file
移动端 ruoyi-office-uniapp/src/pages-oa/file

9.4 移动端(UniApp)体验建议

  1. 编译运行 ruoyi-office-uniapp,从菜单进入企业云盘页。
  2. 在「我的文件 / 共享文件 / 我的收藏」三个 Tab 间切换,确认列表与 PC 同源。
  3. 在「共享文件」中进入被共享的文件夹,用面包屑返回上级,核对与 PC「共享视图」是否一致。
  4. 点击 PDF 或 Word:H5 观察新窗口或直链打开;微信小程序 观察是否可调起系统文档预览。
  5. 下拉刷新列表,确认可手动重载。

结语

企业云盘真正的价值,从来不是"能存文件",而是把文件变成企业知识、协作和流程的底层载体

RuoYi Office 这套设计之所以值得借鉴,不在于页面像不像某个成熟网盘,而在于它把企业真正关心的东西都做进去了:所有权、共享权限、继承策略、配额治理、多视图访问、跨端协同。也正因为如此,它才能继续往知识库、AI 助手、在线文档预览、审批附件联动这些更高层能力演进。


💡 想要体验 RuoYi Office 的强大功能?

🌐 在线演示http://ruoyioffice.com/web/(账号 admin / admin123)

💬 技术咨询 :添加💬 17156169080,备注「RuoYi Office」

如果觉得不错,请给个 Star 支持一下!

复制代码
相关推荐
bitt TRES10 小时前
springboot与springcloud对应版本
java·spring boot·spring cloud
T畅N14 小时前
审批流设计器(前端)
前端·elementui·vue·html·流程图·js
2301_7717172115 小时前
Spring Boot 自动配置核心注解
java·spring boot·mybatis
❀͜͡傀儡师16 小时前
Claude Code 命令大全:从入门到精通的完整指南
spring boot·claude code
吴声子夜歌17 小时前
Vue3——使用Mock.js
javascript·vue·mock.js
kybs199117 小时前
springboot租车系统--附源码68701
java·hadoop·spring boot·python·django·asp.net·php
过期动态18 小时前
MySQL中的约束
android·java·数据库·spring boot·mysql
wxin_VXbishe18 小时前
springboot新能源车充电站管理系统小程序-计算机毕业设计源码29213
java·c++·spring boot·python·spring·django·php
代码漫谈19 小时前
一文学习 SpringBoot 的 application.yml 配置,基于 Spring Boot 3.2.x
java·spring boot·spring·配置文件