提交 5669460a authored 作者: 陈泽健's avatar 陈泽健

feat(ui-test): 新增73个深层交互用例+模块筛选器case_type过滤

- 后端 module_service/routers 新增 case_type 参数,通过 sec_ 前缀区分 UI/安全测试模块
- 前端 Cases.vue/Recorder.vue loadModules 传递 case_type='ui' 过滤安全测试模块
- 前端 api/modules.ts list() 新增 case_type 参数
- 新增功能中心深层交互用例创建脚本 create_deep_cases_func_center_v3.py(73个用例)
- 新增PRD需求文档:功能中心深层交互用例补充 + 模块筛选器显示安全测试模块
- 新增执行计划文档:对应两份PRD的计划执行文档
- 更新HANDOFF交接文档
- 数据库新增73个深层交互用例(202→275)
Co-Authored-By: 's avatarClaude <noreply@anthropic.com>
上级 13a044a6
# 问题处理文档 — 模块筛选器显示安全测试模块
> **文档版本**: v1.0
> **创建日期**: 2026-07-23
> **问题状态**: 待修复
> **负责人**: czj
---
## 一、问题描述
### 1.1 问题现象
用例管理页面(`/cases`)的"选择模块"筛选器下拉框中,显示了安全测试相关模块(如"API1 - 对象级别授权失效"、"华为安全红线检查"等),与 UI 自动化测试模块混在一起,影响用户体验。
### 1.2 影响范围
- `frontend/src/views/Cases.vue` — 用例管理页面的模块筛选器
- `frontend/src/views/Recorder.vue` — 用例录制页面的模块选择器(同样问题)
- 后端 `/api/modules` API 返回所有模块,无区分
### 1.3 根因分析
| # | 问题点 | 说明 |
|---|--------|------|
| 1 | 模块数据模型缺少区分字段 | `module_type` 字段只有 `standard/custom`,安全测试模块也用 `standard` |
| 2 | 后端 API 无 case_type 过滤 | `/api/modules` 不支持按用例类型(ui/security)过滤 |
| 3 | 前端无条件加载所有模块 | `loadModules()` 函数调用 API 获取全部模块 |
### 1.4 安全测试模块特征
- **ID 前缀**: `sec_`(如 `sec_api01``sec_regression``sec_redline`
- **数量**: 12 个安全测试模块
- **用例类型**: `security`
---
## 二、解决方案
### 2.1 方案对比
| 方案 | 描述 | 优点 | 缺点 |
|------|------|------|------|
| **A: 后端API新增参数** | 新增 `case_type` 参数过滤模块 | 统一过滤逻辑,可复用 | 需修改后端+前端 |
| B: 前端过滤 | 前端过滤 `sec_` 前缀模块 | 改动小,快速实现 | 过滤逻辑散落在多处 |
| C: 模块新增字段 | 新增 `case_type` 字段区分模块 | 数据层面区分 | 需迁移数据 |
**推荐方案 A**:后端 API 新增 `case_type` 参数,前端调用时传递 `ui` 只获取 UI 测试模块。
### 2.2 方案A 设计
#### 2.2.1 后端改动
1. **修改 `Module` 模型**(可选,暂不修改字段):
- 保持现有 `module_type` 字段
- 通过模块 ID 前缀判断类型
2. **修改 `/api/modules` 路由**
- 新增 `case_type` 查询参数(`ui`/`security`/`all`
- 默认 `all` 返回全部
- `ui` 过滤掉 `sec_` 前缀模块
- `security` 只返回 `sec_` 前缀模块
3. **修改 `ModuleService.list` 方法**
- 增加 `case_type` 参数过滤逻辑
#### 2.2.2 前端改动
1. **修改 `Cases.vue`**
- `loadModules()` 调用 API 时传递 `case_type=ui`
2. **修改 `Recorder.vue`**(如有同样问题):
- 同上
---
## 三、验收标准
| 验收项 | 验收标准 |
|--------|---------|
| 用例管理模块筛选器 | 只显示 UI 测试模块,不显示安全测试模块 |
| 用例录制模块选择器 | 只显示 UI 测试模块 |
| API 兼容性 | 不传 `case_type` 参数时返回全部模块(向后兼容) |
| 数据库无变化 | 不修改现有数据 |
---
## 四、风险评估
| 风险 | 概率 | 影响 | 缓解措施 |
|------|------|------|---------|
| API 参数默认值影响其他调用方 | 低 | 中 | 默认 `all` 返回全部,向后兼容 |
| 前端其他页面未修改 | 低 | 低 | 全局搜索 `moduleApi.list` 调用 |
---
## 五、相关文件
| 文件 | 说明 |
|------|------|
| `backend/app/routers/modules.py` | 模块 API 路由 |
| `backend/app/services/module_service.py` | 模块服务层 |
| `backend/app/schemas/module.py` | 模块 Schema |
| `frontend/src/views/Cases.vue` | 用例管理页面 |
| `frontend/src/views/Recorder.vue` | 用例录制页面 |
| `frontend/src/api/modules.ts` | 模块 API 封装 |
\ No newline at end of file
# 功能中心深层交互用例补充 需求文档
> **文档版本**: v1.0
> **创建日期**: 2026-07-23
> **文档状态**: 初稿待评审
> **负责人**: czj
---
## 一、背景
### 1.1 问题描述
当前 `platform-auto-test` 平台中,UI自动化测试用例共202个,其中59个是"页面访问验证"用例(仅验证页面可打开)。深层交互用例仅覆盖了会议管理、数据分析、管理看板、运维管理四个模块,大量功能中心页面缺少深层交互步骤(筛选器、表格、Tab切换等交互验证)。
### 1.2 覆盖现状
| 模块 | 页面访问用例 | 深层交互用例 | 覆盖率 |
|------|-------------|-------------|--------|
| 会议管理 | 6 | 38 | 100% |
| 数据分析 | 12 | 19 | 63% |
| 管理看板 | 1 | 14 | 100% |
| 运维管理 | 3 | 12 | 100% |
| 会议运维 | 6 | 0 | 0% |
| 集控控制 | 13 | 2 | 15% |
| 资产管理 | 3 | 0 | 0% |
| 维护工单 | 4 | 0 | 0% |
| 会务管理 | 2 | 0 | 0% |
| 信息管理 | 3 | 0 | 0% |
| 信息发布 | 1 | 0 | 0% |
| 其他分类 | 4 | 0 | 0% |
**问题**:37个页面的用例仅验证页面可访问,无法验证实际功能是否正常。
### 1.3 目标
为37个页面补充深层交互用例,使:
- 总用例数从202增加到约275
- 深层交互用例覆盖率从50%提升到70%以上
- 新增用例执行通过率 >= 75%
---
## 二、需求内容
### 2.1 功能需求
#### 2.1.1 用例新增
为以下9个模块的37个页面补充深层交互用例:
| 模块 | 页面数 | 新增用例数 |
|------|--------|-----------|
| 会议运维 | 6 | 12 |
| 集控控制 | 11 | 22 |
| 资产管理 | 3 | 6 |
| 维护工单 | 4 | 8 |
| 会务管理 | 2 | 4 |
| 信息管理 | 3 | 6 |
| 信息发布 | 1 | 1 |
| 其他分类 | 4 | 8 |
| 数据分析 | 3 | 6 |
| **合计** | **37** | **73** |
#### 2.1.2 交互模式分类
根据页面特征,将37个页面分为6种交互模式:
| 模式 | 页面特征 | 交互步骤 | 适用页面数 |
|------|---------|---------|-----------|
| 模式A: 表格+筛选器 | el-table + el-select | 导航→等待表格→筛选器操作→验证表格 | 14 |
| 模式B: Tab切换 | el-tabs | 导航→验证Tab存在→切换Tab→验证内容 | 6 |
| 模式C: 图表+筛选器 | canvas + el-select | 导航→等待图表→筛选器操作→验证图表 | 3 |
| 模式D: 纯表格验证 | 仅el-table | 导航→等待表格→验证分页/行数 | 5 |
| 模式E: 树形结构 | el-tree + el-table | 导航→点击树节点→验证表格变化 | 3 |
| 模式F: 按钮操作 | 操作按钮 | 导航→点击按钮→验证弹窗/响应 | 4 |
#### 2.1.3 用例设计原则
1. **每个页面至少2个深层交互用例**:表格验证 + 交互验证
2. **断言策略宽松优先**:使用 `element_exists` 而非 `visible`,使用 `element_count_min` 而非 `count`
3. **选择器策略**:使用 `selectors` 回退链而非单一 `selector`
4. **等待策略**:三段式等待(特征元素 + 渲染 + 额外等待)
5. **状态重置**:每个用例末尾添加"回到首页"步骤
6. **无登录步骤**`auto_login=True`,由执行器自动处理登录
### 2.2 非功能需求
#### 2.2.1 执行效率
- 单个用例执行时间不超过180秒
- 批量执行73个用例总时间不超过60分钟
#### 2.2.2 可维护性
- 步骤模板函数可复用
- 新增页面时可直接使用模板快速创建用例
- 支持按名称查找并更新已有用例
---
## 三、用例设计
### 3.1 会议运维模块(12个用例)
| 页面 | 用例1 | 用例2 |
|------|-------|-------|
| 告警列表 | 表格数据验证 | 筛选器交互验证 |
| 视讯设备 | 表格数据验证 | 树形筛选验证 |
| 运维区域 | 表格数据验证 | 筛选器交互验证 |
| 会议巡检 | 表格数据验证 | 分页验证 |
| 运维巡检 | 页面元素验证 | 表格验证 |
| 运维设备 | 表格数据验证 | 筛选器验证 |
### 3.2 集控控制模块(22个用例)
| 页面 | 用例1 | 用例2 |
|------|-------|-------|
| 壁纸推送 | 页面元素验证 | 表格验证 |
| 屏幕管理 | 页面元素验证 | Tab切换验证 |
| 应用管理 | 表格数据验证 | 搜索验证 |
| 播放器发布 | 页面元素验证 | 表格验证 |
| 文件推送 | 表格数据验证 | 筛选器验证 |
| 消息推送 | 表格数据验证 | 筛选器验证 |
| 脚本命令 | 表格数据验证 | 操作按钮验证 |
| 设备网络 | 页面元素验证 | 表格验证 |
| 转录列表 | 表格数据验证 | Tab切换验证 |
| 软件卸载 | 页面元素验证 | 表格验证 |
| 门口屏发布 | 页面元素验证 | 表格验证 |
### 3.3 资产管理模块(6个用例)
| 页面 | 用例1 | 用例2 |
|------|-------|-------|
| 资产信息 | 表格数据验证 | 筛选器交互验证 |
| 资产故障 | 表格数据验证 | 筛选器交互验证 |
| 资产设备 | 表格数据验证 | 操作按钮验证 |
### 3.4 维护工单模块(8个用例)
| 页面 | 用例1 | 用例2 |
|------|-------|-------|
| 信息窗管理 | 表格数据验证 | 筛选器验证 |
| 告警工单 | 表格数据验证 | Tab切换验证 |
| 工单列表 | 表格数据验证 | Tab切换验证 |
| 我的工单 | 表格数据验证 | Tab切换验证 |
### 3.5 会务管理模块(4个用例)
| 页面 | 用例1 | 用例2 |
|------|-------|-------|
| 会务统筹 | 表格数据验证 | 筛选器验证 |
| 会务工单 | 表格数据验证 | 筛选器验证 |
### 3.6 信息管理模块(6个用例)
| 页面 | 用例1 | 用例2 |
|------|-------|-------|
| 下载列表 | 表格数据验证 | 筛选器验证 |
| 文件列表 | 表格数据验证 | 筛选器验证 |
| 通讯录 | 表格数据验证 | 树形筛选验证 |
### 3.7 信息发布模块(1个用例)
| 页面 | 用例 |
|------|------|
| 消息通知 | 表格数据验证 |
### 3.8 其他分类模块(8个用例)
| 页面 | 用例1 | 用例2 |
|------|-------|-------|
| 会议审批 | 表格数据验证 | Tab切换验证 |
| 历史记录 | 表格数据验证 | Tab切换验证 |
| 参会人模板 | 表格数据验证 | 操作按钮验证 |
| 已预定会议 | 表格数据验证 | 筛选器验证 |
### 3.9 数据分析模块(6个用例)
| 页面 | 用例1 | 用例2 |
|------|-------|-------|
| RSE会议统计 | 页面元素验证 | 图表验证 |
| SMC3.0会议统计 | 页面元素验证 | 图表验证 |
| Welink会议统计 | 页面元素验证 | 图表验证 |
---
## 四、验收标准
### 4.1 功能验收
| 验收项 | 验收标准 |
|--------|---------|
| 用例创建 | 数据库新增73个深层交互用例 |
| 用例执行 | 新增用例批量执行通过率 >= 75% |
| 步骤设计 | 每个用例包含至少1个交互操作步骤 |
| 断言设计 | 每个用例包含至少2个断言步骤 |
### 4.2 质量验收
| 验收项 | 验收标准 |
|--------|---------|
| 步骤模板化 | 7个可复用的步骤模板函数 |
| 选择器健壮性 | 使用 selectors 回退链 |
| 状态隔离 | 每个用例末尾有"回到首页"步骤 |
---
## 五、风险评估
| 风险 | 概率 | 影响 | 缓解措施 |
|------|------|------|---------|
| 功能中心抽屉状态残留 | 中 | 中 | 每个用例末尾添加"回到首页"步骤 |
| 表格数据为空 | 高 | 低 | 使用 `element_exists` 断言 |
| 筛选器下拉不弹出 | 中 | 中 | 增加多选器回退链 |
| Tab切换不生效 | 低 | 中 | 增加等待时间 |
| 页面加载超时 | 中 | 中 | 增加超时时间至30s |
---
## 六、附录
### 6.1 相关文档
- HANDOFF_UI自动化.md — 项目交接文档
- _PRD_需求文档_深层交互用例步骤优化.md — 步骤优化PRD
- create_deep_interaction_cases_v2.py — 已有步骤模板脚本
### 6.2 执行器支持的动作和断言
**动作类型**:navigate, click, fill, select, hover, wait, scroll, press, check, uncheck, screenshot
**断言类型**:visible, hidden, element_exists, element_count_min, count, contains, text, value, url_contains, title
\ No newline at end of file
# 模块筛选器显示安全测试模块 计划执行文档
> **文档版本**: v1.0
> **创建日期**: 2026-07-23
> **关联 PRD**: _PRD_问题处理_模块筛选器显示安全测试模块.md v1.0
> **负责人**: czj
---
## 一、执行概述
### 1.1 项目背景
用例管理页面"选择模块"筛选器显示安全测试模块(如"API1 - 对象级别授权失效"等),与 UI 自动化测试模块混在一起。需修改后端 API 和前端调用,按用例类型过滤模块。
### 1.2 执行目标
| 目标 | 描述 | 验收标准 |
|------|------|---------|
| 后端过滤 | API 新增 case_type 参数 | `case_type=ui` 只返回 UI 测试模块 |
| 前端调用 | 传递 case_type=ui | 模块筛选器不显示安全测试模块 |
| 向后兼容 | 不传 case_type 时返回全部 | 现有功能不受影响 |
### 1.3 预计工期
| 阶段 | 内容 | 预计时间 |
|------|------|---------|
| Phase 1 | 后端 API 新增 case_type 参数 | 0.5 小时 |
| Phase 2 | 前端调用传递 case_type | 0.5 小时 |
| Phase 3 | 验证 | 0.5 小时 |
| **总计** | | **1.5 小时** |
---
## 二、任务分解
### 2.1 Phase 1: 后端 API 新增 case_type 参数
#### 2.1.1 修改 `module_service.py` — 服务层过滤逻辑
**文件**: `backend/app/services/module_service.py`
**改动**: `list` 方法新增 `case_type` 参数,通过模块 ID 前缀过滤:
```python
async def list(
self,
skip: int = 0,
limit: int = 100,
order_by: str = "order",
module_type: Optional[str] = None,
case_type: Optional[str] = None, # 新增: ui/security/all
) -> Tuple[List[Module], int]:
conditions = []
if module_type:
conditions.append(Module.module_type == module_type)
# 按 case_type 过滤模块
if case_type == "ui":
# UI测试模块:ID不以 sec_ 开头
conditions.append(~Module.id.startswith("sec_"))
elif case_type == "security":
# 安全测试模块:ID以 sec_ 开头
conditions.append(Module.id.startswith("sec_"))
# case_type 为 None 或 "all" 时不过滤
```
#### 2.1.2 修改 `modules.py` — 路由层参数传递
**文件**: `backend/app/routers/modules.py`
**改动**: `list_modules` 函数新增 `case_type` 查询参数:
```python
@router.get("", response_model=ModuleListResponse)
async def list_modules(
skip: int = Query(0, ge=0, description="跳过的记录数"),
limit: int = Query(100, ge=1, le=500, description="返回记录数上限"),
module_type: Optional[str] = Query(None, description="模块类型筛选: standard/custom"),
case_type: Optional[str] = Query(None, description="用例类型筛选: ui/security/all"),
service: ModuleService = Depends(get_module_service)
):
modules, total = await service.list(
skip=skip, limit=limit, module_type=module_type, case_type=case_type
)
```
#### 2.1.3 修改 `module.py` Schema — 无需修改
ModuleResponse 不需要新增字段,过滤逻辑在查询层完成。
### 2.2 Phase 2: 前端调用传递 case_type
#### 2.2.1 修改 `modules.ts` — API 封装
**文件**: `frontend/src/api/modules.ts`
**改动**: `list` 方法新增 `case_type` 参数:
```typescript
async list(skip = 0, limit = 100, module_type?: string, case_type?: string): Promise<ModuleListResponse> {
const response = await request.get('/api/modules', {
params: { skip, limit, module_type, case_type }
})
return response.data
}
```
#### 2.2.2 修改 `Cases.vue` — 用例管理页面
**文件**: `frontend/src/views/Cases.vue`
**改动**: `loadModules` 函数传递 `case_type=ui`
```typescript
const loadModules = async () => {
try {
const response = await moduleApi.list(0, 100, undefined, 'ui')
modules.value = response.items
} catch (error: any) {
console.error('加载模块列表失败:', error)
}
}
```
#### 2.2.3 修改 `Recorder.vue` — 用例录制页面
**文件**: `frontend/src/views/Recorder.vue`
**改动**: `loadModules` 函数传递 `case_type=ui`
```typescript
const loadModules = async () => {
try {
const response = await moduleApi.list(0, 100, undefined, 'ui')
modules.value = response.items
// ... 后续逻辑不变
} catch (error: any) {
ElMessage.error('加载模块列表失败: ' + error.message)
}
}
```
#### 2.2.4 修改 `Modules.vue` — 模块管理页面(如有模块筛选器)
**文件**: `frontend/src/views/Modules.vue`
需检查是否也有同样的模块列表加载问题。如有,同样传递 `case_type=ui`
### 2.3 Phase 3: 验证
1. 调用 `/api/modules?case_type=ui` 验证只返回 UI 测试模块
2. 调用 `/api/modules?case_type=security` 验证只返回安全测试模块
3. 调用 `/api/modules` 验证返回全部模块(向后兼容)
4. 前端用例管理页面模块筛选器验证不显示安全测试模块
---
## 三、代码变更清单
| 文件 | 变更类型 | 说明 |
|------|---------|------|
| `backend/app/services/module_service.py` | 修改 | `list` 方法新增 `case_type` 参数 |
| `backend/app/routers/modules.py` | 修改 | `list_modules` 新增 `case_type` 查询参数 |
| `frontend/src/api/modules.ts` | 修改 | `list` 方法新增 `case_type` 参数 |
| `frontend/src/views/Cases.vue` | 修改 | `loadModules` 传递 `case_type='ui'` |
| `frontend/src/views/Recorder.vue` | 修改 | `loadModules` 传递 `case_type='ui'` |
---
## 四、验证方案
### 4.1 API 验证
```bash
# 验证 UI 测试模块过滤
curl -s "http://localhost:8001/api/modules?case_type=ui" | python -c "import json,sys; d=json.load(sys.stdin); print(f'UI模块数: {d[\"total\"]}'); [print(f' {m[\"name\"]}') for m in d['items']]"
# 验证安全测试模块过滤
curl -s "http://localhost:8001/api/modules?case_type=security" | python -c "import json,sys; d=json.load(sys.stdin); print(f'安全模块数: {d[\"total\"]}'); [print(f' {m[\"name\"]}') for m in d['items']]"
# 验证向后兼容(无参数返回全部)
curl -s "http://localhost:8001/api/modules" | python -c "import json,sys; d=json.load(sys.stdin); print(f'全部模块数: {d[\"total\"]}')"
```
### 4.2 前端验证
- 用例管理页面模块筛选器不显示安全测试模块
- 用例录制页面模块选择器不显示安全测试模块
\ No newline at end of file
此差异已折叠。
......@@ -48,24 +48,31 @@ async def list_modules(
skip: int = Query(0, ge=0, description="跳过的记录数"),
limit: int = Query(100, ge=1, le=500, description="返回记录数上限"),
module_type: Optional[str] = Query(None, description="模块类型筛选: standard/custom"),
case_type: Optional[str] = Query(None, description="用例类型筛选: ui/security/all"),
service: ModuleService = Depends(get_module_service)
):
"""
获取模块列表
支持分页查询,按排序号升序返回,可按模块类型筛选。
支持分页查询,按排序号升序返回,可按模块类型或用例类型筛选。
Args:
skip (int): 跳过的记录数
limit (int): 返回记录数上限
module_type (Optional[str]): 模块类型筛选 standard/custom
case_type (Optional[str]): 用例类型筛选 ui/security/all
- ui: 只返回 UI 测试模块
- security: 只返回安全测试模块
- all 或不传: 返回全部模块
service (ModuleService): 模块服务实例
Returns:
ModuleListResponse: 模块列表响应
"""
try:
modules, total = await service.list(skip=skip, limit=limit, module_type=module_type)
modules, total = await service.list(
skip=skip, limit=limit, module_type=module_type, case_type=case_type
)
# 转换为响应格式
items = [
......
......@@ -61,6 +61,7 @@ class ModuleService:
limit: int = 100,
order_by: str = "order",
module_type: Optional[str] = None,
case_type: Optional[str] = None,
) -> Tuple[List[Module], int]:
"""
获取模块列表(分页)
......@@ -72,19 +73,31 @@ class ModuleService:
limit (int): 返回记录数上限,默认100
order_by (str): 排序字段,默认 "order"
module_type (Optional[str]): 模块类型筛选 (standard/custom)
case_type (Optional[str]): 用例类型筛选 (ui/security/all)
- ui: 只返回 UI 测试模块(ID不以 sec_ 开头)
- security: 只返回安全测试模块(ID以 sec_ 开头)
- all 或 None: 返回全部模块
Returns:
Tuple[List[Module], int]: (模块列表, 总数)
Example:
>>> modules, total = await service.list(skip=0, limit=20, module_type="standard")
>>> print(f"共 {total} 个模块")
>>> modules, total = await service.list(skip=0, limit=20, case_type="ui")
>>> print(f"共 {total} 个UI测试模块")
"""
# 构建查询条件
conditions = []
if module_type:
conditions.append(Module.module_type == module_type)
# 按用例类型过滤模块(通过模块ID前缀区分)
if case_type == "ui":
# UI测试模块:ID不以 sec_ 开头
conditions.append(~Module.id.startswith("sec_"))
elif case_type == "security":
# 安全测试模块:ID以 sec_ 开头
conditions.append(Module.id.startswith("sec_"))
# 查询总数
count_query = select(func.count(Module.id))
if conditions:
......
此差异已折叠。
......@@ -15,11 +15,14 @@ import type { Module, ModuleListResponse, CreateModuleRequest, UpdateModuleReque
export const moduleApi = {
/**
* 获取模块列表
* @param skip 跳过的记录数
* @param limit 返回记录数上限
* @param module_type 模块类型筛选 standard/custom
* @param case_type 用例类型筛选 ui/security/all
*/
async list(skip = 0, limit = 100, module_type?: string): Promise<ModuleListResponse> {
async list(skip = 0, limit = 100, module_type?: string, case_type?: string): Promise<ModuleListResponse> {
const response = await request.get('/api/modules', {
params: { skip, limit, module_type }
params: { skip, limit, module_type, case_type }
})
return response.data
},
......
......@@ -542,7 +542,8 @@ const commonTags = ['登录', '核心流程', '回归测试', '冒烟测试', '
const loadModules = async () => {
try {
const response = await moduleApi.list()
// 只加载 UI 测试模块,过滤掉安全测试模块
const response = await moduleApi.list(0, 100, undefined, 'ui')
modules.value = response.items
} catch (error: any) {
console.error('加载模块列表失败:', error)
......
......@@ -318,10 +318,11 @@ const assertion = ref({
/**
* 加载模块列表
* 只加载 UI 测试模块,过滤掉安全测试模块
*/
const loadModules = async () => {
try {
const response = await moduleApi.list()
const response = await moduleApi.list(0, 100, undefined, 'ui')
modules.value = response.items
if (modules.value.length > 0) {
recorderForm.value.moduleId = modules.value[0].id
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论