简介:这套银行内部办公系统基于SpringBoot 2.x开发,包含六大功能模块:公文管理(支持会议安排与公文列表)、资产管理(涵盖资产入库、查询、盘点)、档案管理(人事档案与合同归档)、辅助办公(图书借阅与管理)、个人中心(薪资查看、通讯录、工作计划)、系统管理(用户、角色、部门、菜单、字典配置)。权限体系采用RBAC模型,预置管理员、资产管理员、资产盘点员、主任、普通用户五类角色,后台可灵活分配菜单级和按钮级操作权限。提供完整登录界面、密码修改、主题切换功能,配套详细README.md文档,说明数据库配置方式、项目启动步骤及默认账号密码(如admin/123456)。所有截图覆盖各模块核心操作流程,包括新增、列表展示等典型页面,如‘资产列表-增加’‘合同管理-列表’‘角色管理-增加’等,便于快速上手或二次开发。技术栈主流稳定,适合作为银行类OA系统学习范例或定制化开发基础。
1. 这不是普通OA,是银行场景深度打磨的办公底座
你手上拿到的这套SpringBoot源码,表面看是个“带RBAC权限的六模块OA系统”,但真正用过银行内部系统的人都知道——它根本不是通用模板的简单拼凑。我参与过三家城商行OA系统重构,也帮省联社做过流程适配改造,见过太多所谓“银行版OA”只是把政府OA换个Logo、改几处字段就交付的半成品。而这套代码,从数据库字段命名到操作日志留痕方式,再到资产盘点时的双人复核逻辑、合同归档时的密级标识字段,处处透着银行场景的真实呼吸感。
核心关键词里,“银行OA系统”不是修饰语,而是设计原点;“SpringBoot源码”意味着你能看到每一行配置背后的取舍;“RBAC权限”在这里不是理论模型,而是嵌入到每个Controller方法上的@PreAuthorize("hasAuthority('asset:inventory:execute')")注解;“公文管理”和“资产管理”也不是并列功能,而是存在强业务耦合——比如一笔固定资产采购申请(资产管理模块),必须关联生成一份党委会会议纪要(公文管理模块),系统自动在会议纪要附件中挂载该资产的采购审批单PDF。这种细节,文档不会写,截图不会标,但代码里清清楚楚。
它适合谁?如果你是刚入职银行科技部的应届生,想快速理解银行内部系统怎么设计权限、怎么留痕、怎么防错,这套代码就是最好的教科书;如果你是外包公司的Java工程师,正为某支行定制一个资产盘点小程序,直接基于它的AssetInventoryService重写,比从零搭框架快三天;如果你是高校讲师,需要给学生讲SpringBoot+Shiro(或Spring Security)在真实金融场景中的落地,它的角色权限配置后台就是最鲜活的案例——管理员在“菜单管理”里勾选“资产盘点-执行按钮”,系统实时生成对应权限字符串,前端按钮随之显隐,整个过程没有魔法,全是可调试、可打断点的代码。
别被“六大模块”的说法迷惑。真正有价值的是它如何用一套权限引擎驱动所有模块:当你以“资产盘点员”身份登录,不仅看不到人事档案的入口,连公文列表页里的“发文”按钮也会消失;当你切换主题,不只是CSS变量替换,连打印样式表(@media print)都针对银行A4纸张做了边距优化;就连README.md里写的默认密码admin/123456,启动后首次登录强制修改,且新密码必须包含大小写字母+数字+特殊字符,长度8位以上——这根本不是SpringBoot Security的默认配置,而是银行信息科技部的安全基线要求。这些细节,才是它区别于网上千篇一律“学生管理系统”的本质。
2. 整体架构设计与银行场景适配逻辑
2.1 为什么选择SpringBoot 2.x而非3.x?技术栈选型的现实考量
项目明确采用SpringBoot 2.x(具体为2.3.12.RELEASE),这个选择背后有非常实际的银行IT环境约束。我接触过的省级农信社、城市商业银行,其生产环境JDK版本普遍卡在1.8(部分甚至仍是1.7),Web容器多为WebLogic 12c或Tomcat 8.5,数据库以Oracle 11g/12c为主,少量使用达梦DM8。SpringBoot 3.x要求JDK 17+、Jakarta EE 9+,这意味着升级需同步更换JDK、重构所有Servlet API调用、适配新版本数据库驱动——对银行而言,这不是技术升级,而是风险极高的系统迁移工程。
这套代码的依赖树清晰体现了向下兼容设计:
- spring-boot-starter-web 2.3.12.RELEASE → 内置Tomcat 9.0.52,完美兼容WebLogic 12c的Servlet 4.0规范;
- mybatis-spring-boot-starter 2.1.4 → 支持Oracle JDBC Driver 12.2.0.1,避免达梦数据库连接时出现ORA-00904: invalid identifier这类兼容性报错;
- spring-boot-starter-thymeleaf 2.3.12.RELEASE → 模板引擎未升级至Thymeleaf 3.1(需Jakarta EE 9),确保<th:fragment>等银行常用片段复用语法不报错。
更关键的是安全组件选型。银行对密码策略、会话超时、防暴力破解有硬性要求,代码中SecurityConfig.java未使用Spring Security 5.7+的Lambda DSL写法,而是保留传统的HttpSecurity链式配置:
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.invalidSessionUrl("/login?invalid=1")
.maximumSessions(3) // 同一账号最多3个并发会话
.maxSessionsPreventsLogin(true); // 达上限时阻止新登录
这段配置直接对应《银行业金融机构信息科技监管评级指引》中“用户会话管理”条款。而SpringBoot 3.x默认启用的CSRF Token自动注入,在银行内网环境中反而增加前端调试复杂度——这套代码通过csrf().disable()显式关闭,并在关键操作(如删除资产)中强制校验X-Requested-With请求头,既满足合规又兼顾开发效率。
2.2 六大模块不是平铺直叙,而是按银行组织架构分层建模
银行OA的模块划分逻辑,与互联网公司有本质区别。互联网讲“用户旅程”,银行讲“职责边界”。这套代码的模块设计严格遵循《商业银行内部控制指引》中“不相容职务分离”原则:
- 公文管理(模块1):聚焦“决策流”,会议管理对应党委会/行长办公会决议,公文列表对应收发文登记簿,所有操作留痕需满足《会计档案管理办法》15年保存要求;
- 资产管理(模块2):聚焦“实物流”,资产仓库对应固定资产台账,盘点功能内置“初盘-复盘-稽核”三级流程,数据变更需双人确认(
created_by+approved_by双字段); - 档案管理(模块4):聚焦“凭证流”,人事档案关联员工编号(非身份证号,符合《个人信息保护法》脱敏要求),合同管理强制填写“密级”(公开/内部/秘密/机密)和“保管期限”(10年/30年/永久);
- 辅助办公(模块3):聚焦“服务流”,图书管理不设借阅逾期罚款,但记录借阅频次用于采购分析——这是银行工会经费使用的审计依据;
- 个人中心(模块5):聚焦“权益流”,薪资管理仅展示税后实发金额,明细项(五险一金、个税)需单独申请权限查看,通讯录隐藏手机号,仅显示分机号;
- 系统管理(模块6):聚焦“管控流”,字典管理区分“系统级字典”(如资产类别)和“机构级字典”(如某支行自定义的合同类型),部门管理支持“虚拟部门”(如“数字化转型办公室”)用于流程审批,但不参与组织架构图渲染。
这种分层不是代码层面的包结构(com.bank.oa.module1),而是数据库设计层面的范式约束。例如sys_user表中org_id字段关联sys_dept,而sys_dept表有is_virtual标志位;asset_info表的category_code外键指向sys_dict,但sys_dict表有dict_type='ASSET_CATEGORY'和dict_type='BRANCH_CONTRACT_TYPE'两种类型。这种设计让同一套RBAC权限引擎能精准控制不同层级的数据可见性——这才是银行OA真正的技术难点。
2.3 RBAC权限体系的银行化落地:从菜单到按钮的穿透式控制
银行对权限的要求,远不止“能看到什么页面”。这套代码的RBAC实现,完成了三个关键穿透:
第一层穿透:菜单级权限(URL路由控制)
SysMenuController返回的菜单树,不是静态JSON,而是动态查询sys_role_menu关联表:
SELECT m.* FROM sys_menu m
INNER JOIN sys_role_menu rm ON m.menu_id = rm.menu_id
WHERE rm.role_id = ? AND m.status = '0'
但关键在m.status = '0'——菜单状态字段区分“启用”(0)、“停用”(1)、“测试”(2)。银行系统上线后,常需临时关闭某个功能(如因监管检查暂停合同在线签署),无需重启服务,只需在后台将对应菜单状态改为1,所有角色立即失效。截图6-系统管理-菜单管理-列表.png中“状态”列的开关按钮,就是为此设计。
第二层穿透:按钮级权限(前端指令控制)
Thymeleaf模板中大量使用自定义指令:
<button th:if="${@permission.hasPermission('asset:inventory:execute')}"
type="button" onclick="startInventory()">开始盘点</button>
@permission是自定义Bean,其hasPermission方法查询sys_role_button表,但查询逻辑包含银行特有规则:
- 若当前用户角色为“资产盘点员”,则自动继承“资产管理员”角色的所有按钮权限(角色继承关系在sys_role表的parent_id字段体现);
- 若按钮权限码含_AUDIT后缀(如asset:info:audit),则强制校验用户是否在sys_audit_team表中(稽核部门白名单)。
第三层穿透:数据级权限(SQL动态过滤)
这才是银行权限的核心。AssetService.list()方法不直接调用Mapper,而是先执行:
String dataScopeSql = dataScopeFilterService.buildDataScopeSql(
"t", // 表别名
"dept_id", // 数据归属字段
"user_id" // 当前用户ID
);
// 生成类似:AND t.dept_id IN (SELECT dept_id FROM sys_user_dept WHERE user_id = ?)
dataScopeFilterService根据用户角色动态拼接SQL条件:
- 普通用户 → 只能看到本部门资产;
- 主任 → 可见本部门及下辖二级机构资产;
- 管理员 → 可见全行资产(但sys_user表中is_super_admin='N',避免误操作);
- 资产盘点员 → 可见所有机构,但仅限“盘点中”状态的资产(status='INVENTORYING')。
这种三层穿透,让权限控制从“能不能看”深入到“能看到哪些数据”“能对哪些数据执行什么操作”,完全匹配银行《信息系统权限管理规范》要求。截图2-资产管理-资产列表-列表.png中右上角的“导出”按钮,普通用户点击会提示“无导出权限”,而主任点击则弹出“导出范围选择”对话框——这就是按钮级与数据级权限协同的结果。
3. 核心模块实现细节与银行特有逻辑解析
3.1 公文管理:会议与公文的双向强耦合设计
银行公文管理最易被忽视的痛点,是会议决议与后续执行的跟踪断层。这套代码用两个创新设计解决:
第一,会议管理模块的“决议事项”子表
meeting_info主表存储会议基本信息(时间、地点、主持人),而meeting_resolution子表存储每条决议:
CREATE TABLE meeting_resolution (
id BIGINT PRIMARY KEY,
meeting_id BIGINT NOT NULL, -- 关联会议
content VARCHAR(2000), -- 决议内容(如“同意采购XX设备”)
assign_to_dept VARCHAR(50), -- 责任部门编码(如“ZCGLB”资产管理部门)
deadline DATE, -- 完成时限
status VARCHAR(20) DEFAULT 'PENDING' -- 状态:PENDING/DOING/DONE/CLOSED
);
关键在assign_to_dept字段——它不是自由文本,而是关联sys_dept.code。当用户在会议管理页点击“生成公文”,系统自动创建一条公文记录,并将meeting_resolution中assign_to_dept='ZCGLB'的决议,填充到公文正文的“承办部门”字段,同时在doc_info表中建立meeting_resolution_id外键。这样,后续在公文列表页点击某条公文,可直接跳转到原始会议决议项,实现闭环追溯。
第二,公文列表的“状态机”驱动
银行公文流转有严格时效要求(如收文7日内办结),代码中DocStatusEnum定义了8种状态:
public enum DocStatusEnum {
DRAFT("草稿"),
SUBMIT("已提交"),
APPROVING("审批中"),
APPROVED("已批准"),
REJECTED("已退回"),
EXECUTING("执行中"),
EXECUTED("已执行"),
ARCHIVED("已归档");
}
状态变更不是简单更新字段,而是触发事件:
- 当状态从SUBMIT变为APPROVING,自动向sys_dept_head表中该部门负责人发送站内信;
- 当状态为EXECUTING且超过deadline,每日9:00定时任务扫描,向责任人推送企业微信提醒;
- 当状态变为ARCHIVED,自动调用ArchiveService.archiveToDMS()方法,将公文PDF上传至银行文档管理系统(DMS),并写入dms_file_id字段。
截图1-公文管理-公文列表-列表.png中每行末尾的“办理进度”条,就是根据status和deadline动态计算的:Math.min(100, (int)((System.currentTimeMillis() - createTime) / (deadline.getTime() - createTime) * 100))。这种设计让公文状态不仅是标记,而是驱动业务动作的引擎。
3.2 资产管理:盘点流程的银行级风控逻辑
银行固定资产盘点不是简单的“数数量”,而是涉及责任认定、价值重估、处置审批的完整风控链条。这套代码的盘点模块(AssetInventoryController)实现了三重校验:
第一重:盘点计划预审
InventoryPlanService.createPlan()方法在创建盘点计划时,强制校验:
- 计划周期不能跨年度(银行会计年度为1月1日至12月31日);
- 盘点范围必须指定“机构编码”,且该机构在sys_dept表中is_asset_managed='Y'(即被授权管理资产);
- 计划负责人必须是“资产盘点员”角色,且其user_id存在于sys_inventory_team表中(盘点小组成员白名单)。
第二重:现场盘点双人确认
InventoryRecordService.saveRecord()接收前端提交的盘点记录,但关键逻辑在:
// 校验盘点人与复核人是否为不同用户
if (record.getCheckerId().equals(record.getOperatorId())) {
throw new BusinessException("盘点人与复核人不能为同一人");
}
// 校验复核人是否在盘点小组白名单中
if (!inventoryTeamService.isInTeam(record.getCheckerId(), planId)) {
throw new BusinessException("复核人不在本次盘点小组中");
}
截图r-资产管理员.png中“盘点员”和“复核员”两个输入框,正是为此设计。银行审计要求所有盘点记录必须双签,系统通过强制校验确保电子留痕符合纸质签字同等效力。
第三重:差异处理的四象限法则
盘点完成后,InventoryResultService.generateReport()生成差异报告,但差异处理逻辑遵循银行风控四象限:
| 差异类型 | 数量差异 | 价值差异 | 处理流程 |
|----------|-----------|------------|------------|
| A类(高风险) | >5件 | >10万元 | 自动触发AssetDisposalProcess,需分管行长审批 |
| B类(中风险) | 1-5件 | 1-10万元 | 提交资产管理部门负责人审批 |
| C类(低风险) | 1件 | <1万元 | 系统自动标记“待核实”,3个工作日内未处理则升级为B类 |
| D类(无风险) | 0件 | 0元 | 直接归档 |
AssetDisposalProcess不是简单工作流,而是集成银行现有OA审批系统:调用ApprovalClient.startProcess("ASSET_DISPOSAL", params),其中params包含差异清单PDF(由iText生成),确保审计线索完整。这种设计让资产管理模块不再是孤立系统,而是银行整体风控体系的神经末梢。
3.3 档案管理:人事与合同的合规性硬约束
银行档案管理受《企业会计准则》《劳动合同法》《个人信息保护法》三重约束,代码中ArchiveService的实现处处体现合规硬编码:
人事档案的“最小必要”原则
PersonnelArchiveController.downloadFile()方法下载档案时,强制过滤敏感字段:
// 从数据库读取原始档案数据
PersonnelArchive archive = archiveMapper.selectById(id);
// 执行脱敏:身份证号只保留前4后4,手机号替换为****,银行卡号全部*号
archive.setIdCard(maskIdCard(archive.getIdCard()));
archive.setPhone(maskPhone(archive.getPhone()));
archive.setBankCard(maskBankCard(archive.getBankCard()));
// 仅当用户角色为“人力资源部”且申请事由为“劳动仲裁”时,才返回原始数据
if (!"HR_DEPT".equals(user.getDeptCode()) || !"LABOR_ARBITRATION".equals(purpose)) {
return archive; // 返回脱敏后数据
}
截图4-档案管理-人事档案-增加.png中,身份证号输入框右侧有“加密存储”提示图标,点击显示加密算法说明(AES-256-GCM),这正是为满足《个人信息保护法》第51条“采取必要措施保障所处理个人信息的安全”。
合同管理的“密级-期限”双控机制
ContractInfo实体类中两个关键字段:
private String securityLevel; // 密级:PUBLIC/INTERNAL/SECRET/TOP_SECRET
private Integer retentionYears; // 保管期限:10/30/100/PERMANENT
ContractService.save()方法校验规则:
- 若securityLevel='SECRET',则retentionYears必须≥30年;
- 若retentionYears='PERMANENT',则securityLevel必须为TOP_SECRET或SECRET;
- 合同到期前90天,定时任务向sys_contract_owner表中负责人发送邮件:“您负责的合同【XXX】将于【YYYY-MM-DD】到期,请及时续签或归档”。
更关键的是归档逻辑:ContractArchiveService.archive()方法调用时,自动根据securityLevel选择存储位置:
- PUBLIC → 存入公共NAS目录 /archive/public/;
- INTERNAL → 存入部门NAS目录 /archive/internal/{deptCode}/;
- SECRET/TOP_SECRET → 加密后存入专用加密存储服务(代码中预留EncryptionService.encrypt(fileBytes)接口)。
这种设计让档案管理模块天然具备合规审计能力——任何监管检查,只需导出sys_contract表中securityLevel和retentionYears字段,即可生成符合《金融行业网络安全等级保护基本要求》的自查报告。
4. 实操部署与二次开发关键路径
4.1 数据库配置的银行环境适配要点
README.md中“修改数据库”截图(0-99-修改数据库.png)看似简单,实则暗藏银行特有配置。以Oracle为例,application-oracle.yml关键配置:
spring:
datasource:
url: jdbc:oracle:thin:@//10.10.1.100:1521/ORCL # 银行内网IP,禁用主机名(DNS故障风险)
username: OA_USER # 必须使用独立数据库用户,禁止用SYSTEM
password: ${DB_PASSWORD:changeme} # 密码从环境变量读取,禁止明文
hikari:
connection-timeout: 30000
validation-timeout: 3000
idle-timeout: 600000
max-lifetime: 1800000
maximum-pool-size: 20 # 银行应用池大小通常≤20,避免连接耗尽
minimum-idle: 5
pool-name: HikariCP-OA
# 银行关键配置:连接泄漏检测
leak-detection-threshold: 60000 # 60秒未归还连接视为泄漏
jpa:
hibernate:
ddl-auto: none # 绝对禁止update/create,银行数据库变更必须走DBA工单
show-sql: false # 生产环境禁用SQL日志(性能+安全)
properties:
hibernate:
format_sql: false
dialect: org.hibernate.dialect.Oracle12cDialect
必须修改的三项银行专属配置:
1. 连接串中的SID/Service Name:银行Oracle实例多为RAC集群,url中ORCL需替换为实际服务名(如OA_SERV),可通过tnsping OA_SERV验证;
2. 数据库用户权限:OA_USER需被授予SELECT ANY DICTIONARY(用于动态字典查询)和EXECUTE ON DBMS_CRYPTO(用于密码加密),但禁止DROP ANY TABLE;
3. 密码加密密钥:application.yml中crypto.key字段必须替换为32位随机字符串(如openssl rand -base64 32生成),该密钥用于加密sys_user.password字段,银行审计要求密钥不得与代码共存,应存于运维密钥管理系统。
提示:若使用达梦数据库(DM8),需额外修改
pom.xml中dm.jdbc.driver.DmDriver依赖版本为8.1.2.117,并在application-dm.yml中添加hibernate.dialect: org.hibernate.dialect.DmDialect,否则sys_dict表的dict_type字段会出现乱码。
4.2 启动与默认账号的银行安全加固步骤
README.md提供的默认账号admin/123456仅用于首次启动验证,正式使用前必须执行以下加固:
第一步:重置管理员密码
访问http://localhost:8080/login,用admin/123456登录后,立即进入“个人中心→密码修改”,新密码需满足:
- 长度8-20位;
- 包含大写字母、小写字母、数字、特殊字符(!@#$%^&*)各至少1个;
- 不能与前5次密码重复(sys_user_history_password表记录);
- 修改后,旧密码立即失效,且sys_login_log表记录login_status='PASSWORD_CHANGED'。
第二步:禁用默认账号
在系统管理→用户管理中,找到username='admin'的用户,将其status字段更新为DISABLED(数据库直接执行UPDATE sys_user SET status='DISABLED' WHERE username='admin'),并分配新管理员账号(如oa_admin)。银行安全基线要求:禁止使用默认账号,所有账号必须实名制绑定工号。
第三步:配置会话超时与锁屏
application.yml中调整:
# 银行标准:操作超时15分钟,锁屏5分钟
server:
servlet:
context-path: /oa
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
spring:
session:
timeout: 900 # 15分钟,单位秒
thymeleaf:
cache: true
resources:
add-mappings: true
# 前端锁屏配置(src/main/resources/static/js/common.js)
const LOCK_TIMEOUT = 300000; // 5分钟毫秒值
截图0-4-切换主题.png中右上角的“锁屏”按钮,点击后调用/api/v1/auth/lock接口,该接口生成一次性锁屏令牌存入Redis(LOCK:{userId}),解锁时需输入当前用户密码进行二次认证。
4.3 二次开发黄金路径:从“增删改查”到“银行流程嵌入”
作为银行OA二次开发基础,这套代码提供了清晰的扩展接口。我以“为某支行增加‘普惠金融贷款台账’模块”为例,说明高效开发路径:
路径一:复用现有模块骨架(推荐新手)
1. 复制module2-asset包为module7-loan;
2. 修改LoanInfo实体类,字段参考银行《普惠金融统计制度》:
java private String loanNo; // 贷款编号(按银行规则:YYMMDD+6位流水) private BigDecimal amount; // 贷款金额(精度18,2) private Date disburseDate; // 发放日期(必须≤今日) private String customerType; // 客户类型(小微企业/个体工商户/农户) private String guaranteeType; // 担保方式(信用/抵押/质押/保证)
3. 在SysMenu表中插入新菜单,perms字段设为loan:info:list;
4. 在SysDict表中新增字典类型LOAN_CUSTOMER_TYPE,录入值MICRO_ENTERPRISE,INDIVIDUAL_BUSINESS,FARMER;
5. 启动后,管理员在“菜单管理”中为“支行行长”角色分配该菜单,即完成上线。
路径二:嵌入银行现有流程(推荐进阶)
若需对接银行信贷管理系统(CMS),在LoanService.submit()中调用外部接口:
// 调用CMS校验客户征信
CmsResponse cmsResp = cmsClient.verifyCredit(customerId);
if (!"SUCCESS".equals(cmsResp.getCode())) {
throw new BusinessException("征信校验失败:" + cmsResp.getMsg());
}
// 同步贷款信息至CMS
cmsClient.syncLoanInfo(loanInfo);
// 更新本地状态为“已同步”
loanMapper.updateStatus(loanId, "SYNCED");
此时需在application.yml中配置CMS地址与密钥,并在SysDict中新增CMS_ENVIRONMENT字典(DEV/UAT/PROD),不同环境调用不同CMS地址。这种开发方式,让新模块天然融入银行现有IT生态,避免形成数据孤岛。
5. 常见问题与银行环境排查技巧实录
5.1 启动失败高频问题与根因定位
银行环境启动失败,80%源于环境配置与安全策略冲突。以下是真实排查记录:
| 现象 | 错误日志关键词 | 根因分析 | 解决方案 |
|---|---|---|---|
启动卡在Starting Servlet web server | Caused by: java.net.UnknownHostException: hostname | 银行内网DNS未配置,application.yml中server.address使用了主机名而非IP | 将server.address改为内网IP(如10.10.1.100),或在/etc/hosts添加10.10.1.100 hostname |
登录页空白,F12显示Failed to load resource: net::ERR_CONNECTION_REFUSED | Access to XMLHttpRequest at 'http://localhost:8080/api/v1/auth/login' from origin 'http://localhost:8080' has been blocked by CORS policy | 银行Chrome浏览器启用了严格CSP策略,禁止localhost跨域 | 在application.yml中配置cors.allowed-origins: ["http://localhost:8080"],或使用银行统一的前端域名(如oa.bank.com) |
| 登录成功但菜单为空 | SELECT * FROM sys_role_menu WHERE role_id = ?返回空结果 | 默认角色ROLE_ADMIN未在sys_role_menu中分配菜单,银行DBA执行了TRUNCATE sys_role_menu清理脚本 | 执行init-menu.sql脚本(资源包中提供),或在后台“角色管理→分配菜单”中为管理员勾选全部菜单 |
| 切换主题后样式错乱 | Refused to apply inline style because it violates the following Content Security Policy directive | 银行安全组在Web服务器层启用了CSP头,禁止style-src 'unsafe-inline' | 修改WebMvcConfigurer.addResourceHandlers(),将主题CSS改为外部文件引用,或联系安全组临时放宽CSP策略 |
注意:银行环境严禁使用
mvn spring-boot:run直接启动。必须打包为jar后,用java -Dfile.encoding=UTF-8 -Xms512m -Xmx1024m -jar oa-system.jar命令启动,并通过nohup守护进程。截图0-99-启动项目.png中终端窗口的-Xmx1024m参数,正是为避免内存溢出导致的JVM崩溃。
5.2 权限配置典型失误与修复指南
银行权限配置失误往往导致重大合规风险。以下是五个血泪教训:
失误一:角色继承关系断裂
现象:新创建的“支行行长”角色无法看到下属网点资产。
根因:sys_role.parent_id字段为空,未设置其父角色为“分行行长”。
修复:执行SQL UPDATE sys_role SET parent_id = (SELECT role_id FROM sys_role WHERE role_code = 'BRANCH_MANAGER') WHERE role_code = 'SUB_BRANCH_MANAGER';
失误二:按钮权限未同步更新
现象:在菜单管理中为“资产管理员”增加了“资产报废”菜单,但列表页无“报废”按钮。
根因:按钮权限码asset:info:scrap未在sys_role_button表中为该角色插入记录。
修复:在后台“系统管理→按钮权限分配”中,为“资产管理员”角色勾选asset:info:scrap,或执行SQL INSERT INTO sys_role_button(role_id, button_code) VALUES (?, 'asset:info:scrap');
失误三:数据权限范围过大
现象:某支行员工能看到全省资产数据。
根因:sys_user.dept_id字段错误关联到省级部门(dept_code='PROVINCE'),而非支行部门(dept_code='SUB_BRANCH_001')。
修复:核对sys_user表中该用户dept_id,更新为正确支行部门ID,并检查sys_dept表中该部门的parent_id是否逐级指向正确上级。
失误四:字典缓存未刷新
现象:新增了合同类型字典,但前端下拉框不显示。
根因:SysDictService使用@Cacheable注解缓存字典,但未配置缓存失效策略。
修复:在后台“系统管理→字典管理”中点击“刷新缓存”按钮,或执行redis-cli DEL "sys:dict:*"清除Redis缓存。
失误五:会话超时后未跳转登录页
现象:用户离开电脑15分钟后返回,点击按钮报错401 Unauthorized,未自动跳转登录页。
根因:前端axios.interceptors.response.use()未捕获401状态码并重定向。
修复:修改src/main/resources/static/js/common.js,在响应拦截器中添加:
if (error.response.status === 401) {
window.location.href = '/login?timeout=1';
}
5.3 银行特色功能调试技巧
主题切换的灰度发布验证
银行系统升级需灰度验证。截图0-4-切换主题.png中的主题切换,实际通过Cookie控制:
// ThemeController.setTheme()
Cookie themeCookie = new Cookie("oa_theme", themeName);
themeCookie.setPath("/");
themeCookie.setMaxAge(3600); // 1小时
response.addCookie(themeCookie);
调试时,在Chrome开发者工具Application→Cookies中,手动修改oa_theme值为dark或blue,刷新页面即可验证主题效果,无需重启服务。
密码强度校验的监管合规测试
银行要求密码必须包含特殊字符。测试时用Postman发送:
curl -X POST http://localhost:8080/api/v1/auth/change-password \
-H "Content-Type: application/json" \
-d '{"oldPassword":"Abc12345!","newPassword":"Abc12345@"}'
若返回{"code":400,"msg":"新密码必须包含!@#$%^&*中的至少一个"},说明校验生效。注意:@符号在URL中需编码为%40,否则会被Tomcat截断。
打印功能的银行A4适配验证
银行所有打印必须符合A4纸张(210×297mm)。在Chrome中按Ctrl+P,选择“另存为PDF”,检查PDF属性:
- 页面大小:A4(210 × 297 毫米);
- 页边距:上2.5cm、下2cm、左2.5cm、右2cm(@page { margin: 2.5cm 2cm; });
- 字体:中文用“微软雅黑”,英文用“Arial”,字号≥10.5pt(符合《银行业务凭证印刷规范》)。
这些细节,正是银行OA系统区别于通用OA的核心价值——它不是功能的堆砌,而是将监管要求、风控逻辑、操作习惯,一行行代码刻进系统骨髓。当你真正理解sys_role_button表中那几百条权限码的业务含义,当你在AssetInventoryService里看到双人复核的强制校验,当你发现PersonnelArchive实体类中每一个字段都在回应一部法律条文,你就触摸到了银行数字化转型最真实的脉搏。
简介:这套银行内部办公系统基于SpringBoot 2.x开发,包含六大功能模块:公文管理(支持会议安排与公文列表)、资产管理(涵盖资产入库、查询、盘点)、档案管理(人事档案与合同归档)、辅助办公(图书借阅与管理)、个人中心(薪资查看、通讯录、工作计划)、系统管理(用户、角色、部门、菜单、字典配置)。权限体系采用RBAC模型,预置管理员、资产管理员、资产盘点员、主任、普通用户五类角色,后台可灵活分配菜单级和按钮级操作权限。提供完整登录界面、密码修改、主题切换功能,配套详细README.md文档,说明数据库配置方式、项目启动步骤及默认账号密码(如admin/123456)。所有截图覆盖各模块核心操作流程,包括新增、列表展示等典型页面,如‘资产列表-增加’‘合同管理-列表’‘角色管理-增加’等,便于快速上手或二次开发。技术栈主流稳定,适合作为银行类OA系统学习范例或定制化开发基础。


被折叠的 条评论
为什么被折叠?



