ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SpringBoot3+Vue3法律文书模板共享平台:从文件上传到权限审核的完整实践

SpringBoot3+Vue3法律文书模板共享平台:从文件上传到权限审核的完整实践 一个法律文书模板共享平台如果只看功能列表很多人会下意识觉得它就是一个文件上传下载系统用户注册登录上传 Word 或 PDF 模板管理员分类管理其他人搜索下载后台再配几个统计图表。但当这个想法被做成项目后真正的问题才会浮出来模板要不要审核模板更新后旧版本怎么办上传的文档能否按诉讼类型、法院层级或用途筛选下载权限是否要区分免费和付费文件被重复上传时该提示还是覆盖被别人恶意上传大文件时有没有限制。这些才是把“演示项目”拖进“可用环境”的绊脚石。这篇文章围绕一个具体实践路线来展开JAVA SpringBoot3 Vue.js3 MySQL 的法律文书模板共享平台。我不会只铺一张功能清单而是想讲清楚为什么这类系统不能按简单增删改查来做以及在实际开发中从数据库设计、文件上传到权限审核哪些环节最容易踩坑又应该按什么顺序排查。我先把结论放在前面做好法律文书模板共享平台重点不在“能传能下”而在流程边界是否想清楚。模板不是普通图片或压缩包它有版本、有审核、有分类、有下载场景还可能涉及用户上传内容的管理规范。只有先把这个认知框架搭出来后面的技术选型才不容易跑偏。1. 先判断清楚法律文书模板共享平台真正的问题不是增删改查1.1 “能传能下”只是及格线如果拿通用文件管理系统思维去设计你大概率会得到这样一套结构用户在前台上传文件管理员在后台能看到文件列表普通访客按分类浏览并下载。流程确实完整至少从表面看缺什么页面补什么页面登录注销、列表分页、新增修改删除全部都有。但这套设计一旦进入真实使用会立刻遇到一个尴尬场景用户把一份内容有误的起诉状模板上传了管理员根本没有审核入口模板表格里只有文件名和上传人没有适用的诉讼类别和文书用途用户后来改了内容重新上传后生成了一条新记录旧版本却再也找不到路径。所以把这类平台理解为“带文件附件的列表管理”是不合适的。文件本身虽然是承载物但真正需要管理的颗粒度应该是模板信息及其生命周期。什么意思呢核心不是“一个文件上传后提供下载链接”而是“一个模板被创建、审核、发布、更新、下架、再发布的完整过程”。这里有一个很常见的设计分歧是否允许用户直接替换文件如果允许那线上已经下载过的模板可能因为后台误操作而变成另一个内容审计上会有隐患。更好的做法是引入版本概念每次更新都生成新版本记录旧版本可以保留但不一定对外展示。后面在数据库设计部分我会再展开讲这个判断。1.2 决定平台质量的是能力和边界谁先定义好我观察到不少项目文档会把“共享”写得很宽泛好像所有注册用户都拥有相同权限。这种设计在工具型平台里有一定合理性但在法律文书模板这类场景里边界比功能更重要。原因很简单模板由谁上传、是否经过审核、谁能下载、谁能删除这些问题不解决平台开放得越早内容质量和法律风险就越难控制。所以你需要把“共享”拆成几个具体的权限动作浏览不需要登录就可以看公开模板列表还是必须先登录上传哪些角色能上传上传后直接可见还是进入待审核状态审核谁有权限通过或驳回模板驳回原因要记录吗下载普通用户和管理员是否下载同一个文件是否要记录下载人管理谁能修改分类、删除模板、强制下架删除是物理删除还是逻辑删除这些问题不是技术层面的复杂问题而是产品边界问题但它们会直接决定数据库表怎么建、接口怎么暴露、前端菜单怎么放。如果等到编码末期再补权限通常要改动大量接口成本反而比一开始就设计高出很多。2. 技术组合落地前最好先把 SpringBoot3 的版本雷区扫掉2.1 SpringBoot3 换成的不只是版本号看到项目标题里写的是 SpringBoot3而不是 SpringBoot2这说明项目采用了比较新的技术基线。SpringBoot3 依赖 Spring Framework 6 和 Jakarta EE 规范这意味着很多老项目里习惯用的 javax 前缀包名已经改成 jakarta 前缀。比如引入一个第三方工具有些老库还停留在 javax.servlet会导致应用启动时出现奇怪的类冲突或 404。另外SpringBoot3 默认要求 Java 17 及以上环境。你在本机装 Java 8打开项目后可能还编译不报错但运行时会出现 UnsupportedClassVersionError或者 Maven 插件版本不兼容。这里的经验是要先把统一 JDK 版本和 Maven 检查清楚再做模块拆分。如果使用 Spring SecuritySpringBoot3 现在的写法也偏向 lambda DSL而不是以前那种 antMatchers 链式配置。常见做法是http .authorizeHttpRequests(auth - auth .requestMatchers(/api/auth/**).permitAll() .requestMatchers(/api/templates/public/**).permitAll() .requestMatchers(/api/admin/**).hasRole(ADMIN) .anyRequest().authenticated() );这种写法不算复杂但如果你搜索到的资料停留在 Spring Security 5复制过来通常不能直接运行。所以这里我会建议一个非常保守的做法先只引入 Web 和 Security 依赖跑通一个默认登录逻辑再往业务里加接口权限。不要一上来就把 JWT、动态路由、数据权限全部混在一起否则报错时很难定位。MySQL 驱动也要注意。SpringBoot3 在依赖管理里默认支持的 MySQL 驱动坐标已变成com.mysql:mysql-connector-j。如果还在用老式依赖mysql:mysql-connector-java在某些版本组合下版本号可能被覆盖或无法加载驱动。建议显式写明连接参数比如字符集、时区、SSL 开关spring: datasource: url: jdbc:mysql://localhost:3306/legal_template?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue username: root password: your-password driver-class-name: com.mysql.cj.jdbc.Driver这里的serverTimezone特别重要。如果 MySQL 连接 URL 不设置时区在某些环境下会报连接超时或时间类型转换异常allowPublicKeyRetrievaltrue也是 MySQL 8 高版本连接时经常会遇到的参数。2.2 Vue3 与 Vue2 的真正差异在工程化组织前端选择 Vue.js3核心不应该是为了“新版本”。Vue3 带来的 Composition API 和script setup语法对中后台项目非常友好。这里想强调一个实际体验老项目用 Options API一段逻辑常常散落在 data、methods、watch 里Vue3 更建议把相关逻辑抽到一个 composable 函数中例如把“模板列表的查询条件、分页、加载状态”打包成一个useTemplateList方法页面组件会清爽很多。也就是说如果团队没系统写过 Vue3上来就套用 Vue2 的思维方式你会把 setup 当作 created 的升级版所有代码继续堆在地一个组件里。那样项目虽然能跑却没有享受版本升级带来的重构价值。对前端工程化来说比较合理的路径是用 Vite 创建 Vue3 TypeScript 项目这比老式 Webpack 配置更简单编译也更轻量。引入 element-plus 或同类组件库时按需引入部分组件避免一次性全量打包。状态管理优先考虑 Pinia。它不是推荐新库就一定要用但在中后台里token、用户信息、菜单权限这类全局状态很容易成为多页面共享的依赖Pinia 写法比 Vuex 简练TypeScript 支持也更好。路由守卫是一个必须关注的点。通常要处理“未登录跳转登录页”、“已登录但角色权限不够时拦截”这两层逻辑。2.3 MySQL 仍然是这个场景下的稳妥选择MySQL 在这个项目里的位置不是“数据库引擎秀肌肉”而是提供稳定的关系模型。法律文书模板有明显的分类属性和状态字段模板之间还有上传人、审核人、下载记录等关联关系用关系型数据库来处理这些结构天然比单纯用文档型数据库更方便。日常开发里表结构用 InnoDB 引擎字符集建议用 utf8mb4。如果只看到 MySQL 默认就能保存文件却没有区分文本内容和文件体会出现设计缺陷。从实践看文件本体不应该存进 MySQL 的 BLOB 字段尤其是模板可能会被反复上传、更新如果每次上传都把一个几 MB 的 Word 文件塞进 MySQL数据库体积会很快膨胀备份和恢复都变得痛苦。所以一般做法是数据库只存文件元数据比如原始文件名、存储路径、文件大小、扩展名、内容哈希真正的文件落盘到服务器目录或对象存储服务里。这样做还有一个好处后续想接 MinIO、阿里云 OSS 或腾讯云 COS 时只需要替换文件存储服务层的实现不需要改动整张表结构。3. 数据库怎么设计模板和文件不该搅在同一个表里3.1 模板主表与版本表为什么更新不能直接覆盖我在这类项目里最想强调的设计点是把模板信息与模板文件版本分开存储。也就是增加一张模板版本表或模板文件表主表记录模板公共维度版本表记录具体文件变化。主表可以这样理解id模板唯一标识title模板名称例如“民事起诉状民间借贷纠纷适用”category_id所属分类uploader_id上传人status草稿/待审核/已发布/下架audit_status审核状态可以并入 status 字段也可以单独保留方便追溯标签字段或标签关联表创建时间、更新时间版本表字段则更偏向文件idtemplate_idfile_namefile_pathfile_sizefile_md5download_countversion_nocreator_id创建时间这种设计的核心原因是更新一个法律文书模板不应该覆盖用户已有认知。很多律师或法务复用模板时会关注条款引用的法律依据是否最新。如果后台改一次内容就把原来的文件直接换掉那么已经下载过旧版本的用户再打开同一链接可能会得到不同内容甚至造成版本误用。引入版本表之后每次更新只是新增一条记录你可以决定默认下载最新版本也能保留历史版本在必要时候回退或溯源。如果只想做一个比较轻量的课程设计不一定需要复杂的版本回退界面但至少版本表能解决“同一模板多次上传后互相覆盖”的 bug。简单来说主表负责“模板是什么”版本表负责“这个模板现在对应哪个文件”。3.2 文件存储路径不要写成完整 URL文件存储路径也是一个容易踩坑的点。建议数据库保存相对路径而不是完整的本地绝对路径。比如保存/data/legal-template/2025/07/xxx.docx前端展示时通过接口拼接下载地址。这比直接把D:/upload/xxx.docx写死在数据库里灵活。后来更换服务器目录时只需要改配置文件的存储根路径。如果直接把绝对路径存进数据库迁移环境就会遇到大量脏数据。这里再强调一个更实际的边界上传目录和项目代码目录最好分离不能把模板文件直接放在 Spring Boot 的 classpath 或前端静态资源目录里。否则项目重新打包、服务重启或前端构建时不小心做了 clean文件可能被清掉。3.3 分类表、标签表和下载记录表分类表建议采用比较扁平的结构。法律文书模板类型多但也别把分类层级设计得过深。常见分类有起诉状、答辩状、上诉状、合同协议、律师函、公司法律文书等。你可以在分类表里预留 parent_id 支持两级或三级但不建议超过三层否则前端分类树、后端递归逻辑都会增加复杂度。标签表可以做成模板与标签的多对多关系比如“民间借贷”“劳动争议”“婚姻家庭”“合同审查”。这些标签主要服务于搜索和筛选。如果项目追求轻量也可以在第一版只保留分类字段等后期发现检索需求明显时再补标签体系。再有一点容易被忽略下载记录表看起来辅助却非常有用。它记录哪个用户、在什么时候、下载了哪个模板的哪个版本。对于管理员来说它可以发现热门模板对于审计来说它可以追踪文件分发行为。下载记录表还可以顺便解决一个问题用户下载模板后当模板疑似侵权或内容有误时后台可以知道有哪些用户受影响才能决定是否需要定向通知。典型的下载记录表字段可以包括id、template_id、template_version_id、user_id、下载时间、下载状态、IP 地址。这里 IP 字段不是必须但如果项目将来要考虑防刷或审计可以提前留一个。MySQL 建表时我记得一个细节是索引设计得跟着业务查询走。比如列表页高频按分类筛选、按标题模糊匹配、按状态加载那就在 category_id、status、title 这些字段上做索引。但如果全文搜索是硬需求LIKE %关键词% 在数据量大时并不高效。这个项目最好的迁移方向是引入全文搜索引擎例如 Elasticsearch但在课程设计阶段先用 MySQL 的 LIKE 查询跑通流程不比一上来引入重型中间件差。4. 核心流程上传校验、防路径穿越、下载响应头4.1 文件类型校验只检查后缀名是不够的法律文书模板常见的格式是 .doc、.docx、.pdf可能还有少量 .txt 格式。上传时默认不能什么都收。最常见的校验方式是检查扩展名但这只能挡住初级误操作不能防止伪造扩展名或文件伪装。一个更稳妥的检查链路是先看扩展名是否符合白名单再读取文件头做二次识别最后检查文件大小是否在配置范围。比如 .docx 文件本质是一个 Zip 容器文件头通常以PK开头.pdf 文件通常以%PDF开头老式 .doc 文件通常是 OLE 复合文档格式具体文件头依赖微软旧格式。这里最关键的理解是不要在 Controller 里把所有判断逻辑叠在一起。你应该把“文件内容是否合法”的逻辑放进一个独立的 FileValidateService方便后续替换识别策略或接入第三方文件识别能力。4.2 保存路径使用 UUID 重命名是防止路径穿越的第一步上传文件名如果直接拼接路径保存很容易出现路径穿越问题。比如用户上传的文件名叫../../shell.jsp如果后端没有处理可能就会写到一个非预期目录。从工程角度看这类问题不应该靠“过滤路径”解决而应该在保存逻辑里干脆不让用户控制文件名。常见做法是用 UUID 或时间戳重命名落盘文件原文件名只保留到数据库字段用于展示。这样保存路径永远是服务端生成的唯一名称从源头上避免路径拼接。后端保存伪代码的思路如下// 伪代码仅表述设计思路 String ext getExtension(originalFilename); String storeName UUID.randomUUID().toString().replace(-, ) . ext; Path targetPath Paths.get(uploadRoot, storeName); file.transferTo(targetPath);这里还提醒一个细节如果原始上传文件是 docx但用户实际传上来的是 HTML 伪装的 docx单纯改名不能解决文件内容风险。所以前面说的类型校验要有而且最好在文件落盘前先读取几 KB 检查。4.3 下载接口的响应头中文文件名乱码才让人头疼模板下载接口通常不是返回一个 JSON而是返回文件流。这里最基础的要求是设置好 Content-Type 和 Content-Disposition 响应头。如果响应头处理不对用户下载下来的文件名可能出现%E6%B0%91%E4%BA%8B%E8%B5%B7%E8%AF%89%E7%8A%B6.docx这种编码串或者在浏览器里变成乱码。实际项目里如果文件名是中文最好不要直接拼到 Content-Disposition 的 filename 里因为不同浏览器的标准兼容不一致。一个相对稳妥的写法是提供关键 filename* 参数并使用 UTF-8 编码Content-Disposition: attachment; filenametemplate.docx; filename*UTF-8%E6%B0%91%E4%BA%8B%E8%B5%B7%E8%AF%89%E7%8A%B6.docx当然如果你不希望暴露原始文件名也可以干脆用模板 ID 或 UUID 作为下载文件名再在前端把真实名称展示在页面上下载后由用户自行重命名。这个问题没有完美解关键是后端和前端要保持规则一致。4.4 上传参数配置先定好边界再谈并发Spring Boot 在上传文件时有一个默认大小限制不同版本的具体默认值可能有差异但在上传大文档时经常会报 MaxUploadSizeExceededException。所以需要显式设置上传文件大小spring: servlet: multipart: max-file-size: 20MB max-request-size: 50MB在这个基础上还需要写一个全局异常处理器把“文件过大”“文件类型不支持”“上传目录不存在”这类异常转成对前端友好的 JSON 信息。如果什么都不处理用户看到的可能是一整页错误堆栈体验非常糟糕。另有一个容易被忽略的地方上传时后端不要把文件对象全部读进内存。Spring 的 MultipartFile 在小于阈值时会进入内存超过阈值会转为临时文件。这个阈值可以通过配置调整但作为通用经验上传接口设计好后最好先用一个 10MB 的真实 Word 文件测试观察服务内存占用情况。否则一旦上线后多人同时上传大文件应用进程内存可能飙升甚至在服务器上直接触发 OOM。5. 权限与审核可以不够复杂但不能等到上线前再补5.1 最小可用 RBAC三种角色覆盖共享平台的典型需求在课程设计或个人项目里角色不用很多我建议先满足三种角色管理员负责分类维护、模板审核、下架违规内容、查看下载记录。注册用户浏览公开模板、下载模板、上传自己的模板。游客可浏览公开列表但不能下载或上传或根据需求决定是否允许。有观点认为既然要强调共享游客就不应该看到内容否则没法引导用户注册。这个决策需要产品侧来判断技术上无需纠结。但从数据权限角度这里有一个关键 filter普通用户访问未审核模板时后端直接返回 404 或无权限而不是把待审核内容暴露出去。也就是说模板列表和详情接口查询时必须根据角色决定要过滤掉哪些状态的数据。这个逻辑看起来只是多一个 SQL 条件但很多初学者把它放在前端菜单里判断以为隐藏了按钮就够了。前端隐藏不等于安全如果普通用户直接猜测接口地址依然能绕过页面拿到数据。所以后端查询必须在数据访问层就做状态过滤。5.2 状态机草稿、待审核、已发布、下架模板状态设计成什么样的流转我建议按这个基本状态机走草稿上传者刚创建可能还没有填写完整分类或标签。待审核上传者提交审核管理员可以审核。已发布审核通过后公开可见可下载。已下架管理员强制下架或上传者主动撤回。审核动作发生时建议在审核记录表里保存操作人、操作时间、审核意见。不要只是把状态从“0”改成“1”。理由是当上传者看到模板被驳回时需要一个原因提示。如果没有驳回原因用户只能猜测然后反复提交几次错误内容管理员又要反复审核。把这个流程画成一个简单的表当前状态、触发动作、目标状态。比如待审核状态下管理员点击“通过”状态变为已发布点击“驳回”状态变回草稿或专属的已驳回状态已发布状态下管理员可点击“下架”。这套规则可以帮助同事理解业务也方便写单元测试。5.3 登录认证建议从 Spring Security 或 Sa-Token 中选一个认证层面最简单的方案是做一个登录接口返回一个随机 token 存内存或数据库然后每个请求都自己验证。这在演示阶段没问题但随着权限逻辑变多你会发现自己写的验证过程越来越像一个“半吊子权限框架”。这类项目完全可以选一个成熟方案Spring Security 或 Sa-Token。如果团队熟悉 Spring用 Spring Security 比较顺如果追求写法和 SpringBoot3 都很匹配还想要简洁的登录鉴权和接口权限Sa-Token 也是一个可选项。但要注意引入安全框架会带来学习成本尤其是过滤链、匿名用户、会话策略这些概念。不同版本配置也不一样所以落地的原则是先用最少的配置把登录接口跑通再逐步加权限拦截。角色权限在数据库层面通常通过角色表和权限表完成用户归属一个或多个角色角色绑定数个权限点。在功能简单时可以只实现角色判断/api/admin/**必须是管理员。等到菜单多起来再考虑把权限点细化到按钮级别。6. 典型故障排查链路从页面报错一路查到文件落盘6.1 不要凭印象猜问题先确定故障在哪一层这个项目在前端、后端、数据库和文件存储之间横跳一旦出问题初学者最常见的做法是反复刷新页面、重新启动后端、清理浏览器缓存但问题并没有解决。我建议固化一条排查链路每次出问题都按顺序来看现象。页面是直接 404、401、403还是控制台报 CORS 错误上传后是前端报错还是后端错误日志里已经出现堆栈看请求。用浏览器开发者工具打开 Network 面板看请求 URL、请求方法、响应状态码。这一步能区分是前端路由问题还是后端接口问题。看后端日志。确认 Controller 是否被调用如果连日志都没有大概率是请求没进入后端或 URL 路径不对。看参数和输入。尤其是文件上传接口字段名是否和前端 FormData 一致。看依赖和版本。SpringBoot3 项目如果报 ClassNotFound 或 NoSuchMethodError优先检查版本兼容性。看资源。上传目录是否存在、是否有写权限、磁盘是否已满、MySQL 连接是否正常。最后看工具边界。某些浏览器插件的拦截、代理配置、跨域设置也会导致接口异常。比如一个常见例子前端上传时提示“请求失败”后端日志却什么也没有。排查后很可能不是接口问题而是 Nginx 或开发代理的请求体大小限制。前端直接访问后端没有这个问题但通过 Vite proxy 或 Nginx 反代就会被拦截。这种问题如果只盯着业务代码可能排查很久。6.2 上传成功但下载失败多半是路径或权限问题如果上传接口已经返回成功但下载接口报 404通常不用怀疑业务代码逻辑先按下面顺序排查数据库保存的 file_path 是否真实存在检查是否在不同环境里硬编码了路径。下载接口拼接文件路径时是取配置文件还是取库里的相对路径有没有出现反斜杠和正斜杠混用服务器上对应的 upload 目录是否可读Linux 环境下如果服务进程以低权限用户运行可能无法读取另一个用户创建的目录。文件是不是真的落盘了有时上传代码调用 transferTo 时因为没设置目录权限表面报成功实际只是临时文件被保存然后又被清理。为了少出问题下载接口要把文件不存在、文件名非法、目录不可读等情况转换成明确异常。比如返回“文件不存在或已下架”而不是直接给一段 500 堆栈。每个下载动作可以写日志记录模板 ID、用户 ID、耗时和文件大小这样后续排查会有很大帮助。6.3 登录后调接口仍然 403检查 Security 过滤链在前后端分离项目里登录后调用受保护接口经常遇到三种情况token 没有放到请求头、Security 配置没有放行某些接口、token 过期。前端在 axios 请求拦截器里通常会把 token 放在 Authorization 头config.headers.Authorization Bearer token很多同学漏了这一步后端拿不到 token 后返回 401前端又会跳到登录页。所以在排查时要先打开 Network 看请求头里有没有 Authorization如果没有问题大概率在前端拦截器。后端如果常见/api/admin/**这类请求被 403 拦截要看SecurityFilterChain里的规则顺序。Spring Security 中的规则遵循先匹配先生效如果你把/**写成 authenticated又写在/api/admin/**前面后面的管理员规则可能根本不生效。不同版本的写法和规则顺序也不同最好每一步都做断言式测试。6.4 列表数据不更新可能是缓存或查询条件模板列表更新后没有出现在前端很多时候并不是数据库没更新而是查询条件过滤了状态。例如上传后 status 还处于“待审核”普通用户视角的列表查询只发布状态当然看不到。这不是 Bug而是业务边界所以要给上传者增加一个“我上传的模板”入口让他们可以看到待审核记录。如果页面一直显示旧数据还有可能是前端拿数据比较后没有重新加载或者列表查询接口使用Cacheable缓存了旧结果。实际开发中建议后端在新增或审核操作后清理对应缓存或者在接口返回里带一个 version 字段前端用 version 判断是否需要刷新。7. 项目收尾之后更重要的是判断下一步迭代边界7.1 全文搜索与文档预览是最明显的两个升级入口如果一个基础版本已经跑通下一个阶段最值得做的不是无限制加新功能而是先把体验补齐。当前版本如果只靠标题 LIKE 搜索用户输入“民间借贷起诉状”可以查到标题匹配的内容但如果文档内容里写的是“民间借贷纠纷起诉状”而标题只是“民事起诉状”搜索效果就会欠缺。这里可以升级为 MySQL 全文索引或者引入 Elasticsearch。不过引入 ES 要谨慎因为法律文书模板共享平台的模板量在初期不见得很大如果只是几千条数据MySQL 配合合理的表结构和索引已经足够。先不要为技术上新而引入重型中间件。文档预览也是个常见需求。用户下载之前最好能在线预览但 Word 文档在线预览不像图片那么简单。常见思路是把 docx 转成 PDF 再在浏览器里预览。转换工具有很多例如 LibreOffice、OnlyOffice 或云服务转换能力。这个环节真正的难点不是“调用转换接口”而是转换后的文件命名、缓存策略、权限控制和并发处理。如果一次几十个用户同时触发转换而服务端是一台低配虚拟机资源占用可能直接把服务拖垮所以预览功能通常要加队列或限流。7.2 长期使用时日志、审计和备份比新菜单更重要我见过不少共享平台项目功能越加越多但问起“某个模板是什么时候被谁删除的”后台没有一个准确的记录。所以模板删除建议用逻辑删除而不是物理删除。在数据库表里保留一个 deleted 字段普通查询自动带上deleted 0。这样一旦发现误删还能恢复数据。日志要记录的不仅仅是异常信息还应该记录关键业务行为上传、审核、下载、删除、权限变更。这些日志不等于简单打印几行 log如果项目要放进生产环境需要考虑日志文件的切分、保留时长和敏感信息脱敏。MySQL 也需要定期备份模板数据虽小但下载记录和用户数据积累起来会越滚越大没有备份就是给自己埋雷。最后把上传目录的保留策略想好。模板平台不像聊天软件文件一旦被下载过就不能轻易从磁盘上删除。如果要做清理需要先判断该文件是否有下载记录、是否属于历史版本、是否被管理员强制删除。只根据文件创建时间清盘法律文书这种场景下很容易误删。7.3 从“能用”到“好用”核心是把不确定性消除掉这个项目做完后真正让人有成就感的时刻通常不是页面 UI 做了多精致而是当用户提交一份待审核模板时他能看到自己的模板处于什么状态当管理员驳回时他能看到为什么会驳回当用户反复下载同一个模板时后台能分辨这是重复下载还是模板名容易混淆。回到开头的判断法律文书模板共享平台本质上不是一套文件系统而是一个带审核、版本和溯源的共享流程系统。SpringBoot3、Vue3、MySQL 都只是实现它的工具。只要把这个底层认知理解了项目剩下的事情就是按照合理的流程边界去堆叠功能。这也是为什么我更建议从最小可用的“上传-审核-发布-下载”闭环出发先跑通再慢慢加上搜索、预览、统计。只要流程状态是清晰的后续每个功能都能自然地挂到这张图上不会轻易做成四不像。
返回列表