From ff345dc42a006100074ac72861f8588564491eee Mon Sep 17 00:00:00 2001 From: czl231 <3286836406@qq.com> Date: Tue, 11 Aug 2026 02:01:00 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=BB=9F=E4=B8=80=E8=B4=A6=E6=88=B7?= =?UTF-8?q?=E8=A7=92=E8=89=B2=E5=B1=95=E7=A4=BA=E5=B9=B6=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E8=B5=84=E6=BA=90=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../internal/logic/platform/gas/account.go | 23 +++++- .../logic/platform/gas/account_test.go | 19 +++++ docs/05-平台总后台需求.md | 10 ++- docs/06-气站管理系统需求.md | 3 + docs/07-配送点管理系统需求.md | 3 + ...作日志_标准资源编辑页提示精简_20260811.md | 37 ++++++++++ ...作日志_标准资源详情字段布局优化_20260811.md | 39 ++++++++++ ...日志_账户角色中文展示与摘要统一_20260811.md | 57 ++++++++++++++ docs/项目文档_标准资源全页管理_v1.0.md | 11 ++- frontend/delivery_admin/src/api/platform.ts | 2 +- frontend/delivery_admin/src/api/resources.ts | 23 +++++- .../src/views/shared/CrudListPage.vue | 53 +++++++++++-- frontend/gas_admin/src/api/platform.ts | 2 +- frontend/gas_admin/src/api/resources.ts | 23 +++++- .../src/views/shared/CrudListPage.vue | 53 +++++++++++-- frontend/platform_admin/package.json | 1 + .../check-account-role-presentation.mjs | 74 +++++++++++++++++++ frontend/platform_admin/src/api/platform.ts | 2 +- .../src/api/resource-display.ts | 10 ++- .../src/api/resource-page-rules.ts | 3 +- .../src/api/resource-record-form.ts | 2 +- frontend/platform_admin/src/api/resources.ts | 25 ++++++- .../views/resource/ResourceAccountSummary.vue | 20 ++++- .../views/resource/ResourceDetailContent.vue | 20 +++-- .../src/views/resource/ResourceFieldForm.vue | 30 +++++--- .../views/resource/ResourceRecordPage.less | 3 +- .../src/views/resource/ResourceRecordPage.vue | 40 +++++++--- .../src/views/shared/CrudListPage.vue | 43 ++++++++++- 28 files changed, 555 insertions(+), 76 deletions(-) create mode 100644 backend/api/internal/logic/platform/gas/account_test.go create mode 100644 docs/操作日志_标准资源编辑页提示精简_20260811.md create mode 100644 docs/操作日志_标准资源详情字段布局优化_20260811.md create mode 100644 docs/操作日志_账户角色中文展示与摘要统一_20260811.md create mode 100644 frontend/platform_admin/scripts/check-account-role-presentation.mjs diff --git a/backend/api/internal/logic/platform/gas/account.go b/backend/api/internal/logic/platform/gas/account.go index d99b1ae..8d8d54e 100644 --- a/backend/api/internal/logic/platform/gas/account.go +++ b/backend/api/internal/logic/platform/gas/account.go @@ -12,18 +12,33 @@ import ( "gorm.io/gorm" ) +// gasAdminRoleCode 是气站管理后台当前唯一允许登录的角色编码。 +const gasAdminRoleCode = "admin" + +// newGasAccount 构造平台创建的气站账户,并固定为气站管理员角色。 +func newGasAccount(gasBasicID uint64, request accountRequest, passwordHash string) models.GasAccount { + return models.GasAccount{ + Entity: common.NewEntity(common.StatusEnable), + GasBasicID: gasBasicID, + Username: request.Username, + DisplayName: request.DisplayName, + PasswordHash: passwordHash, + RoleCode: gasAdminRoleCode, + } +} + type accountRequest struct { Username string `json:"username" binding:"required,max=64"` Password string `json:"password" binding:"required"` DisplayName string `json:"display_name" binding:"max=64"` - RoleCode string `json:"role_code" binding:"max=64"` + RoleCode string `json:"role_code" binding:"max=64"` // 兼容旧客户端,服务端固定使用 admin。 GasBasicIdentity string `json:"gas_basic_identity"` DeliveryBasicIdentity string `json:"delivery_basic_identity"` } type accountUpdateRequest struct { DisplayName string `json:"display_name" binding:"max=64"` - RoleCode string `json:"role_code" binding:"max=64"` + RoleCode string `json:"role_code" binding:"max=64"` // 兼容旧客户端,更新时不采纳。 GasBasicIdentity string `json:"gas_basic_identity"` DeliveryBasicIdentity string `json:"delivery_basic_identity"` } @@ -63,7 +78,7 @@ func CreateGasAccount(ctx *gin.Context) { infra.Response.Error(ctx, err) return } - account := models.GasAccount{Entity: common.NewEntity(common.StatusEnable), GasBasicID: gasBasicID, Username: request.Username, DisplayName: request.DisplayName, PasswordHash: hash, RoleCode: request.RoleCode} + account := newGasAccount(gasBasicID, request, hash) if err := impl.DBService.Create(&account).Error; err != nil { infra.Response.Error(ctx, err) return @@ -82,7 +97,7 @@ func UpdateGasAccount(ctx *gin.Context) { infra.Response.Error(ctx, errcode.ErrInvalidArgument) return } - common.UpdateAllowedByIdentity(ctx, &models.GasAccount{}, gin.H{"gas_basic_id": gasBasicID, "display_name": request.DisplayName, "role_code": request.RoleCode}, []string{"gas_basic_id", "display_name", "role_code"}) + common.UpdateAllowedByIdentity(ctx, &models.GasAccount{}, gin.H{"gas_basic_id": gasBasicID, "display_name": request.DisplayName}, []string{"gas_basic_id", "display_name"}) } func splitOwnerIdentities(value string) []string { diff --git a/backend/api/internal/logic/platform/gas/account_test.go b/backend/api/internal/logic/platform/gas/account_test.go new file mode 100644 index 0000000..a42f9da --- /dev/null +++ b/backend/api/internal/logic/platform/gas/account_test.go @@ -0,0 +1,19 @@ +package gas + +import "testing" + +// TestNewGasAccountUsesAdminRole 验证旧客户端提交的角色不会改变气站管理员权限。 +func TestNewGasAccountUsesAdminRole(t *testing.T) { + account := newGasAccount( + 9, + accountRequest{ + Username: "gas-admin", + DisplayName: "气站管理员", + RoleCode: "legacy-role", + }, + "password-hash", + ) + if account.RoleCode != gasAdminRoleCode { + t.Fatalf("气站管理员角色编码必须为 %q,实际为 %q", gasAdminRoleCode, account.RoleCode) + } +} diff --git a/docs/05-平台总后台需求.md b/docs/05-平台总后台需求.md index cbdf47a..21044b4 100644 --- a/docs/05-平台总后台需求.md +++ b/docs/05-平台总后台需求.md @@ -114,9 +114,9 @@ 新建和编辑页使用全宽信息卡,内部表单内容最大宽度为 `1440px`,并按内容容器宽度在双列与单列之间切换。页面内容从顶部自然排列,只保留面包屑和右侧返回按钮,不重复展示“新建/编辑资源名称”及操作说明;字段和底部操作按钮保持统一基线。账户头像摘要和详情页展示结构不随该表单布局调整而改变。 -标准详情页同样只保留面包屑、编辑和返回操作,不重复展示“详情资源名称”及说明文字。详情卡片按内容自然高度从顶部排列,统一使用 `12px` 间距和紧凑内边距;基本信息在大屏、中屏和小屏分别采用三列、两列和单列。未开通钱包使用单行提示,气站启停继续保留独立状态管理卡片,不改变原有接口和权限校验。 +标准详情页同样只保留面包屑、编辑和返回操作,不重复展示“详情资源名称”及说明文字。详情卡片按内容自然高度从顶部排列,统一使用 `12px` 间距和紧凑内边距;基本信息在大屏、中屏和小屏分别采用三列、两列和单列。字段标签按文字自然宽度与值保持 `12px` 间距,长标签禁止拆字换行,不使用固定标签列制造多余空白。未开通钱包使用单行提示,气站启停继续保留独立状态管理卡片,不改变原有接口和权限校验。 -新建与编辑使用不同字段规则。唯一标识、用户名、创建编码、不可变归属等创建后锁定字段只读展示且禁止修改;后端更新协议要求原归属标识时,页面只会原样回传该字段。合同状态、检修结果、系统角色和平台权限等限制同时由页面和后端校验。编辑页离开前检测未保存内容,详情页的聚合子表、钱包摘要、气站状态开关及资源专属业务动作继续保留。 +新建与编辑使用不同字段规则。唯一标识、用户名、创建编码、不可变归属等创建后锁定字段以灰色禁用控件展示且禁止修改,不重复显示顶部说明条、字段旁提示或禁用占位文字;后端更新协议要求原归属标识时,页面只会原样回传该字段。合同状态、检修结果、系统角色和平台权限等限制同时由页面和后端校验。编辑页离开前检测未保存内容,详情页的聚合子表、钱包摘要、气站状态开关及资源专属业务动作继续保留。 ### 6.1 机构管理 @@ -129,6 +129,10 @@ 气站只能由平台总后台新增,创建后直接进入启用状态,无需审核。已启用或已停用气站可继续切换启停状态。 +气站账户与配送点账户当前均只有管理员角色。新建时服务端分别固定写入 `admin`,编辑时不允许变更角色;旧客户端继续提交 `role_code` 时服务端兼容接收但不采纳。列表、详情、新建和编辑页面统一显示“角色”,并将 `admin` 显示为“气站管理员”或“配送点管理员”。历史未知编码显示为“未知角色(原编码)”,不得自动改成管理员。 + +气站账户、配送点账户和生产商账户没有头像字段与受控头像接口。它们的详情和编辑页使用紧凑文字账户摘要,新建页直接显示基本信息表单,不展示无法上传或保存的默认头像。工作人员、用户和平台账户继续使用真实头像上传与受控读取链路。 + ### 6.2 工作人员管理 | 资源 | 路径 | 模式 | 已实现能力 | @@ -165,6 +169,8 @@ 智能气阀必须关联生产商和类型,可选关联库房、气站、配送点或用户。生产商登录密码仅保存哈希且不通过资源接口返回;独立生产端登录路由待生产管理系统落地时接入。归属组合由后端校验,不允许形成非法多重归属。生命周期支持待处理、在库、运输中、使用中、维修中和已报废;状态变化使用 `/product_info/:identity/lifecycle`,不能通过通用编辑直接改写。归属变化自动追加归属记录。 +生产商账户当前没有完整角色权限字典。本阶段仅移除无效头像占位,不改变其 `role_code` 写入规则;待生产管理系统明确角色模型后再统一中文角色名称和权限约束。 + ### 6.5 配送合同 | 资源 | 路径 | 模式 | 已实现能力 | diff --git a/docs/06-气站管理系统需求.md b/docs/06-气站管理系统需求.md index 4fc8369..3685c40 100644 --- a/docs/06-气站管理系统需求.md +++ b/docs/06-气站管理系统需求.md @@ -40,6 +40,9 @@ - 气站账号由平台总后台创建;气站端不允许自助创建管理员。 - 仅启用状态、关联启用气站且 `role_code = admin` 的 `gas_account` 可以登录。 +- 平台创建气站账户时固定保存 `role_code = admin`,更新账户时不允许修改角色;旧客户端携带该字段时兼容接收但忽略。 +- 管理页面将 `admin` 显示为“气站管理员”;历史未知编码显示为“未知角色(原编码)”,不自动迁移或提升权限。 +- 气站账户没有头像字段和受控头像接口,账户资料不得展示可操作或可持久化的头像入口。 - JWT 客户端固定为 `gas_admin`,与平台总后台会话隔离。 - 登录后由后端 `gas_menu` 接口按 `role_code` 返回静态菜单,前端据此渲染。 - 修改密码必须校验当前密码;新密码仅校验长度不少于 6 位。 diff --git a/docs/07-配送点管理系统需求.md b/docs/07-配送点管理系统需求.md index aaeb3bd..56bde0d 100644 --- a/docs/07-配送点管理系统需求.md +++ b/docs/07-配送点管理系统需求.md @@ -52,6 +52,9 @@ Global: - 配送点管理员账号由平台或所属气站创建。 - 仅启用、关联启用配送点且 `role_code = admin` 的 `delivery_account` 可以登录。 +- 平台或所属气站创建配送点账户时固定保存 `role_code = admin`,更新账户时不允许修改角色。 +- 三套管理后台统一使用“配送点账户”和“角色”,并将 `admin` 显示为“配送点管理员”;历史未知编码显示为“未知角色(原编码)”。 +- 配送点账户没有头像字段和受控头像接口,不展示无法上传或保存的默认头像。 - JWT 客户端固定为 `delivery_admin`,与平台和气站管理端会话隔离。 - 菜单由后端 `delivery_menu` 接口按 `role_code` 返回,前端登录后据此渲染。 - 修改本人密码必须校验当前密码;新密码只要求不少于 6 位。 diff --git a/docs/操作日志_标准资源编辑页提示精简_20260811.md b/docs/操作日志_标准资源编辑页提示精简_20260811.md new file mode 100644 index 0000000..43f90ef --- /dev/null +++ b/docs/操作日志_标准资源编辑页提示精简_20260811.md @@ -0,0 +1,37 @@ +# 标准资源编辑页提示精简操作日志 + +操作时间:2026-08-11 01:14:16 +操作类型:修改 +影响模块:平台总后台标准资源编辑页 + +## 操作前状态 + +- 编辑页顶部显示“灰色字段为创建后不可修改的信息,不会提交到更新接口”的蓝色说明条。 +- 每个禁用字段旁重复显示“创建后不可修改”,文本会挤压输入框并在窄空间换行。 +- 禁用文本输入框在值为空时仍显示“创建后不可修改”占位文字。 + +## 具体操作 + +- 修改 `frontend/platform_admin/src/views/resource/ResourceRecordPage.vue`,删除编辑页顶部重复说明条。 +- 修改 `frontend/platform_admin/src/views/resource/ResourceFieldForm.vue`,删除禁用字段旁提示和禁用占位文字。 +- 修改 `frontend/platform_admin/src/views/resource/ResourceRecordPage.less`,清理说明条已不再使用的样式选择器。 +- 保留灰色禁用样式、只读字段展示、允许更新字段计算和更新请求过滤逻辑。 + +## 操作后状态 + +- 所有标准资源编辑页直接从字段区域开始,不保留说明条空位。 +- 禁用字段和值继续显示,输入框宽度与同列其他字段一致。 +- 页面不再重复解释不可修改状态,更新安全边界保持不变。 + +## 验证结果 + +- `npm.cmd run type:check`:通过。 +- `npm.cmd run build`:通过,Vite 生产构建完成。 +- `npm.cmd run resource-pages:check`:通过,详情 46 类、新建 25 类、编辑 23 类。 +- `npm.cmd run contract:check`:通过,48 个资源契约一致。 +- 浏览器回归:气站编辑页顶部说明条、字段旁提示和禁用占位文字均已消失;禁用输入框与普通输入框宽度一致,控制台无警告或错误;未执行保存操作。 + +## 风险评估 + +- 本次只删除视觉提示,不改变字段权限、表单值、校验、请求负载或后端接口。 +- 新建页、详情页、业务动作弹窗、气站后台 5175 和配送点后台 5176 不受影响。 diff --git a/docs/操作日志_标准资源详情字段布局优化_20260811.md b/docs/操作日志_标准资源详情字段布局优化_20260811.md new file mode 100644 index 0000000..3826449 --- /dev/null +++ b/docs/操作日志_标准资源详情字段布局优化_20260811.md @@ -0,0 +1,39 @@ +# 标准资源详情字段布局优化操作日志 + +操作时间:2026-08-11 01:21:54 +操作类型:修改 +影响模块:平台总后台标准资源详情页 + +## 操作前状态 + +- 详情字段使用固定 `120px` 标签列,短标签和值之间出现明显空白。 +- “统一社会信用代码”等长中文标签空间不足,会拆字换行并增加行高。 +- 固定标签列在不同字段长度下无法同时兼顾紧凑性和可读性。 + +## 具体操作 + +- 修改 `frontend/platform_admin/src/views/resource/ResourceDetailContent.vue`: + - 标签列改为按文字自然宽度计算。 + - 标签和值之间统一使用 `12px` 间距。 + - 标签禁止换行,值区域继续允许收缩和自动换行。 + - 小屏不再恢复固定 `100px` 标签列。 +- 更新平台需求和标准资源全页管理项目文档。 + +## 操作后状态 + +- 短标签后的多余空白消失,字段值紧邻对应标签。 +- 长中文标签保持单行,不再出现单字换行。 +- 大屏三列、中屏两列、小屏单列及字段分隔线保持不变。 + +## 验证结果 + +- `npm.cmd run type:check`:通过。 +- `npm.cmd run build`:通过,Vite 生产构建完成。 +- `npm.cmd run resource-pages:check`:通过,详情 46 类、新建 25 类、编辑 23 类。 +- `npm.cmd run contract:check`:通过,48 个资源契约一致。 +- 浏览器回归:“唯一标识”和“统一社会信用代码”标签与值的实际间距均为 `12px`,长标签保持单行;`700px` 小屏使用单列且无水平溢出,控制台无警告或错误。 + +## 风险评估 + +- 本次仅调整详情字段 CSS,不修改字段顺序、格式化、唯一标识复制、接口或权限逻辑。 +- 聚合子表、钱包、状态管理、编辑页、新建页及其他管理端保持原状。 diff --git a/docs/操作日志_账户角色中文展示与摘要统一_20260811.md b/docs/操作日志_账户角色中文展示与摘要统一_20260811.md new file mode 100644 index 0000000..1369501 --- /dev/null +++ b/docs/操作日志_账户角色中文展示与摘要统一_20260811.md @@ -0,0 +1,57 @@ +# 操作日志:账户角色中文展示与摘要统一 + +操作时间:2026-08-11 01:47:12 + +操作类型:修改、扩展 + +影响模块:平台总后台、气站后台、配送点后台、平台账户接口 + +## 操作前状态 + +- 配送点账户曾实现“配送点管理员”中文展示,但标准资源独立页面改造后退回“角色编码 / admin”。 +- 气站登录只允许 `admin`,平台创建和更新接口却仍接受任意角色编码,可能产生无法登录的账户。 +- 气站、配送点和生产商账户没有头像字段或受控头像接口,平台页面仍展示默认头像占位。 +- 平台账户编辑下拉使用角色名称,但列表和详情仍可能显示原始角色编码。 + +## 具体操作 + +1. 为气站和配送点账户增加资源级固定角色元数据,统一显示“角色”“气站管理员”“配送点管理员”。 +2. 气站账户创建强制写入 `admin`,更新不再修改角色;保留旧请求字段用于兼容但不采纳。 +3. 历史未知角色统一显示为“未知角色(原编码)”,不执行数据库迁移,不自动扩大权限。 +4. 平台账户列表和详情加载动态角色名称,用角色名称替代裸编码。 +5. 无真实头像能力的账户隐藏头像列并使用文字摘要;新建页不展示空的唯一标识和创建时间。具备头像接口的工作人员、用户和平台账户保持原功能。 +6. 气站后台和配送点后台的账户管理弹层同步使用中文只读角色,并停止向账户更新接口提交角色字段。 + +## 代码变更 + +- `backend/api/internal/logic/platform/gas/account.go`:固定气站管理员角色并禁止更新角色。 +- `backend/api/internal/logic/platform/gas/account_test.go`:验证旧角色字段不能改变管理员角色。 +- `frontend/platform_admin/src/api/`:增加固定角色、未知角色和动态平台角色显示能力。 +- `frontend/platform_admin/src/views/resource/`:按真实头像能力切换头像摘要或文字摘要。 +- `frontend/gas_admin/src/`、`frontend/delivery_admin/src/`:统一账户角色中文名称和只读行为。 +- `frontend/platform_admin/scripts/check-account-role-presentation.mjs`:静态检查三套后台的角色与摘要规则。 + +## 行为变化 + +| 场景 | 修改前 | 修改后 | +| --- | --- | --- | +| 配送点账户角色 | “角色编码 / admin” | “角色 / 配送点管理员” | +| 气站账户角色 | 可输入任意编码 | 固定“气站管理员”,后端保存 `admin` | +| 历史未知角色 | 直接显示裸编码 | 显示“未知角色(原编码)”,不自动修改 | +| 无头像账户 | 显示不可操作默认头像 | 详情、编辑使用文字摘要;新建直接进入表单 | +| 平台账户角色 | 列表和详情可能显示编码 | 使用动态平台角色名称 | + +## 验证结果 + +- 平台总后台、气站后台、配送点后台 TypeScript 类型检查和生产构建全部通过。 +- 三套后台资源契约检查通过;标准资源页面检查通过:详情 46 类、新建 25 类、编辑 23 类。 +- 账户角色静态检查通过,确认三套后台中文角色、未知角色和头像摘要规则均已覆盖。 +- 后端 `go test ./...` 全量测试通过,包含新增气站管理员角色约束测试。 +- 本地浏览器已验证应用可正常进入登录页;数据页视觉回归因当前测试会话未登录而未执行,未使用或提交本地默认密码。 + +## 风险评估 + +- 不迁移历史非 `admin` 记录,避免静默赋予管理员权限;管理员需根据“未知角色”提示单独核查。 +- 气站账户从本次变更起无法创建新角色,符合当前登录与菜单仅支持 `admin` 的既有约束。 +- 生产商角色模型尚未明确,本次不修改其角色写入规则。 +- 本次不新增气站、配送点或生产商头像字段,因此不产生数据库迁移和孤儿上传文件。 diff --git a/docs/项目文档_标准资源全页管理_v1.0.md b/docs/项目文档_标准资源全页管理_v1.0.md index 78c6223..b98d302 100644 --- a/docs/项目文档_标准资源全页管理_v1.0.md +++ b/docs/项目文档_标准资源全页管理_v1.0.md @@ -69,10 +69,10 @@ platforms/ - 详情页顶部只保留“列表 / 详情”面包屑、编辑和返回操作,不重复展示“详情资源名称”及说明文字。 - 页面网格从顶部按内容自然排列,详情卡片统一使用 `12px` 间距、圆角、标题高度和内容内边距,不随剩余视口高度拉伸。 -- 普通资源使用响应式三列信息区,金额、状态、日期、布尔和关系字段统一格式化。 +- 普通资源使用响应式三列信息区;字段标签按文字自然宽度与值保持 `12px` 间距,长标签保持单行,避免短标签后留白或中文标签拆字换行;金额、状态、日期、布尔和关系字段统一格式化。 - 聚合详情中的数组继续以页签和表格展示,例如合同产品、修订记录和订单轨迹。 - 气站详情保留独立的紧凑启停区域;钱包归属资源保留钱包摘要和钱包详情入口,未开通钱包时显示单行紧凑提示。 -- 工作人员、用户和平台账户保留头像、用户名、唯一标识、创建时间的账户摘要。 +- 工作人员、用户和平台账户保留头像、用户名、唯一标识、创建时间的账户摘要;气站、配送点和生产商账户仅展示紧凑文字摘要,不显示无数据能力的装饰头像。 - 资源专属流程动作继续使用短模态框,危险动作显示风险提示,平台角色菜单分配保留专属适配。 ### 4.3 新建与编辑 @@ -80,8 +80,8 @@ platforms/ - 新建和编辑卡片铺满主内容区,卡片内部使用最大 `1440px` 的内容容器控制输入框行长;标题、字段和操作按钮保持同一左基线。 - 表单根据容器实际宽度响应:内容区达到约 `900px` 时使用双列,否则切换为单列;地址、备注、条款、参数和正文等长字段独占整行。 - 页面网格从顶部自然排列;新建、编辑页只保留“列表 / 当前操作”面包屑和右侧返回按钮,不重复展示操作大标题及说明文字;保存和取消按钮位于表单末尾,不吸附浏览器底部。 -- 账户类资源继续保留头像和身份摘要的居中结构,详情页布局不受表单优化影响。 -- 编辑页展示创建后不可修改字段,但禁用字段不会进入更新请求。 +- 具备受控头像接口的账户继续保留头像和身份摘要;没有头像能力的账户在新建页直接进入表单,在编辑页使用紧凑文字摘要。 +- 编辑页继续以禁用控件展示创建后不可修改字段,不额外显示说明条、字段旁提示或禁用占位文字;禁用字段不会进入更新请求。 - 必填、密码最短 6 位、关系选项和金额转换复用统一校验与负载构建逻辑。 - 页面检测表单和头像变更;返回、取消或浏览器路由离开时均提示是否放弃未保存内容。 - 机构“账户管理”不再打开二级模态框,而是进入带机构过滤条件的隐藏账户列表及其独立 CRUD 页面。 @@ -91,6 +91,8 @@ platforms/ - 详情始终调用现有受保护资源接口,不使用列表缓存绕过脱敏和对象权限。 - 头像继续通过专用上传与受控读取接口;平台账户补充同等头像读取能力。 - 平台账户普通编辑没有提交头像时保持原值,避免更新其他资料时意外清空头像。 +- 气站和配送点账户的 `admin` 分别显示为“气站管理员”和“配送点管理员”,表单只读;历史未知编码保留并显示明确提示,不做自动权限迁移。 +- 平台账户列表和详情使用动态平台角色名称,不直接暴露角色编码;无法匹配时显示“未知角色(原编码)”。 - `return_to` 拒绝协议相对地址和站外地址。 - 附件查看未接入:现有通用响应会剥离敏感 URI,待受控下载接口完成后再扩展。 @@ -112,6 +114,7 @@ platforms/ ```powershell npm.cmd run resource-pages:check +npm.cmd run account-roles:check npm.cmd run contract:check npm.cmd run build ``` diff --git a/frontend/delivery_admin/src/api/platform.ts b/frontend/delivery_admin/src/api/platform.ts index bbdda98..57670f5 100644 --- a/frontend/delivery_admin/src/api/platform.ts +++ b/frontend/delivery_admin/src/api/platform.ts @@ -33,7 +33,7 @@ export type PlatformMenu = { identity: string; parent_identity?: string; group_c export const platformApi = { overview: () => request('/dashboard/overview'), listAccount: () => request<{ total: number; list: Record[] }>('/platform_account'), - listRole: () => resourceApi.list('/platform_role'), + listRole: () => resourceApi.list('/platform_role', 1, 100), createRole: (data: Record) => resourceApi.create('/platform_role', data), listMenu: () => request<{ total: number; list: PlatformMenu[] }>('/delivery_menu'), listRoleMenuIdentities: (identity: string) => diff --git a/frontend/delivery_admin/src/api/resources.ts b/frontend/delivery_admin/src/api/resources.ts index 96aa09b..af7f685 100644 --- a/frontend/delivery_admin/src/api/resources.ts +++ b/frontend/delivery_admin/src/api/resources.ts @@ -25,6 +25,9 @@ export type ResourceField = { required?: boolean; relation?: string; options?: Array<{ label: string; value: string | number }>; + defaultValue?: string | number | boolean; + readonly?: boolean; + unknownValueLabel?: string; }; export type DetailAction = { @@ -63,7 +66,7 @@ const fieldLabels: Record = { username: '用户名', password: '密码', display_name: '显示名称', - role_code: '角色编码', + role_code: '角色', platform_role_code: '平台角色', credit_code: '统一社会信用代码', principal: '负责人', @@ -272,6 +275,18 @@ function relation(key: string, resource: string, required = false): ResourceFiel return f(key, { type: 'identity', relation: resource, required }); } +/** 创建固定管理员角色字段,确保页面仅展示后端支持的角色。 */ +function fixedAdminRole(label: string): ResourceField { + return f('role_code', { + type: 'select', + required: true, + options: [{ label, value: 'admin' }], + defaultValue: 'admin', + readonly: true, + unknownValueLabel: '未知角色', + }); +} + function define( name: string, title: string, @@ -310,9 +325,9 @@ const reason = [f('reason', { required: true })]; const platformResources: ResourceUiDefinition[] = [ { ...define('gas_basic', '气站管理', 'writable', [f('code', { required: true }), f('name', { required: true }), f('credit_code'), f('principal'), f('address'), f('longitude'), f('latitude')]), accountManagement: { resource: '/gas_account', relationKey: 'gas_basic_identity', title: '气站账户' }, walletOwnerType: 'gas' }, - define('gas_account', '气站账户', 'writable', [f('username', { required: true }), f('password', { required: true }), f('display_name'), f('role_code'), relation('gas_basic_identity', '/gas_basic', true)]), + define('gas_account', '气站账户', 'writable', [f('username', { required: true }), f('password', { required: true }), f('display_name'), fixedAdminRole('气站管理员'), relation('gas_basic_identity', '/gas_basic', true)]), { ...define('delivery_basic', '配送点管理', 'writable', [f('delivery_code', { required: true }), f('name', { required: true }), relation('gas_basic_identity', '/gas_basic'), f('principal'), f('address')]), accountManagement: { resource: '/delivery_account', relationKey: 'delivery_basic_identity', title: '配送点账户' }, walletOwnerType: 'delivery' }, - define('delivery_account', '配送站账户', 'writable', [f('username', { required: true }), f('password', { required: true }), f('display_name'), f('role_code'), relation('delivery_basic_identity', '/delivery_basic', true)]), + define('delivery_account', '配送点账户', 'writable', [f('username', { required: true }), f('password', { required: true }), f('display_name'), fixedAdminRole('配送点管理员'), relation('delivery_basic_identity', '/delivery_basic', true)]), { ...define('staff_account', '工作人员', 'writable', [f('username', { required: true }), f('password', { required: true }), f('name', { required: true }), f('phone'), f('avatar'), f('role_code', { required: true, type: 'select', options: [{ label: '安装人员', value: 'installer' }, { label: '配送人员', value: 'delivery' }, { label: '运维人员', value: 'operations' }] }), relation('gas_basic_identity', '/gas_basic'), relation('delivery_basic_identity', '/delivery_basic'), f('work_status', { type: 'select', options: [{ label: '在岗', value: 'on_duty' }, { label: '离岗', value: 'off_duty' }] })]), walletOwnerType: 'staff' }, define('staff_credential', '工作人员资质', 'writable', [relation('staff_account_identity', '/staff_account', true), f('credential_type', { required: true }), f('credential_no'), f('expired_at')]), { ...define('user_account', '用户账户', 'writable', [f('username', { required: true }), f('password', { required: true }), f('name', { required: true }), f('phone'), f('avatar'), f('real_name')]), walletOwnerType: 'user' }, @@ -409,7 +424,7 @@ const platformResources: ResourceUiDefinition[] = [ const gasOverrides: ResourceUiDefinition[] = [ { ...define('delivery_basic', '配送点管理', 'writable', [f('delivery_code', { required: true }), f('name', { required: true }), f('principal'), f('address')]), accountManagement: { resource: '/delivery_account', relationKey: 'delivery_basic_identity', title: '配送点账户' } }, - define('delivery_account', '配送点账户', 'writable', [f('username', { required: true }), f('password', { required: true }), f('display_name')], 'list', [ + define('delivery_account', '配送点账户', 'writable', [f('username', { required: true }), f('password', { required: true }), f('display_name'), fixedAdminRole('配送点管理员')], 'list', [ { name: '重置密码', resource: '/delivery_account/:identity/password', method: 'PUT', fields: [f('password', { required: true })] }, ]), define('staff_account', '工作人员', 'writable', [f('username', { required: true }), f('password', { required: true }), f('name', { required: true }), f('phone'), f('avatar'), f('role_code', { required: true, type: 'select', options: [{ label: '安装人员', value: 'installer' }, { label: '配送人员', value: 'delivery' }, { label: '运维人员', value: 'operations' }] }), relation('delivery_basic_identity', '/delivery_basic'), f('work_status', { type: 'select', options: [{ label: '在岗', value: 'on_duty' }, { label: '离岗', value: 'off_duty' }] })], 'list', [ diff --git a/frontend/delivery_admin/src/views/shared/CrudListPage.vue b/frontend/delivery_admin/src/views/shared/CrudListPage.vue index 49aa9a4..78e4347 100644 --- a/frontend/delivery_admin/src/views/shared/CrudListPage.vue +++ b/frontend/delivery_admin/src/views/shared/CrudListPage.vue @@ -102,7 +102,9 @@ - + + +