pangu-user-platform/docs/应用管理技术方案.md

418 lines
17 KiB
Markdown
Raw Permalink Normal View History

# 应用管理技术方案
## 一、功能概述
应用管理模块用于管理接入盘古用户认证中心的第三方应用系统,实现应用注册、密钥管理、接口授权等功能。
## 二、数据库设计
### 2.1 ER 关系图
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ pg_application │ │ pg_app_api │ │ pg_api_dict │
│ (第三方应用表) │ 1───n │ (应用API授权表) │ n───1 │ (API接口字典表) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
```
### 2.2 表结构设计
#### 2.2.1 第三方应用表 (pg_application)
| 字段名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| app_id | bigint | 是 | 应用ID主键雪花算法 |
| app_code | varchar(32) | 是 | 应用编码唯一格式YY000001 |
| app_name | varchar(100) | 是 | 应用名称 |
| app_secret | varchar(100) | 是 | 应用密钥32位UUID |
| contact_person | varchar(50) | 否 | 联系人 |
| contact_phone | varchar(20) | 否 | 联系电话 |
| status | char(1) | 是 | 状态0正常 1停用 |
| tenant_id | varchar(20) | 是 | 租户编号 |
| create_dept | bigint | 否 | 创建部门 |
| create_by | bigint | 否 | 创建者 |
| create_time | datetime | 否 | 创建时间 |
| update_by | bigint | 否 | 更新者 |
| update_time | datetime | 否 | 更新时间 |
| del_flag | char(1) | 是 | 删除标志0存在 1删除 |
| remark | varchar(500) | 否 | 备注 |
**索引**
- PRIMARY KEY (`app_id`)
- UNIQUE KEY `uk_app_code` (`app_code`)
#### 2.2.2 API接口字典表 (pg_api_dict)
| 字段名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| api_id | bigint | 是 | API ID主键 |
| api_code | varchar(50) | 是 | API编码唯一 |
| api_name | varchar(100) | 是 | API名称 |
| api_path | varchar(200) | 是 | API路径 |
| api_method | varchar(10) | 是 | 请求方法GET/POST/PUT/DELETE |
| api_desc | varchar(500) | 否 | API描述 |
| status | char(1) | 是 | 状态0正常 1停用 |
| order_num | int | 是 | 排序号 |
**索引**
- PRIMARY KEY (`api_id`)
- UNIQUE KEY `uk_api_code` (`api_code`)
#### 2.2.3 应用API授权表 (pg_app_api)
| 字段名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| id | bigint | 是 | 主键 |
| app_id | bigint | 是 | 应用ID |
| api_id | bigint | 是 | API ID |
| create_time | datetime | 否 | 创建时间 |
**索引**
- PRIMARY KEY (`id`)
- UNIQUE KEY `uk_app_api` (`app_id`, `api_id`)
### 2.3 SQL 脚本
```sql
-- 第三方应用表
DROP TABLE IF EXISTS `pg_application`;
CREATE TABLE `pg_application` (
`app_id` bigint NOT NULL COMMENT '应用ID',
`app_code` varchar(32) NOT NULL COMMENT '应用编码',
`app_name` varchar(100) NOT NULL COMMENT '应用名称',
`app_secret` varchar(100) NOT NULL COMMENT '应用密钥',
`contact_person` varchar(50) DEFAULT NULL COMMENT '联系人',
`contact_phone` varchar(20) DEFAULT NULL COMMENT '联系电话',
`status` char(1) DEFAULT '0' COMMENT '状态0正常 1停用',
`tenant_id` varchar(20) DEFAULT '000000' COMMENT '租户编号',
`create_dept` bigint DEFAULT NULL COMMENT '创建部门',
`create_by` bigint DEFAULT NULL COMMENT '创建者',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` bigint DEFAULT NULL COMMENT '更新者',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`del_flag` char(1) DEFAULT '0' COMMENT '删除标志0存在 1删除',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`app_id`),
UNIQUE KEY `uk_app_code` (`app_code`)
) ENGINE=InnoDB COMMENT='第三方应用表';
-- API接口字典表
DROP TABLE IF EXISTS `pg_api_dict`;
CREATE TABLE `pg_api_dict` (
`api_id` bigint NOT NULL COMMENT 'API ID',
`api_code` varchar(50) NOT NULL COMMENT 'API编码',
`api_name` varchar(100) NOT NULL COMMENT 'API名称',
`api_path` varchar(200) NOT NULL COMMENT 'API路径',
`api_method` varchar(10) DEFAULT 'GET' COMMENT '请求方法',
`api_desc` varchar(500) DEFAULT NULL COMMENT 'API描述',
`status` char(1) DEFAULT '0' COMMENT '状态0正常 1停用',
`order_num` int DEFAULT 0 COMMENT '排序',
PRIMARY KEY (`api_id`),
UNIQUE KEY `uk_api_code` (`api_code`)
) ENGINE=InnoDB COMMENT='API接口字典表';
-- 应用API授权表
DROP TABLE IF EXISTS `pg_app_api`;
CREATE TABLE `pg_app_api` (
`id` bigint NOT NULL COMMENT '主键',
`app_id` bigint NOT NULL COMMENT '应用ID',
`api_id` bigint NOT NULL COMMENT 'API ID',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_app_api` (`app_id`, `api_id`)
) ENGINE=InnoDB COMMENT='应用API授权表';
-- 菜单数据
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query_param, is_frame, is_cache, menu_type, visible, status, perms, icon, create_dept, create_by, create_time)
VALUES (2300, '应用管理', 0, 4, 'application', 'business/application/index', '', 1, 0, 'C', '0', '0', 'business:application:list', 'component', 103, 1, NOW());
INSERT INTO sys_menu VALUES (2301, '应用查询', 2300, 1, '', '', '', 1, 0, 'F', '0', '0', 'business:application:query', '#', 103, 1, NOW(), NULL, NULL, '');
INSERT INTO sys_menu VALUES (2302, '应用新增', 2300, 2, '', '', '', 1, 0, 'F', '0', '0', 'business:application:add', '#', 103, 1, NOW(), NULL, NULL, '');
INSERT INTO sys_menu VALUES (2303, '应用修改', 2300, 3, '', '', '', 1, 0, 'F', '0', '0', 'business:application:edit', '#', 103, 1, NOW(), NULL, NULL, '');
INSERT INTO sys_menu VALUES (2304, '应用删除', 2300, 4, '', '', '', 1, 0, 'F', '0', '0', 'business:application:remove', '#', 103, 1, NOW(), NULL, NULL, '');
INSERT INTO sys_menu VALUES (2305, '重置密钥', 2300, 5, '', '', '', 1, 0, 'F', '0', '0', 'business:application:resetSecret', '#', 103, 1, NOW(), NULL, NULL, '');
INSERT INTO sys_menu VALUES (2306, '接口授权', 2300, 6, '', '', '', 1, 0, 'F', '0', '0', 'business:application:api', '#', 103, 1, NOW(), NULL, NULL, '');
-- API字典初始数据
INSERT INTO pg_api_dict (api_id, api_code, api_name, api_path, api_method, api_desc, status, order_num)
VALUES (1700000000000000001, 'OPEN_STUDENT_LIST', '学生列表', '/open/api/student/list', 'GET', '开放API-学生列表分页查询', '0', 10);
```
## 三、后端代码结构
### 3.1 目录结构
```
pangu-modules/pangu-business/src/main/java/org/dromara/pangu/application/
├── controller/
│ └── PgApplicationController.java # 应用管理控制器
├── domain/
│ ├── PgApplication.java # 第三方应用实体
│ ├── PgApiDict.java # API字典实体
│ └── PgAppApi.java # 应用API授权实体
├── mapper/
│ ├── PgApplicationMapper.java # 应用Mapper
│ ├── PgApiDictMapper.java # API字典Mapper
│ └── PgAppApiMapper.java # 应用API授权Mapper
└── service/
├── IPgApplicationService.java # 应用服务接口
├── IPgApiDictService.java # API字典服务接口
└── impl/
├── PgApplicationServiceImpl.java # 应用服务实现
└── PgApiDictServiceImpl.java # API字典服务实现
```
### 3.2 API 接口列表
| 接口 | 方法 | 路径 | 权限标识 | 说明 |
|------|------|------|----------|------|
| 应用列表 | GET | /business/application/list | business:application:list | 分页查询应用列表 |
| 应用详情 | GET | /business/application/{appId} | business:application:query | 获取应用详情 |
| 新增应用 | POST | /business/application | business:application:add | 新增第三方应用 |
| 修改应用 | PUT | /business/application | business:application:edit | 修改应用信息 |
| 删除应用 | DELETE | /business/application/{appIds} | business:application:remove | 删除应用 |
| 重置密钥 | PUT | /business/application/resetSecret/{appId} | business:application:edit | 重置应用密钥 |
| 接口列表 | GET | /business/application/apiList | business:application:list | 获取可授权的API列表 |
### 3.3 核心代码
#### 3.3.1 控制器 (PgApplicationController.java)
```java
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/business/application")
public class PgApplicationController extends BaseController {
private final IPgApplicationService applicationService;
private final IPgApiDictService apiDictService;
@SaCheckPermission("business:application:list")
@GetMapping("/list")
public TableDataInfo<PgApplication> list(PgApplication app, PageQuery pageQuery) {
return applicationService.selectPageList(app, pageQuery);
}
@SaCheckPermission("business:application:edit")
@Log(title = "应用管理", businessType = BusinessType.UPDATE)
@PutMapping("/resetSecret/{appId}")
public R<PgApplication> resetSecret(@PathVariable Long appId) {
PgApplication app = applicationService.selectById(appId);
if (app == null) {
return R.fail("应用不存在");
}
String newSecret = IdUtil.fastSimpleUUID();
app.setAppSecret(newSecret);
applicationService.update(app);
return R.ok(app);
}
}
```
#### 3.3.2 服务实现 (PgApplicationServiceImpl.java)
```java
@RequiredArgsConstructor
@Service
public class PgApplicationServiceImpl implements IPgApplicationService {
private final PgApplicationMapper baseMapper;
private final PgAppApiMapper appApiMapper;
private final PgApiDictMapper apiDictMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public int insert(PgApplication app) {
// 自动生成应用编码格式YY000001
String appCode = generateAppCode();
app.setAppCode(appCode);
// 自动生成32位密钥
app.setAppSecret(IdUtil.fastSimpleUUID());
int rows = baseMapper.insert(app);
// 保存接口授权
if (rows > 0 && app.getApiCodes() != null && !app.getApiCodes().isEmpty()) {
saveAppApis(app.getAppId(), app.getApiCodes());
}
return rows;
}
private String generateAppCode() {
// 查询当前最大编码,生成下一个序号
// 格式YY + 6位数字如 YY000001
}
@Override
public boolean checkApiPermission(String appCode, String apiPath) {
// 校验应用是否有访问该接口的权限
List<String> paths = appApiMapper.selectApiPathsByAppCode(appCode);
return paths != null && paths.contains(apiPath);
}
}
```
#### 3.3.3 实体类 (PgApplication.java)
```java
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("pg_application")
public class PgApplication extends BaseEntity {
@TableId(type = IdType.ASSIGN_ID)
private Long appId;
private String appCode;
private String appName;
private String appSecret;
private String contactPerson;
private String contactPhone;
private String status;
private String tenantId;
@TableLogic
private String delFlag;
private String remark;
/** 接口授权API编码列表不落库 */
@TableField(exist = false)
private List<String> apiCodes;
}
```
## 四、前端代码结构
### 4.1 目录结构
```
frontend/src/
├── api/pangu/
│ └── application.js # API接口定义
└── views/application/
├── index.vue # 应用列表页面
└── components/
├── AppDialog.vue # 新增/编辑弹窗
└── SecretDialog.vue # 密钥展示弹窗
```
### 4.2 API 接口 (application.js)
```javascript
import request from '@/utils/request'
// 获取应用列表
export function getApplicationList(params) {
return request({ url: '/business/application/list', method: 'get', params })
}
// 新增应用
export function addApplication(data) {
return request({ url: '/business/application', method: 'post', data })
}
// 修改应用
export function updateApplication(data) {
return request({ url: '/business/application', method: 'put', data })
}
// 删除应用
export function deleteApplication(appId) {
return request({ url: `/business/application/${appId}`, method: 'delete' })
}
// 重置应用密钥
export function resetAppSecret(appId) {
return request({ url: `/business/application/resetSecret/${appId}`, method: 'put' })
}
// 获取接口授权选项列表
export function getApiAuthOptions() {
return request({ url: '/business/application/apiList', method: 'get' })
}
```
### 4.3 页面组件
#### 列表页面 (index.vue)
- 搜索条件:应用名称、应用编码、状态
- 列表字段:应用名称、应用编码、授权接口、状态、创建时间、创建人
- 操作按钮:新增、编辑、重置密钥、删除
#### 新增/编辑弹窗 (AppDialog.vue)
- 表单字段:应用名称、应用描述、联系人、联系电话、状态、接口授权
- 接口授权:多选框组,从 API 字典加载
## 五、业务流程
### 5.1 新增应用流程
```
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ 填写表单 │───>│ 提交保存 │───>│ 生成编码 │───>│ 生成密钥 │
└──────────┘ └──────────┘ └──────────┘ └──────────┘
│ │
v v
┌──────────────────────────┐
│ 保存应用 + 接口授权 │
└──────────────────────────┘
```
### 5.2 第三方调用接口流程
```
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ 携带凭证 │───>│ 拦截校验 │───>│ 权限检查 │───>│ 执行业务 │
└──────────┘ └──────────┘ └──────────┘ └──────────┘
│ │ │
│ v v
│ 校验AppCode 校验该应用
│ 和AppSecret 是否有权限
│ 访问该接口
v
请求头携带:
X-App-Code
X-App-Secret
X-Timestamp
X-Sign
```
## 六、文件清单
### 6.1 后端文件
| 文件路径 | 说明 |
|----------|------|
| `pangu-business/src/.../application/controller/PgApplicationController.java` | 应用管理控制器 |
| `pangu-business/src/.../application/domain/PgApplication.java` | 第三方应用实体 |
| `pangu-business/src/.../application/domain/PgApiDict.java` | API字典实体 |
| `pangu-business/src/.../application/domain/PgAppApi.java` | 应用API授权实体 |
| `pangu-business/src/.../application/mapper/PgApplicationMapper.java` | 应用Mapper |
| `pangu-business/src/.../application/mapper/PgApiDictMapper.java` | API字典Mapper |
| `pangu-business/src/.../application/mapper/PgAppApiMapper.java` | 应用API授权Mapper |
| `pangu-business/src/.../application/service/IPgApplicationService.java` | 应用服务接口 |
| `pangu-business/src/.../application/service/IPgApiDictService.java` | API字典服务接口 |
| `pangu-business/src/.../application/service/impl/PgApplicationServiceImpl.java` | 应用服务实现 |
| `pangu-business/src/.../application/service/impl/PgApiDictServiceImpl.java` | API字典服务实现 |
### 6.2 前端文件
| 文件路径 | 说明 |
|----------|------|
| `frontend/src/api/pangu/application.js` | API接口定义 |
| `frontend/src/views/application/index.vue` | 应用列表页面 |
| `frontend/src/views/application/components/AppDialog.vue` | 新增/编辑弹窗 |
| `frontend/src/views/application/components/SecretDialog.vue` | 密钥展示弹窗 |
### 6.3 SQL 文件
| 文件路径 | 说明 |
|----------|------|
| `pangu-business/sql/pangu_tables.sql` | 表结构包含pg_application、pg_api_dict、pg_app_api |
| `pangu-business/sql/pangu_menu.sql` | 菜单数据 |
| `pangu-business/sql/open_api_dict_data.sql` | API字典初始数据 |
---
*文档版本v1.0*
*更新日期2026-02-04*
*作者pangu*