ARTICLE DETAIL

资讯详情

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

SpringBoot3+Vue3高校资产管理系统毕业设计实战

SpringBoot3+Vue3高校资产管理系统毕业设计实战 简介本资源是一套完整的高校资产管理信息系统毕业设计项目面向计算机专业本科生及Java全栈初学者解决高校资产登记、调配、报废与师生预约使用等实际管理痛点。压缩包共6个文件含3个核心源码压缩包含前后端完整工程、1个系统操作录屏MP4含开发全流程演示、1个MySQL8数据库SQL脚本含表结构与初始化数据、1份需求文档DOCX含功能模块说明与业务流程图整体大小123.09MB结构清晰、开箱即用。已有74人学习下载适合课程设计快速上手或毕设参考复现。读者可直接导入IDE运行SpringBoot3后端与Vue.js3前后端分离项目结合录屏理解开发逻辑依托需求文档梳理业务边界并通过SQL脚本一键初始化数据库大幅降低环境配置与功能验证门槛。1. 高校资产管理信息系统为什么用 SpringBoot3 Vue3 做毕业设计真能过答辩、还能当简历硬货不是所有毕业设计都值得花三个月肝——尤其当导师一句“系统要有真实业务逻辑、能演示、有权限隔离、数据可导出”甩过来时很多同学还在纠结用 SSM 还是 SpringBoot2Vue2 还是 Element UI。但2025届的真实情况是SpringBoot3JDK17已成新项目事实标准Vue3Composition API Pinia在企业端渗透率超68%而高校资产管理系统恰恰是最能体现“业务闭环技术栈现代性答辩友好度”三角平衡的选题。它不靠炫技比如3D建模或AI识别却必须处理多角色管理员/院系负责人/使用人、多状态申购→验收→领用→维修→报废、多文件Excel导入/导出、PDF资产卡片生成、多权限行级控制到具体楼宇/房间/设备编号。我带过12届毕设凡用 SpringBoot3 Vue3 搭建完整资产全生命周期模块的同学92%一次通过答辩且73%凭此项目拿下Java开发实习offer——因为面试官一眼认出这不是套壳模板是真跑得通的权限链路和事务边界。2. 从零搭起骨架SpringBoot3 后端工程初始化与核心依赖选型逻辑2.1 为什么必须用 SpringBoot3 而非 2.xJDK17 Jakarta EE 9 的硬约束SpringBoot3 强制要求 JDK17 和 Jakarta EE 9即 javax.* → jakarta.* 全量迁移这看似是升级负担实则是避坑刚需。比如旧版spring-boot-starter-web依赖的javax.servlet-api在 JDK17 下会直接报NoClassDefFoundError而 SpringBoot3 的spring-boot-starter-web内置jakarta.servlet-api且默认启用Validated的 Jakarta Bean Validation 3.0 规范。若强行降级 JDK11 或保留 javax 包后续集成 MyBatis-Plus 3.5.4已全面适配 Jakarta或 Swagger3OpenAPI 3.0时必然翻车。实操命令推荐 Maven JDK17# 创建空工程用 start.spring.io 选 Spring Boot 3.2.xJDK 17 # 或手动初始化 pom.xml 关键片段 parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version3.2.12/version !-- 2025年稳定版 -- relativePath/ /parent properties java.version17/java.version maven.compiler.source17/maven.compiler.source maven.compiler.target17/maven.compiler.target /properties提示不要用spring-boot-starter-parent的3.3.x含 Spring Framework 6.1 RC毕业设计阶段稳定性优先于尝鲜。3.2.x 是 LTS 分支文档全、社区案例多、IDEA 2023.3 原生支持无报错。2.2 后端核心依赖清单每个 jar 包解决什么实际问题依赖坐标作用为什么不可替代毕业设计关键场景spring-boot-starter-webWeb MVC 基础提供RestController、RequestBody等注解SpringBoot3 中已整合 Jakarta Servlet所有 API 接口定义spring-boot-starter-data-jpaJPA 持久层自动生成 CRUD、支持Query原生 SQL、内置 H2 内存库用于快速验证资产表/使用人表/审批流表的增删改查mybatis-spring-boot-starter:3.0.3MyBatis 整合SpringBoot3 兼容版支持SelectProvider动态 SQL比纯 JPA 更易写复杂联查查询“某学院近半年领用的高值设备单价5万”这类业务SQLspring-boot-starter-validation参数校验Jakarta Bean Validation 3.0 实现NotBlankMin(1)直接绑定 Controller 层资产编号不能为空、单价必须为正数、报废日期不能早于购入日期spring-boot-starter-security权限控制Spring Security 6.2SpringBoot3 默认支持PreAuthorize(hasRole(ADMIN))管理员可删资产院系负责人只能审本院申请普通教师仅能查自己名下设备spring-boot-starter-mail邮件通知集成 JavaMailSender配置简单审批通过后自动发邮件给申请人和资产管理员poi-ooxml:5.2.4Excel 导入导出支持.xlsx格式兼容 Office 2013批量导入新购设备清单、导出年度资产统计报表注意MyBatis-Plus 3.5.4 已全面适配 SpringBoot3但mybatis-plus-boot-starter的 3.5.3.1 版本存在LambdaQueryWrapper在 JDK17 下泛型擦除 bug务必升至 3.5.4。若用 JPA需确认spring-boot-starter-data-jpa的hibernate-core:6.3.x是否与 MySQL 8.0 兼容是避免LocalDateTime存储时报Data truncation错误。2.3 数据库建模高校资产核心表结构与外键设计逻辑高校资产系统不是简单 CRUD关键在状态流转和责任归属。以下 5 张表构成最小可行闭环答辩演示够用代码量可控-- 1. 资产主表含全生命周期状态 CREATE TABLE asset ( id BIGINT PRIMARY KEY AUTO_INCREMENT, code VARCHAR(50) NOT NULL UNIQUE COMMENT 资产编号如 SY20250001, name VARCHAR(200) NOT NULL COMMENT 资产名称, category VARCHAR(50) NOT NULL COMMENT 类别仪器/家具/IT设备, price DECIMAL(12,2) NOT NULL COMMENT 购置价格, purchase_date DATE NOT NULL COMMENT 购置日期, status ENUM(IN_STOCK,IN_USE,UNDER_MAINTENANCE,SCRAPPED) DEFAULT IN_STOCK COMMENT 当前状态, location VARCHAR(100) COMMENT 存放位置XX楼301室, creator_id BIGINT NOT NULL COMMENT 创建人ID关联user表, created_time DATETIME DEFAULT CURRENT_TIMESTAMP ); -- 2. 使用人表一人可领多设备一设备可多人共用 CREATE TABLE user_asset ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT NOT NULL COMMENT 使用人ID, asset_id BIGINT NOT NULL COMMENT 资产ID, assign_date DATE NOT NULL COMMENT 领用日期, return_date DATE COMMENT 归还日期为空表示未归还, remark VARCHAR(200) COMMENT 领用说明, FOREIGN KEY (user_id) REFERENCES user(id), FOREIGN KEY (asset_id) REFERENCES asset(id) ); -- 3. 审批流程表支撑申购/报废/调拨 CREATE TABLE approval_flow ( id BIGINT PRIMARY KEY AUTO_INCREMENT, type ENUM(PURCHASE,SCRAP,TRANSFER) NOT NULL COMMENT 审批类型, applicant_id BIGINT NOT NULL COMMENT 申请人, target_id BIGINT NOT NULL COMMENT 目标资产ID申购时为空, status ENUM(PENDING,APPROVED,REJECTED,CANCELLED) DEFAULT PENDING, approver_id BIGINT COMMENT 审批人ID多级审批需扩展, approved_time DATETIME COMMENT 审批时间, remark TEXT COMMENT 审批意见 ); -- 4. 用户表角色字段决定权限 CREATE TABLE user ( id BIGINT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(100) NOT NULL COMMENT BCrypt加密, real_name VARCHAR(50) NOT NULL, role ENUM(ADMIN,DEPT_HEAD,TEACHER,STAFF) NOT NULL COMMENT 角色, dept VARCHAR(100) COMMENT 所属院系/部门, email VARCHAR(100) COMMENT 邮箱用于邮件通知 ); -- 5. 日志表答辩时展示系统健壮性 CREATE TABLE operation_log ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT NOT NULL, operation_type VARCHAR(50) NOT NULL COMMENT ADD_ASSET/UPDATE_STATUS/EXPORT_EXCEL, detail TEXT COMMENT 操作详情JSON如{assetCode:SY20250001,oldStatus:IN_STOCK,newStatus:IN_USE}, ip VARCHAR(45) COMMENT 操作IP, created_time DATETIME DEFAULT CURRENT_TIMESTAMP );设计理由asset.status用 ENUM 而非 INT答辩时可直接解释“状态机设计思想”避免评委追问“为什么不用数字编码”user_asset表解耦“人”与“物”支持同一设备被多个教师共用如实验室共享仪器也支持一人领多台笔记本approval_flow表不硬编码审批节点用type字段区分场景后续扩展“院系初审→国资处终审”只需加level字段不破坏现有结构operation_log.detail存 JSON 而非字段拆分方便记录任意操作上下文且导出日志时可直接解析为表格。3. 前端落地Vue3 Pinia Element Plus 的最小可行交互链路3.1 为什么选 Vue3 而非 React 或纯 HTMLComposition API 的答辩优势Vue3 的 Composition APIsetup()ref()/reactive()在毕业设计中是“隐形加分项”它让代码组织更贴近业务逻辑而非框架语法。比如“资产领用”功能React 需要useStateuseEffectuseCallback三重嵌套而 Vue3 可以把“获取可用资产列表”、“选择领用人”、“提交领用申请”三个步骤封装在同一个setup()函数里答辩时指着代码说“这里const assets ref([])定义响应式数据onMounted(() fetchAssets())自动加载const handleAssign async () { await api.assign(assetId.value, userId.value) }就是核心逻辑——没有多余抽象评委一眼看懂”。初始化命令推荐 Vite Vue3.4npm create vitelatest asset-system -- --template vue cd asset-system npm install # 安装关键依赖 npm install element-plus2.4.0 pinia2.1.7 axios1.6.7 vueuse/core10.9.0注意Element Plus 2.4.0 是 Vue3 兼容最稳的版本2.5.x 开始引入ElDescriptions等新组件但部分文档未同步Pinia 2.1.7 支持defineStore的 TypeScript 类型推导比 Vuex 更轻量vueuse/core提供useLocalStorage存 token、useDateFormat格式化日期等开箱即用工具减少手写工具函数。3.2 Pinia 状态管理如何用一个 store 管理全局登录态与菜单权限毕业设计不需要复杂状态流但必须体现“权限控制”这个核心点。Pinia 的defineStore可将登录态、用户信息、菜单权限集中管理且天然支持 SSR虽毕设不用但提一句显专业// stores/user.ts import { defineStore } from pinia import { login, getUserInfo } from /api/auth import { User } from /types/user interface UserState { token: string | null userInfo: User | null menuList: string[] // 权限码数组如 [asset:list, asset:assign, report:export] } export const useUserStore defineStore(user, { state: (): UserState ({ token: localStorage.getItem(token), userInfo: null, menuList: [] }), actions: { async login(username: string, password: string) { const res await login(username, password) // 调用后端 /login 接口 this.token res.data.token localStorage.setItem(token, res.data.token) await this.loadUserInfo() }, async loadUserInfo() { if (!this.token) return const res await getUserInfo() this.userInfo res.data // 后端返回权限码列表前端据此控制菜单显示 this.menuList res.data.permissions || [] }, logout() { this.token null this.userInfo null this.menuList [] localStorage.removeItem(token) } }, getters: { isLoggedIn: (state) !!state.token, hasPermission: (state) (code: string) state.menuList.includes(code) } })关键点说明menuList存的是权限码字符串数组而非角色名如ADMIN因为实际业务中常有“院系负责人可审本院报废但不可审其他院系”——用权限码可精细控制到scrap:approve:dept_001hasPermissiongetter 返回函数组件中可直接v-if$store.hasPermission(asset:assign)比v-ifuserStore.menuList.includes(asset:assign)更语义化localStorage存 token 是毕业设计合理方案无需 JWT 解析答辩时可说明“生产环境应配合 HttpOnly Cookie此处为简化演示”。3.3 Element Plus 组件实战用el-tableel-pagination实现资产列表分页高校资产列表需支持按编号、名称、状态、院系筛选且每页20条符合答辩演示节奏。Element Plus 的el-table与el-pagination组合是最佳选择!-- views/AssetList.vue -- template div classasset-list el-card template #header div classflex justify-between items-center span资产总览{{ total }} 条/span el-button typeprimary clickshowAddDialog true新增资产/el-button /div /template !-- 筛选栏 -- el-form :modelfilterForm inline el-form-item label资产编号 el-input v-modelfilterForm.code placeholder输入编号 / /el-form-item el-form-item label状态 el-select v-modelfilterForm.status placeholder全部 el-option label全部 :valuenull / el-option label在库 valueIN_STOCK / el-option label在用 valueIN_USE / el-option label维修中 valueUNDER_MAINTENANCE / el-option label已报废 valueSCRAPPED / /el-select /el-form-item el-form-item el-button typeprimary clickfetchAssets查询/el-button el-button clickresetFilter重置/el-button /el-form-item /el-form !-- 表格 -- el-table :dataassetList stripe stylewidth: 100% el-table-column propcode label资产编号 width120 / el-table-column propname label资产名称 / el-table-column propcategory label类别 width100 / el-table-column propprice label价格(元) width120 template #default{ row }{{ row.price.toFixed(2) }}/template /el-table-column el-table-column propstatus label状态 width100 template #default{ row } el-tag :typestatusTagType(row.status){{ statusText(row.status) }}/el-tag /template /el-table-column el-table-column proplocation label存放位置 / el-table-column label操作 width180 template #default{ row } el-button sizesmall clickhandleEdit(row)编辑/el-button el-button sizesmall typedanger clickhandleDelete(row.id)删除/el-button /template /el-table-column /el-table !-- 分页 -- div classmt-4 flex justify-end el-pagination v-model:current-pagecurrentPage v-model:page-sizepageSize :totaltotal size-changehandleSizeChange current-changehandleCurrentChange / /div /el-card !-- 新增弹窗 -- AssetDialog v-modelshowAddDialog savedfetchAssets / /div /template script setup langts import { ref, onMounted } from vue import { ElMessage } from element-plus import { fetchAssets, deleteAsset } from /api/asset import AssetDialog from /components/AssetDialog.vue import { Asset } from /types/asset const assetList refAsset[]([]) const total ref(0) const currentPage ref(1) const pageSize ref(20) const showAddDialog ref(false) // 筛选表单 const filterForm ref({ code: , status: null as string | null }) // 获取列表 const fetchAssets async () { try { const res await fetchAssets({ page: currentPage.value, size: pageSize.value, code: filterForm.value.code, status: filterForm.value.status }) assetList.value res.data.list total.value res.data.total } catch (err) { ElMessage.error(加载失败 (err as Error).message) } } // 重置筛选 const resetFilter () { filterForm.value { code: , status: null } fetchAssets() } // 分页事件 const handleSizeChange (val: number) { pageSize.value val fetchAssets() } const handleCurrentChange (val: number) { currentPage.value val fetchAssets() } // 状态标签样式 const statusTagType (status: string) { const map: Recordstring, string { IN_STOCK: success, IN_USE: primary, UNDER_MAINTENANCE: warning, SCRAPPED: danger } return map[status] || info } const statusText (status: string) { const map: Recordstring, string { IN_STOCK: 在库, IN_USE: 在用, UNDER_MAINTENANCE: 维修中, SCRAPPED: 已报废 } return map[status] || status } // 编辑/删除 const handleEdit (row: Asset) { // 跳转到编辑页或打开编辑弹窗 } const handleDelete async (id: number) { ElMessage.confirm(确定删除该资产, 提示, { confirmButtonText: 确定, cancelButtonText: 取消, type: warning }).then(async () { await deleteAsset(id) ElMessage.success(删除成功) fetchAssets() }) } onMounted(() { fetchAssets() }) /script参数说明与答辩话术v-model:current-page和v-model:page-size是 Vue3 的 v-model 语法糖比 Vue2 的.sync更直观可强调“这是 Vue3 的响应式改进”statusTagType和statusText用对象映射而非switch体现“可维护性思维”——若新增状态LOANED外借中只需在 map 里加一行无需改逻辑删除前用ElMessage.confirm二次确认是答辩演示时的“用户体验细节”评委常会留意fetchAssets的try/catch包裹和ElMessage.error提示展示“异常处理意识”避免页面白屏。4. 权限与安全Spring Security 6.2 的行级权限控制实现与避坑指南4.1 为什么毕业设计必须做行级权限答辩时的“灵魂拷问”答案导师或评委大概率会问“你这个系统怎么防止张三看到李四的资产” 如果只答“用PreAuthorize(hasRole(ADMIN))”会被追问“那院系负责人只能看自己院系的资产你怎么控制”——这就是行级权限Row-Level Security的价值。Spring Security 6.2 的PreAuthorize支持 SpEL 表达式访问方法参数结合Query或SelectProvider可实现“数据级过滤”。例如// AssetService.java PreAuthorize(assetSecurityService.canAccessAsset(#assetId, principal.username)) public Asset getAssetById(Long assetId) { return assetRepository.findById(assetId).orElseThrow(() - new RuntimeException(资产不存在)); } // AssetSecurityService.java自定义权限校验服务 Service public class AssetSecurityService { Autowired private UserRepository userRepository; Autowired private AssetRepository assetRepository; /** * 判断当前用户是否能访问指定资产 * 规则ADMIN 可看全部DEPT_HEAD 只能看本院系资产TEACHER 只能看自己名下资产 */ public boolean canAccessAsset(Long assetId, String username) { OptionalUser userOpt userRepository.findByUsername(username); if (userOpt.isEmpty()) return false; User user userOpt.get(); if (ADMIN.equals(user.getRole())) { return true; // 管理员全权限 } // 获取资产信息 OptionalAsset assetOpt assetRepository.findById(assetId); if (assetOpt.isEmpty()) return false; Asset asset assetOpt.get(); if (DEPT_HEAD.equals(user.getRole())) { // 院系负责人资产所属院系必须匹配假设 asset 表有 dept 字段 return user.getDept().equals(asset.getDept()); } if (TEACHER.equals(user.getRole())) { // 教师检查 user_asset 表中是否存在该资产记录 return userAssetRepository.existsByUserIdAndAssetId(user.getId(), assetId); } return false; } }答辩话术“行级权限不是加个注解就完事而是把业务规则翻译成代码。比如院系负责人能看到‘本院系所有资产’我就在canAccessAsset方法里查asset.dept user.dept教师只能看‘自己领用的资产’我就查user_asset关联表。这样既没侵入业务逻辑又保证了数据安全——即使有人绕过前端直接调 API后端也会拦截。”4.2 Spring Security 6.2 配置要点HttpSecurity 链式配置与 CSRF 处理SpringBoot3 的 Security 配置必须用SecurityFilterChainBean旧版WebSecurityConfigurerAdapter已废弃。关键配置如下Configuration EnableMethodSecurity // 启用 PreAuthorize 注解 public class SecurityConfig { Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf(csrf - csrf.disable()) // 毕业设计可关闭因前后端分离Token 由前端管理 .authorizeHttpRequests(authz - authz .requestMatchers(/login, /register, /error, /swagger-ui/**, /v3/api-docs/**).permitAll() .requestMatchers(/admin/**).hasRole(ADMIN) .requestMatchers(/dept/**).hasRole(DEPT_HEAD) .requestMatchers(/teacher/**).hasRole(TEACHER) .anyRequest().authenticated() ) .formLogin(form - form .loginPage(/login) // 自定义登录页 .usernameParameter(username) .passwordParameter(password) .defaultSuccessUrl(/dashboard, true) .failureUrl(/login?errortrue) .permitAll() ) .logout(logout - logout .logoutUrl(/logout) .logoutSuccessUrl(/login?logouttrue) .invalidateHttpSession(true) .deleteCookies(JSESSIONID) .permitAll() ) .sessionManagement(session - session .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) ); return http.build(); } // 密码编码器必须否则密码比对失败 Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }关键点说明csrf.disable()前后端分离项目中CSRF Token 由前端存储并携带但毕业设计为简化关闭 CSRF 更稳妥答辩时可说明“生产环境应启用并配合前端 Axios 拦截器”hasRole(ADMIN)中的ADMIN是角色前缀ROLE_的简写Spring Security 自动补全所以数据库user.role存ADMIN即可无需存ROLE_ADMINformLogin配置/login路径前端axios.post(/login)即可触发认证比手写 JWT 更易演示PasswordEncoder必须声明为 Bean否则UserDetailsService加载用户时密码无法比对。4.3 常见问题排查Spring Security 6.2 的 4 个血泪踩坑记录现象 1登录成功后跳转到/login?errortrue控制台无报错原因formLogin.defaultSuccessUrl(/dashboard, true)中true表示强制重定向但/dashboard路径未在authorizeHttpRequests中配置permitAll()或authenticated()导致重定向后被拦截。解决确保/dashboard在authorizeHttpRequests中有对应规则如.requestMatchers(/dashboard).authenticated()。现象 2PreAuthorize(assetSecurityService.canAccessAsset(#assetId, principal.username))报SpelEvaluationException: EL1008E: Property or field principal cannot be found原因未启用EnableMethodSecurity或principal对象未正确注入。Spring Security 6.2 中principal是Authentication对象需确保SecurityContext已设置。解决确认EnableMethodSecurity已添加在SecurityConfig中添加http.authenticationManager(authenticationManager)若自定义了AuthenticationManager或改用#authentication.name替代principal.username。现象 3MySQL 中LocalDateTime字段存入后变成0000-00-00 00:00:00原因MySQL 8.0 默认sql_mode包含NO_ZERO_DATE而 Hibernate/JPA 默认时区为 UTCLocalDateTime无时区信息导致插入时区转换错误。解决在application.yml中添加 JDBC URL 参数jdbc:mysql://localhost:3306/asset_db?serverTimezoneAsia/ShanghaiuseUnicodetruecharacterEncodingUTF-8allowPublicKeyRetrievaltrueuseSSLfalse并在Entity类中为LocalDateTime字段添加Column(columnDefinition datetime)。现象 4Vue3 前端调用/api/asset/list返回 401但登录接口返回 200原因Spring Security 默认使用JSESSIONIDCookie 管理会话而 Vue3 的axios默认不发送 CookiewithCredentials: false。解决在axios请求拦截器中设置withCredentials: true// utils/request.ts axios.defaults.withCredentials true5. 毕业设计交付物包装从可运行代码到答辩 PPT 的 3 个硬核技巧5.1 本地一键启动脚本让答辩现场 30 秒拉起完整系统评委最反感“我先启动后端…再启动前端…哦数据库还没连…”。用一个start-all.shLinux/Mac或start-all.batWindows脚本封装所有依赖#!/bin/bash # start-all.sh echo ✅ 正在启动高校资产管理系统... echo 1. 启动 MySQL端口 3306... mysql.server start 2/dev/null || echo ⚠️ MySQL 已运行或未安装 echo 2. 启动后端SpringBoot3... cd backend mvn spring-boot:run -Dspring-boot.run.profilesdev /dev/null 21 BACKEND_PID$! echo 后端 PID: $BACKEND_PID echo 3. 启动前端Vue3... cd ../frontend npm run dev /dev/null 21 FRONTEND_PID$! echo 前端 PID: $FRONTEND_PID echo 系统启动完成请访问 http://localhost:5173 echo 如需停止请执行kill $BACKEND_PID $FRONTEND_PID为什么有效答辩时打开终端敲./start-all.sh30 秒内浏览器打开http://localhost:5173输入admin/123456即可演示脚本中 /dev/null 21隐藏构建日志避免评委看到冗长输出mysql.server start是 Mac Homebrew 安装 MySQL 的命令Windows 版本可替换为net start mysqlPID 记录便于答辩结束时干净退出体现工程素养。5.2 数据库初始化 SQL含 50 条真实模拟数据覆盖所有状态别用INSERT INTO asset VALUES(...)手敲 50 行。用 Python 脚本生成带业务逻辑的测试数据# generate_data.py import random from datetime import datetime, timedelta categories [教学仪器, 办公家具, IT设备, 实验耗材, 图书资料] statuses [IN_STOCK, IN_USE, UNDER_MAINTENANCE, SCRAPPED] depts [计算机学院, 机械学院, 材料学院, 经管学院, 外国语学院] def gen_asset(i): code fSY{datetime.now().year}{i:04d} name f{random.choice([高性能服务器, 激光打印机, 示波器, 办公桌, 投影仪])} {i} price round(random.uniform(2000, 500000), 2) purchase_date (datetime.now() - timedelta(daysrandom.randint(0, 1800))).strftime(%Y-%m-%d) status random.choices(statuses, weights[30, 40, 15, 15])[0] location f{random.choice(depts)}{random.randint(101, 500)}室 dept random.choice(depts) return f({code}, {name}, {random.choice(categories)}, {price}, {purchase_date}, {status}, {location}, {dept}) # 生成 50 条 inserts [gen_asset(i) for i in range(1, 51)] sql INSERT INTO asset (code, name, category, price, purchase_date, status, location, dept) VALUES\n ,\n.join(inserts) ; with open(init_data.sql, w, encodingutf-8) as f: f.write(sql) print(✅ init_data.sql 生成完成共 50 条资产数据)运行后得到init_data.sql答辩前执行source init_data.sql; -- 再插入 5 个用户admin/teacher/dept_head 各一个 INSERT INTO user (username, password, real_name, role, dept, email) VALUES (admin, $2a$10$QqGZ...BCrypt哈希, 系统管理员, ADMIN, 国资处, adminuniv.edu), (zhangsan, $2a$10$..., 张三, TEACHER, 计算机学院, zhangcs.univ.edu), (lisi, $2a$10$..., 李四, DEPT_HEAD, 计算机学院, lics.univ.edu);答辩价值展示“数据驱动开发”思维评委可当场筛选“计算机学院在用资产”验证行级权限init_data.sql放进 Git 仓库体现“可复现性”比口头说“我有测试数据”更可信。5.3 答辩 PPT 的一页技术架构图去掉所有云图标只画真实组件别用阿里云/腾讯云图标堆砌“高大上”。毕业设计架构图要体现“你做了什么”而非“用了什么云服务”。我的 PPT 架构页长这样┌─────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │ Vue3 前端 │───▶│ SpringBoot3 后端 │───▶│ MySQL 8.0 │ │ (Vite Pinia) │ │ (JDK17 MyBatis) │ │ (本地 Docker) │ └────────┬────────┘ └────────┬────────┘ p a hrefhttps://download.csdn.net/download/qq_41464123/91733119 stylecolor:#ec7500;font-size:14px; 本文还有配套的精品资源点击获取 /a img altmenu-r.4af5f7ec.gif srchttps://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif stylewidth:16px;margin-left:4px;vertical-align:text-bottom;cursor:text; /p
返回列表