切换主题
从页面到数据库:计量单位名称编辑
本教程沿当前 Nuxt UI 宿主的真实功能,完成一次“查询 → 打开记录 → 修改名称 → 校验 → 保存 → 重新读取”。你将知道每一步由哪段代码负责,以及后续修改应当落在哪里。
本教程不是新增、删除、启停的完整 CRUD 教程。 新宿主当前这条路径只修改名称;编码只读,启用状态通过独立后端操作维护。不要为跟做教程扩大这个页面的写入范围。
1. 准备一条可以修改的记录
先按快速开始运行后端和新宿主,使用实际本地账号登录。账号需要拥有计量单位 Query 和 Edit 权限;Host 或租户身份必须与测试记录所在范围对应。
打开 /measurement-units,选择一条有明确测试用途且允许修改的记录。没有记录时,由有权限的管理员通过现有创建入口准备,不直接改数据库、植入演示数据或自动授予权限。
记下原名称。只修改本轮有权操作的测试记录,完成后通过同一页面恢复原名称并重新读取确认;不要批量清库。
2. 按这条路径操作
| 操作 | 预期观察 | 主要代码位置 |
|---|---|---|
| 搜索名称或编码,切换页码 | 请求携带筛选与分页,返回记录及总数 | MeasurementUnits.vue → service.ts:list |
| 点击编辑 | 重新请求当前记录,不把列表行直接当作权威编辑数据 | editor.ts:edit → service.ts:edit |
| 修改名称后取消 | 不发送更新请求 | editor.ts:cancel 与 modal.ts 的关闭保护 |
| 清空名称并保存 | 输入校验阻止无效提交,保留当前编辑状态 | 生成的 UpdateMeasuringUnitRequest 校验 |
| 输入合法名称并保存 | 只提交记录标识和名称 | editor.ts:save → service.ts:save |
| 保存返回后 | 重新读取记录,再刷新原列表;不是仅显示一条成功提示 | 同一次 save 的回读与刷新分支 |
| 刷新页面、重新打开记录 | 显示服务端保存的实际名称 | 再次经过查询或 GetForEdit |
有其他未保存任务时,关闭、刷新等操作还要遵守外壳的 dirty/busy 协调;外壳不能替这个 feature 保存第二份草稿。
3. 源码地图
以下路径相对于仓库根目录。表格中的函数名用于定位现有实现,不是要求把这些文件复制到另一套 Runtime。
| 层 | 文件或目录 |
|---|---|
| 页面、查询与呈现 | apps/yoyo-admin/admin-nuxtui/src/features/measurement-units/MeasurementUnits.vue |
| 编辑草稿、提交与回读 | 同目录的 editor.ts |
| 业务 API 适配 | 同目录的 service.ts |
| 会话与请求接线 | apps/yoyo-admin/admin-nuxtui/src/integrations/abp/auth/client.ts、session.ts |
| 生成的请求方法 | apps/yoyo-admin/api-client/src/generated/endpoints/measuring-unit/measuring-unit.ts |
| 生成 DTO 与输入校验 | 同一客户端的 src/generated/model/、src/generated/zod/endpoints/yoyoAdminAPI.schemas.zod.ts |
| 请求执行与解包 | 同一客户端的 src/runtime/fetcher.ts |
| 后端入口 | apps/yoyo-admin/aspnet-core/src/Yoyo.Admin.Application/MeasuringUnits/MeasuringUnitAppService.cs |
| 输入与输出 DTO | 同一个 MeasuringUnits/ 目录 |
| 领域输入规则与实体 | apps/yoyo-admin/aspnet-core/src/Yoyo.Admin.Core/BasicData/MeasuringUnits/MeasuringUnitRules.cs、MeasuringUnit.cs |
| EF 与数据库迁移 | apps/yoyo-admin/aspnet-core/src/Yoyo.Admin.EntityFrameworkCore/ |
@api 在新宿主 Vite 配置中指向现有唯一客户端。它复用生成边缘,不导入旧业务页。不要再生成一个 admin-nuxtui/api-client 副本。
4. 从页面发出查询
页面从 useSession() 得到当前会话,再把 session.fetcher 传给 createMeasurementUnitService。组件不自行读取令牌、拼接租户请求头或解析 ABP 响应。
service.ts:list 调用生成方法 apiServicesAppMeasuringunitGetlistGet,提供 FilterText、SkipCount、MaxResultCount。当前该页面按每页 20 条计算偏移。结果经过现有解包接口,页面使用 items 和 totalCount 更新列表。
后端 GetList 检查 Query 权限,规范化输入,按名称/编码筛选并分页读取仓储。实体具有租户字段,读取依赖后端既有数据范围;页面不通过临时修改租户标识来扩大查询。
调整搜索框或列的位置,只改页面呈现。改变服务端查询字段或排序合同,则先修改后端,再沿生成流程更新前端。
5. 打开记录,建立编辑基线
editor.ts:edit 先检查编辑资格与当前任务状态,再调用 GetForEdit。后端根据是否提供 id 区分 Create 或 Edit 权限;本教程始终提供现有记录 id。
后端重新读取记录并映射编辑 DTO。新宿主缺少有效记录 id 时会拒绝打开,不将空对象当作可保存的记录。取得数据后才填入草稿和名称基线。
这一步说明:列表用于浏览,编辑前再读取当前记录。 列表可能已经过时,不能仅复制一行数据就认为取得了最新编辑状态。
6. 只提交这次操作允许修改的字段
页面使用生成的 UpdateMeasuringUnitRequest 校验,提交形状如下。这里的 id 要来自实际 GetForEdit 结果,不使用示例标识调用接口。
json
{
"measuringUnit": {
"id": "<当前记录的实际 id>",
"name": "修改后的测试名称"
}
}前端在提交前检查输入,并使用生成的 apiServicesAppMeasuringunitCreateorupdatePost。service.ts 不把整个展示对象直接发送;编码与启用状态没有进入名称编辑请求。
后端 CreateOrUpdate 根据 id 进入 UpdateAsync。后者再次检查 Edit 权限,读取目标记录,并明确拒绝请求中的 Code 和 Enabled:编码创建后不可修改,状态应通过独立命令修改。
MeasuringUnitRules.NormalizeName 处理首尾空白、必填与最大长度,随后通过仓储更新并调用当前工作单元的 SaveChangesAsync。真正的数据写入发生在后端,不是修改前端表格数组。
前端校验便于及时反馈;后端规则才是无法绕过的最终检查。不要为前端显示不同而复制另一套名称长度常量或放宽后端授权。
7. 区分写入失败和回读失败
写入返回后,编辑任务先记录“已提交”,再调用 GetForEdit 和列表刷新。只有这些步骤成功,才完成本次编辑。
| 结果 | 应怎样处理 | 不能做什么 |
|---|---|---|
| 前端输入无效 | 提示字段错误,保留输入,不发送写请求 | 清空表单或伪装成成功 |
| 后端校验/写入失败 | 将现有错误转换为页面及字段提示,保留草稿 | 因失败自动补权限、改配置或丢弃输入 |
| 写入成功,记录或列表回读失败 | 明确提示已提交,仅重试读取;当前任务不重复写入 | 再次点击后又发送同一更新 |
| 权限不足 | 展示受控拒绝,使用已有平台与配置处理 | 把 403 当作空列表或自动切换到另一个身份 |
| 页面或身份已失效 | 旧异步结果不能写回新的任务 | 用迟到响应恢复旧草稿或身份 |
弹窗保护由同目录 modal.ts 接入共享 Modal helper;草稿与提交仍可在 editor.ts 的 savedPendingRead、修订标识与释放分支中定位。它们保护这次任务,不是另一个独立的认证系统。服务器错误由现有 transport/错误适配处理,页面不逐个判断 ABP envelope。
8. 后续需求应该改哪里
| 需求 | 修改位置与约束 |
|---|---|
| 调整标题、列顺序、输入宽度 | 页面组件;直接采用 Nuxt UI 公开配置,不重生成客户端 |
| 修改名称的领域规则 | 后端规则/DTO及受影响测试;合同发生变化后再更新生成边缘 |
| 新增一种查询条件 | 后端输入与查询 → OpenAPI/客户端 → service 与页面,保持同一字段合同 |
| 为页面增加启停操作 | 先核对已有 SetEnabled 合同与权限,显式接入独立动作;不混入名称更新 |
| 改成配置化标准工作台 | 评估现有 Schema 的适用资源形状,使用唯一 compiler 和现有作者入口,不另造页面 DSL |
生成字段与接口只从生产者/生成器修改,不能直接编辑 generated 目录。接口未变化时,不为纯 UI 改动运行合同刷新。
9. 如何验证自己的修改
下面两个命令块各自从仓库根目录开始。进入新宿主后执行类型、lint 和受影响测试;这里只给现有入口,不要求每次改文案都重跑整个后端:
powershell
Set-Location apps/yoyo-admin/admin-nuxtui
pnpm typecheck
pnpm lint
pnpm test -- tests/editor.spec.ts tests/integration.spec.ts实际改到后端规则时,检查后端 test/Yoyo.Admin.Tests/BasicData/ 下的 MeasuringUnitManagementTests.cs、MeasuringUnitTenantManagementTests.cs 和 MeasuringUnitRulesTests.cs,按后端 README 的测试层次运行受影响用例。
需要证明浏览器保存与真实回读时,沿用已运行的本地前后端与正式测试工程:
powershell
Set-Location apps/yoyo-admin/ui-tests-playwright
pnpm test -- tests/basic-data/measuring-units/measuring-units-nuxtui.real.spec.ts浏览器测试须使用本地测试配置;测试会执行真实操作,先确认环境。测试文件存在不等于你当前源码已经通过,本教程也不把历史通过记录当作本次重新执行结果。