SpringBoot+Vue3 企业云盘系统设计:文件上传+共享权限+收藏分类+5GB空间控制------从"网盘孤岛"到"企业知识底座"
🌐 文档地址 :http://ruoyioffice.com | 📦 源码1 :https://gitcode.com/zhouzhongyan/ruoyi-office-vben.git | 📦 源码2 :https://gitcode.com/zhouzhongyan/ruoyi-office.git | 📦 源码3 :https://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 文件主数据和二进制内容为什么分离?
系统里真正的"文件"其实有两部分:
- 二进制内容:真正的 PDF、Word、图片、视频。
- 元数据:名称、大小、后缀、类别、所有者、所属部门、共享状态等。
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 思路一致);小程序 / App 走 downloadFile + 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());
}
这里体现了三个企业级设计点:
- 单文件限制,防止大文件滥用。
- 用户级总空间限制,防止整体存储失控。
- 二进制内容交给统一存储服务,不在业务库里硬塞大对象。
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)
- 上传一个测试文档到"我的文件"。
- 新建一个文件夹并整理资料目录。
- 对某个文件发起分享,分别尝试"按人员分享"和"按组织分享"。
- 在分享弹窗里切换"仅查看/可管理"权限。
- 收藏一个常用文件,切换到"我的收藏"视图查看。
- 查看左侧空间统计和分类筛选效果。
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)体验建议
- 编译运行
ruoyi-office-uniapp,从菜单进入企业云盘页。 - 在「我的文件 / 共享文件 / 我的收藏」三个 Tab 间切换,确认列表与 PC 同源。
- 在「共享文件」中进入被共享的文件夹,用面包屑返回上级,核对与 PC「共享视图」是否一致。
- 点击 PDF 或 Word:H5 观察新窗口或直链打开;微信小程序 观察是否可调起系统文档预览。
- 下拉刷新列表,确认可手动重载。
结语
企业云盘真正的价值,从来不是"能存文件",而是把文件变成企业知识、协作和流程的底层载体。
RuoYi Office 这套设计之所以值得借鉴,不在于页面像不像某个成熟网盘,而在于它把企业真正关心的东西都做进去了:所有权、共享权限、继承策略、配额治理、多视图访问、跨端协同。也正因为如此,它才能继续往知识库、AI 助手、在线文档预览、审批附件联动这些更高层能力演进。
💡 想要体验 RuoYi Office 的强大功能?
🌐 在线演示 :http://ruoyioffice.com/web/(账号 admin / admin123)
💬 技术咨询 :添加💬 17156169080,备注「RuoYi Office」
⭐ 如果觉得不错,请给个 Star 支持一下!