# MES系统授权续费功能 - 任务文档 **版本**: v2.0.008 **作者**: 周启威 **日期**: 2026-03-12 **状态**: 开发完成 --- ## 功能概述 实现MES系统授权到期提醒和续费管理功能,包括: 1. 首页弹窗提醒(剩余天数/已过期天数) 2. 首页顶部到期时间显示(版本说明左侧) 3. 到期后限制普通用户访问业务模块 4. 管理员续费操作和历史记录管理 5. 联系方式管理(邮箱+电话) --- ## 已完成工作 ### 1. 数据库设计 ✅ #### 1.1 系统授权配置表(sys_license_config) - 存储系统全局到期时间和联系方式 - 字段:id, expire_date, contact_email, contact_phone, create_time, update_time - SQL文件:`.sql/2026-03-12_v2.0.008_周启威_到期续费功能.sql` #### 1.2 续费记录表(sys_license_renewal) - 存储每次续费操作的历史记录 - 字段:id, company_name, previous_expire_date, expire_date, operator, operate_time, remark - 索引:idx_operate_time - **previous_expire_date**: 记录续费前的到期时间,便于查看每次续费延长的时间 ### 2. 后端代码 ✅ #### 2.1 实体类 - `SysLicenseConfig.java` - 系统授权配置实体 - `SysLicenseRenewal.java` - 续费记录实体 #### 2.2 Mapper层 - `SysLicenseConfigMapper.java` + XML - `SysLicenseRenewalMapper.java` + XML #### 2.3 Service层 - `ISysLicenseService.java` - 接口定义 - `SysLicenseServiceImpl.java` - 业务实现 - 获取授权信息(含剩余天数计算) - 更新到期时间 - 更新联系方式 - 新增续费记录(事务保证,自动记录续费前到期时间) - 查询续费记录列表(按时间倒序) - 获取最新续费记录 - 检查是否过期 #### 2.4 Controller层 - `SysLicenseController.java` - GET /system/license/info - 获取授权信息(所有用户) - PUT /system/license/expire - 更新到期时间(仅管理员,@RequestBody) - PUT /system/license/contact - 更新联系方式(仅管理员,@RequestBody) - POST /system/license/renewal - 新增续费记录(仅管理员) - GET /system/license/renewal/list - 查询续费记录(仅管理员) - GET /system/license/renewal/latest - 获取最新续费记录(所有用户) ### 3. 前端代码 ✅ #### 3.1 API封装 - `src/api/system/license.js` - 授权相关接口 #### 3.2 组件开发 - `src/components/LicenseExpireDialog/index.vue` - 首页弹窗提醒组件 - 距离到期≤30天或已过期时显示 - 显示剩余/过期天数 - 显示联系邮箱和电话 - **智能提醒机制**: - 剩余天数 > 5天:可选择"今日不再提示",当天不再弹窗 - 剩余天数 ≤ 5天:每次进入都提示,无法忽略 - 已过期:每次进入都提示,无法忽略 - 使用 sessionStorage 存储今日忽略状态 - `src/components/LicenseExpireInfo/index.vue` - 首页到期时间显示组件 - 显示位置:首页顶部,版本说明左侧 - 动态颜色:正常(灰色)/警告(橙色)/过期(红色+脉冲动画) - **智能Tooltip**:鼠标悬停显示详细信息 - 下次到期时间 - 剩余天数/已过期天数 - 上次续费时间 - 联系邮箱和电话 - 管理员点击跳转续费管理页面 - 每小时自动刷新数据 #### 3.3 页面开发 - `src/views/system/license/renewal.vue` - 续费管理页面 - 上方:续费操作表单(企业名称、到期时间、备注) - 下方:历史续费记录表格(支持分页) - 显示续费前到期时间和续费后到期时间对比 - 按操作时间倒序排列 - 仅管理员可访问 --- ## 核心功能说明 ### 1. 到期提醒机制 - **弹窗提醒**:距离到期≤30天或已过期时显示弹窗 - **剩余 > 5天**:显示"今日不再提示"和"我知道了"两个按钮,用户可选择今日忽略 - **剩余 ≤ 5天**:只显示"我知道了"按钮,每次进入都提示 - **已过期**:只显示"我知道了"按钮,每次进入都提示 - **首页显示**:实时显示到期时间和剩余天数,根据状态变色,下拉菜单显示详细续费信息 - **关闭控制**: - 点击"今日不再提示":使用 sessionStorage 记录,当天不再显示(仅剩余>5天时可用) - 点击"我知道了":关闭弹窗,下次进入系统会再次显示 ### 2. 权限控制 - **管理员**:不受任何限制,可正常访问所有模块和续费管理 - **普通用户**: - 系统未到期:正常访问所有模块 - 系统已过期:只能访问首页和个人中心,访问业务模块时拦截 - **路由守卫实现**: - 在 `permission.js` 中添加授权过期检查 - 使用缓存机制(1分钟刷新),避免频繁请求接口 - 过期后访问业务模块会弹窗提示并强制跳转首页 - **黑名单拦截**(仅拦截以下业务模块): - `/mes/` - 生产管理 - `/warehouse/` - 仓库管理 - `/quality/` - 质量管理 - `/sale/` - 销售管理 - `/purchase/` - 采购管理 - `/energy/` - 能源管理 - `/safe/` - 安全管理 - `/finance/` - 财务管理 - **允许访问**:首页、个人中心、系统管理、授权管理等非业务模块 ### 3. 续费操作 - 管理员填写企业名称、续费到期时间、备注 - 点击确认续费后: 1. 自动记录续费前的到期时间 2. 更新系统全局到期时间 3. 插入续费历史记录 4. 自动记录操作人和操作时间 5. 刷新历史记录表格 ### 4. 数据展示 - **历史续费记录**:按操作时间倒序显示(SQL层面保证) - **字段**:企业名称、续费前到期时间、续费后到期时间、操作人、操作时间、备注 - **分页**:支持分页查询 - **续费信息Tooltip**:首页到期时间显示处,鼠标悬停可查看最新续费记录 --- ## 集成工作(已完成) ### 1. 首页集成 #### 1.1 弹窗组件集成 已在 `src/views/index.vue` 中集成 `LicenseExpireDialog` 组件 - 登录后自动检查授权状态 - 剩余天数 ≤30 或已过期时自动弹窗 - 使用 `sessionStorage` 存储关闭状态(关闭浏览器后重新显示) #### 1.2 导航栏授权信息显示 已在 `src/layout/components/Navbar.vue` 中集成 `LicenseExpireInfo` 组件 - 显示位置:版本说明左侧 - 下拉菜单格式,与版本说明样式一致 - 显示内容:到期时间、剩余天数、上次续费、联系方式 - 管理员可点击"进入续费管理" ### 2. 路由配置 在 `src/router/index.js` 中添加: ```javascript { path: '/system/license', component: Layout, hidden: true, permissions: ['system:license:view'], children: [ { path: 'renewal', component: () => import('@/views/system/license/renewal'), name: 'LicenseRenewal', meta: { title: '续费管理', icon: 'license', activeMenu: '/system/license' } } ] } ``` ### 3. 权限拦截(需手动完成) #### 3.1 前端路由守卫 在 `src/permission.js` 中添加: ```javascript import { getLicenseInfo } from '@/api/system/license' const RESTRICTED_MODULES = [ '/mes/production', // 生产管理 '/warehouse', // 仓库管理 '/quality', // 质量管理 '/equipment' // 设备管理 ] router.beforeEach(async (to, from, next) => { // 检查系统授权状态 try { const response = await getLicenseInfo() const { isExpired } = response.data const roles = store.getters.roles if (isExpired && !roles.includes('admin')) { const isRestrictedPath = RESTRICTED_MODULES.some(module => to.path.startsWith(module) ) if (isRestrictedPath) { Message.error('系统已过期,请联系管理员续费') next({ path: '/' }) return } } } catch (error) { console.error('检查授权状态失败:', error) } next() }) ``` #### 3.2 后端拦截器(可选) 创建 `LicenseInterceptor.java` 并注册到 `WebMvcConfig` --- ## 验收清单 ### 数据库 - [ ] sys_license_config 表创建成功,包含初始数据 - [ ] sys_license_renewal 表创建成功 ### 后端接口 - [ ] GET /system/license/info 返回正确的授权信息和剩余天数 - [ ] PUT /system/license/expire 仅管理员可调用,成功更新到期时间 - [ ] PUT /system/license/contact 仅管理员可调用,成功更新联系方式 - [ ] POST /system/license/renewal 仅管理员可调用,成功新增续费记录并更新系统到期时间 - [ ] GET /system/license/renewal/list 仅管理员可调用,返回续费记录列表(按时间倒序) ### 前端页面 - [ ] 首页弹窗正确显示剩余天数或已过期天数 - [ ] 首页弹窗显示联系邮箱和电话 - [ ] 首页弹窗关闭后当天不再显示 - [ ] 首页顶部版本说明左侧正确显示到期时间 - [ ] 根据剩余天数显示不同颜色(正常/警告/错误) - [ ] 管理员点击可跳转到续费管理页面 - [ ] 续费管理页面仅管理员可访问 - [ ] 续费操作成功后,系统到期时间更新 - [ ] 续费操作成功后,历史续费记录表格显示最新记录 - [ ] 历史续费记录按操作时间倒序显示 ### 权限控制 - [ ] 系统已过期时,普通用户无法访问生产管理、仓库管理、质量管理、设备管理模块 - [ ] 系统已过期时,管理员可正常访问所有模块 - [ ] 访问受限模块时提示"系统已过期,请联系管理员续费" --- ## 文件清单 ### SQL文件 - `.sql/2026-03-12_v2.0.008_周启威_到期续费功能.sql` ### 后端文件 - `mes-system/src/main/java/cn/sourceplan/system/domain/SysLicenseConfig.java` - `mes-system/src/main/java/cn/sourceplan/system/domain/SysLicenseRenewal.java` - `mes-system/src/main/java/cn/sourceplan/system/mapper/SysLicenseConfigMapper.java` - `mes-system/src/main/java/cn/sourceplan/system/mapper/SysLicenseRenewalMapper.java` - `mes-system/src/main/resources/mapper/system/SysLicenseConfigMapper.xml` - `mes-system/src/main/resources/mapper/system/SysLicenseRenewalMapper.xml` - `mes-system/src/main/java/cn/sourceplan/system/service/ISysLicenseService.java` - `mes-system/src/main/java/cn/sourceplan/system/service/impl/SysLicenseServiceImpl.java` - `mes-admin/src/main/java/cn/sourceplan/web/controller/system/SysLicenseController.java` ### 前端文件 - `mes-ui/src/api/system/license.js` - `mes-ui/src/components/LicenseExpireDialog/index.vue` - `mes-ui/src/components/LicenseExpireInfo/index.vue` - `mes-ui/src/views/system/license/renewal.vue` - `mes-ui/src/permission.js` - 路由守卫(授权过期拦截) - `mes-ui/src/layout/components/Navbar.vue` - 顶部导航栏集成 - `mes-ui/src/views/index.vue` - 首页弹窗集成 --- ## 优化改进 (2026-03-13) ### 1. 用户体验优化 - ✅ **弹窗显示机制**:每次进入系统都显示 - 确保用户不会错过重要的续费提醒 - 避免因关闭弹窗而长期不看到提醒的情况 ### 2. 数据完整性增强 - ✅ **续费前到期时间记录**:新增 `previous_expire_date` 字段 - 自动记录每次续费前的系统到期时间 - 可清晰看到每次续费延长了多少时间 - 便于续费历史追溯和审计 ### 3. 接口规范化 - ✅ **RESTful规范**:统一使用 `@RequestBody` 接收JSON - `PUT /system/license/expire` 改用 JSON body - `PUT /system/license/contact` 改用 JSON body - 前后端交互更规范,便于后续扩展 ### 4. 数据查询优化 - ✅ **SQL排序保证**:Mapper XML 添加 `ORDER BY operate_time DESC` - 确保续费记录始终按时间倒序显示 - 不依赖数据库默认顺序,提高可靠性 ### 5. 信息展示增强 - ✅ **智能Tooltip**:首页到期时间显示增强 - 鼠标悬停显示详细续费信息 - 包含:下次到期时间、剩余天数、上次续费时间、联系方式 - 类似版本说明的交互方式,用户体验一致 ### 6. 弹窗提醒优化 - ✅ **今日不再提示功能**:智能提醒策略 - **剩余 > 5天**:用户可选择"今日不再提示",避免频繁打扰 - **剩余 ≤ 5天**:强制提醒,确保临近到期不会被忽略 - **已过期**:强制提醒,确保过期状态得到重视 - 使用 sessionStorage 存储忽略状态,关闭浏览器后重置 - 平衡用户体验和提醒效果,既不过度打扰,又不遗漏重要提醒 ### 7. 路由拦截策略优化 - ✅ **黑名单拦截模式**:从白名单改为黑名单 - 仅拦截核心业务模块(生产、仓库、质量、销售、采购、能源、安全、财务) - 允许访问系统管理、授权管理等非业务模块 - 避免过度限制,提升用户体验 ### 8. 弹窗UI现代化 - ✅ **视觉设计优化**:现代化UI风格 - 大图标 + 渐变背景 + 动画效果 - 根据状态变色(橙色警告/红色过期) - 卡片式布局,信息层次清晰 - 圆角设计,阴影效果,视觉更友好 --- ## 注意事项 1. **时区问题**:确保前后端时间格式一致,使用 `yyyy-MM-dd HH:mm:ss` 格式 2. **权限校验**:所有管理员操作接口必须添加 `@PreAuthorize("@ss.hasRole('admin')")` 注解 3. **事务管理**:续费操作涉及两张表,已使用 `@Transactional` 保证事务一致性 4. **日志记录**:所有授权相关操作已添加 `@Log` 注解记录操作日志 5. **弹窗提醒**:每次进入系统都会显示到期提醒弹窗,确保用户不会错过续费 6. **自动记录**:续费操作会自动记录续费前到期时间,无需手动填写 --- ## 设计原则 ✅ **轻量化** - 仅2张表,6个接口,3个前端组件 ✅ **简洁高效** - 无复杂依赖,无授权密钥验证 ✅ **权限分离** - 管理员全权限,普通用户受限 ✅ **用户友好** - 弹窗可关闭,首页显示直观 ✅ **可维护性** - 代码简洁,逻辑清晰 --- ## 开发状态 **✅ 开发完成** - 2026-03-13 所有功能已实现并集成完毕: - ✅ 后端接口和数据库 - ✅ 前端组件和页面 - ✅ 首页弹窗和导航栏显示 - ✅ 路由守卫和权限控制 - ✅ 样式优化(下拉菜单格式) **测试要点**: 1. 登录后首页是否显示授权到期弹窗(剩余≤30天或已过期) 2. 导航栏"授权信息"下拉菜单是否显示正确 3. 普通用户在授权过期后访问业务模块是否被拦截 4. 管理员是否可以正常续费 5. 续费后授权信息是否实时更新 --- ## 排除范围 以下功能**不在本次需求范围内**: - ❌ 授权密钥验证 - ❌ 趋势分析 - ❌ 邮件通知 - ❌ 系统消息推送 - ❌ 模块粒度授权控制 - ❌ 多租户支持 - ❌ 自动续费 - ❌ 在线支付