418 lines
17 KiB
Markdown
418 lines
17 KiB
Markdown
# 应用管理技术方案
|
||
|
||
## 一、功能概述
|
||
|
||
应用管理模块用于管理接入盘古用户认证中心的第三方应用系统,实现应用注册、密钥管理、接口授权等功能。
|
||
|
||
## 二、数据库设计
|
||
|
||
### 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*
|