From 2e2c1a35dd7d40ed296d507e29db3647c8bc7c3d Mon Sep 17 00:00:00 2001 From: czl231 <3286836406@qq.com> Date: Sat, 22 Aug 2026 21:10:22 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E9=85=8D=E9=80=81=E7=AB=AF?= =?UTF-8?q?=E8=B4=A6=E6=88=B7=E5=A4=B4=E5=83=8F=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/api/internal/logic/delivery/staff.go | 42 ++++++-- backend/api/internal/logic/delivery/user.go | 41 ++++++-- backend/api/internal/routers/delivery.go | 2 + backend/api/internal/routers/delivery_test.go | 2 + docs/操作日志_配送点独立资源页面_20260822.md | 5 +- docs/项目文档_配送点独立资源页面_v1.0.md | 4 + .../scripts/check-resource-pages.mjs | 5 + frontend/delivery_admin/src/api/avatar.ts | 50 ++++++++++ .../src/contracts/delivery-resources.json | 2 +- .../views/resource/ResourceAccountSummary.vue | 98 +++++++++++++++++++ .../views/resource/ResourceDetailContent.vue | 3 + .../src/views/resource/ResourceRecordPage.vue | 28 +++++- .../src/views/resource/avatar-upload-cache.ts | 26 +++++ .../src/views/resource/use-resource-avatar.ts | 72 ++++++++++++++ 14 files changed, 356 insertions(+), 24 deletions(-) create mode 100644 frontend/delivery_admin/src/api/avatar.ts create mode 100644 frontend/delivery_admin/src/views/resource/ResourceAccountSummary.vue create mode 100644 frontend/delivery_admin/src/views/resource/avatar-upload-cache.ts create mode 100644 frontend/delivery_admin/src/views/resource/use-resource-avatar.ts diff --git a/backend/api/internal/logic/delivery/staff.go b/backend/api/internal/logic/delivery/staff.go index 97535a7..f25477b 100644 --- a/backend/api/internal/logic/delivery/staff.go +++ b/backend/api/internal/logic/delivery/staff.go @@ -6,6 +6,7 @@ import ( "git.apinb.com/bsm-sdk/core/errcode" "git.apinb.com/bsm-sdk/core/infra" "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/common" + "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/upload" "git.apinb.com/heqiapp/platforms/backend/api/internal/models" "github.com/gin-gonic/gin" "gorm.io/gorm" @@ -41,13 +42,26 @@ func GetStaff(ctx *gin.Context) { ctx.Param("identity"), point.GasBasicID, point.ID, "delivery"), &staff) } +// GetStaffAvatar 返回当前配送点范围内配送人员的受保护头像。 +func GetStaffAvatar(ctx *gin.Context) { + point, _, ok := currentScope(ctx) + if !ok { + return + } + staff, ok := scopedStaff(ctx, ctx.Param("identity"), point) + if !ok { + return + } + upload.ServeAvatar(ctx, staff.Avatar) +} + type staffRequest struct { - Username string `json:"username"` - Password string `json:"password"` - Name string `json:"name" binding:"required,max=64"` - Phone string `json:"phone" binding:"max=32"` - Avatar string `json:"avatar" binding:"max=512"` - WorkStatus string `json:"work_status" binding:"required"` + Username string `json:"username"` + Password string `json:"password"` + Name string `json:"name" binding:"required,max=64"` + Phone string `json:"phone" binding:"max=32"` + Avatar *string `json:"avatar" binding:"omitempty,max=512"` + WorkStatus string `json:"work_status" binding:"required"` } func CreateStaff(ctx *gin.Context) { @@ -66,9 +80,13 @@ func CreateStaff(ctx *gin.Context) { infra.Response.Error(ctx, err) return } + avatar := "" + if request.Avatar != nil { + avatar = *request.Avatar + } staff := models.StaffAccount{ Entity: common.NewEntity(common.StatusEnable), Username: request.Username, PasswordHash: hash, - Name: request.Name, Phone: request.Phone, Avatar: request.Avatar, RoleCode: "delivery", + Name: request.Name, Phone: request.Phone, Avatar: avatar, RoleCode: "delivery", GasBasicID: point.GasBasicID, DeliveryBasicID: point.ID, WorkStatus: request.WorkStatus, } if err := common.CreateStaffRecord(&staff); err != nil { @@ -92,9 +110,13 @@ func UpdateStaff(ctx *gin.Context) { infra.Response.Error(ctx, errcode.ErrInvalidArgument) return } - common.UpdateAllowedByIdentityWithError(ctx, &models.StaffAccount{}, gin.H{ - "name": request.Name, "phone": request.Phone, "avatar": request.Avatar, "work_status": request.WorkStatus, - }, []string{"name", "phone", "avatar", "work_status"}, common.StaffWriteError) + values := gin.H{"name": request.Name, "phone": request.Phone, "work_status": request.WorkStatus} + // 未选择新头像时不提交 avatar,避免编辑基础资料误清空现有头像。 + if request.Avatar != nil { + values["avatar"] = *request.Avatar + } + common.UpdateAllowedByIdentityWithError(ctx, &models.StaffAccount{}, values, + []string{"name", "phone", "avatar", "work_status"}, common.StaffWriteError) } func ResetStaffPassword(ctx *gin.Context) { diff --git a/backend/api/internal/logic/delivery/user.go b/backend/api/internal/logic/delivery/user.go index 698f026..90743a4 100644 --- a/backend/api/internal/logic/delivery/user.go +++ b/backend/api/internal/logic/delivery/user.go @@ -6,6 +6,7 @@ import ( "git.apinb.com/bsm-sdk/core/errcode" "git.apinb.com/bsm-sdk/core/infra" "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/common" + "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/upload" "git.apinb.com/heqiapp/platforms/backend/api/internal/models" "github.com/gin-gonic/gin" "gorm.io/gorm" @@ -57,13 +58,26 @@ func GetUser(ctx *gin.Context) { infra.Response.Success(ctx, response) } +// GetUserAvatar 返回当前配送点存在有效服务关系的用户受保护头像。 +func GetUserAvatar(ctx *gin.Context) { + point, _, ok := currentScope(ctx) + if !ok { + return + } + user, _, ok := scopedUser(ctx, ctx.Param("identity"), point.ID) + if !ok { + return + } + upload.ServeAvatar(ctx, user.Avatar) +} + type userRequest struct { - Username string `json:"username"` - Password string `json:"password"` - Name string `json:"name" binding:"required,max=64"` - Phone string `json:"phone" binding:"max=32"` - Avatar string `json:"avatar" binding:"max=512"` - RealName string `json:"real_name" binding:"max=64"` + Username string `json:"username"` + Password string `json:"password"` + Name string `json:"name" binding:"required,max=64"` + Phone string `json:"phone" binding:"max=32"` + Avatar *string `json:"avatar" binding:"omitempty,max=512"` + RealName string `json:"real_name" binding:"max=64"` } func CreateUser(ctx *gin.Context) { @@ -81,9 +95,13 @@ func CreateUser(ctx *gin.Context) { infra.Response.Error(ctx, err) return } + avatar := "" + if request.Avatar != nil { + avatar = *request.Avatar + } user := models.UserAccount{ Entity: common.NewEntity(common.StatusEnable), Username: request.Username, PasswordHash: hash, - Name: request.Name, Phone: request.Phone, Avatar: request.Avatar, RealName: request.RealName, + Name: request.Name, Phone: request.Phone, Avatar: avatar, RealName: request.RealName, } relation := models.UserServiceRelation{ Entity: common.NewEntity(common.StatusEnable), GasBasicID: point.GasBasicID, DeliveryBasicID: point.ID, @@ -115,9 +133,12 @@ func UpdateUser(ctx *gin.Context) { infra.Response.Error(ctx, errcode.ErrInvalidArgument) return } - if err := db().Model(&user).Updates(map[string]any{ - "name": request.Name, "phone": request.Phone, "avatar": request.Avatar, "real_name": request.RealName, - }).Error; err != nil { + values := map[string]any{"name": request.Name, "phone": request.Phone, "real_name": request.RealName} + // 未选择新头像时不提交 avatar,避免编辑基础资料误清空现有头像。 + if request.Avatar != nil { + values["avatar"] = *request.Avatar + } + if err := db().Model(&user).Updates(values).Error; err != nil { infra.Response.Error(ctx, err) return } diff --git a/backend/api/internal/routers/delivery.go b/backend/api/internal/routers/delivery.go index 046dfeb..1349bf9 100644 --- a/backend/api/internal/routers/delivery.go +++ b/backend/api/internal/routers/delivery.go @@ -28,6 +28,7 @@ func RegisterDelivery(serviceKey string, engine *gin.Engine) { staff.GET("", deliverylogic.ListStaff) staff.POST("", deliverylogic.CreateStaff) staff.GET("/:identity", deliverylogic.GetStaff) + staff.GET("/:identity/avatar", deliverylogic.GetStaffAvatar) staff.PUT("/:identity", deliverylogic.UpdateStaff) staff.PUT("/:identity/password", deliverylogic.ResetStaffPassword) staff.PATCH("/:identity/status", deliverylogic.UpdateStaffStatus) @@ -44,6 +45,7 @@ func RegisterDelivery(serviceKey string, engine *gin.Engine) { user.GET("", deliverylogic.ListUser) user.POST("", deliverylogic.CreateUser) user.GET("/:identity", deliverylogic.GetUser) + user.GET("/:identity/avatar", deliverylogic.GetUserAvatar) user.PUT("/:identity", deliverylogic.UpdateUser) user.PUT("/:identity/password", deliverylogic.ResetUserPassword) user.PATCH("/:identity/status", deliverylogic.UpdateUserStatus) diff --git a/backend/api/internal/routers/delivery_test.go b/backend/api/internal/routers/delivery_test.go index 0fec593..6c491cc 100644 --- a/backend/api/internal/routers/delivery_test.go +++ b/backend/api/internal/routers/delivery_test.go @@ -45,6 +45,8 @@ func TestDeliveryOrderActionBoundary(t *testing.T) { "POST /heqi/delivery/v1/gasorder_basic/:identity/adjust-amount", "GET /heqi/delivery/v1/wallet_recharge", "GET /heqi/delivery/v1/wallet_recharge/:identity", + "GET /heqi/delivery/v1/staff_account/:identity/avatar", + "GET /heqi/delivery/v1/user_account/:identity/avatar", } { if !routes[required] { t.Fatalf("missing confirmed delivery action %s", required) diff --git a/docs/操作日志_配送点独立资源页面_20260822.md b/docs/操作日志_配送点独立资源页面_20260822.md index d93b0ac..f9e71d3 100644 --- a/docs/操作日志_配送点独立资源页面_20260822.md +++ b/docs/操作日志_配送点独立资源页面_20260822.md @@ -17,6 +17,8 @@ 5. 将配送端支付、退款资源统一为 `payment_order`、`payment_refund`,同步后端契约快照。 6. 增加页面能力矩阵自动检查,并更新项目文档。 7. 依据 5173 页面重新对齐灰色页面底、面包屑、分区卡片、详情信息网格、双列表单和底部操作区。 +8. 将配送人员和用户账户的头像文本框替换为 5173 头像摘要卡片,新增上传、预览、恢复默认头像和配送点范围鉴权读取能力。 +9. 修正配送人员、用户编辑接口:没有提交头像字段时保留旧头像,避免编辑其他资料时误清空。 ## 操作后状态 @@ -43,11 +45,12 @@ - `contract:check`:通过,18 个资源与后端契约一致。 - `profile:check`:通过,资料专用只读页未回退。 - `type:check`:通过。 -- `build`:通过,2622 个模块完成生产构建。 +- `build`:通过,2628 个模块完成生产构建。 - `go test ./internal/logic/delivery`:通过。 - `lint`:通过;仅报告项目既有警告,未产生失败项。 - 浏览器回归:工作人员列表、详情、编辑、正式新建地址、返回链路、未保存保护、配送订单新建页、支付列表均通过。 - 布局回归:工作人员详情、编辑和配送订单新建页已在应用内浏览器逐页截图检查,与 5173 的页面结构和响应式断点一致。 +- 头像回归:配送人员新建、编辑页已确认不再显示头像文本框,头像选择按钮、格式大小提示、默认头像和身份摘要均正常;后端头像路由测试通过。 ## 风险评估 diff --git a/docs/项目文档_配送点独立资源页面_v1.0.md b/docs/项目文档_配送点独立资源页面_v1.0.md index 74216a0..4f95526 100644 --- a/docs/项目文档_配送点独立资源页面_v1.0.md +++ b/docs/项目文档_配送点独立资源页面_v1.0.md @@ -33,6 +33,8 @@ frontend/delivery_admin/ │ ├── ResourceDetailContent.vue # 主记录和集合详情展示 │ ├── ResourceFieldForm.vue # 通用资源字段表单 │ ├── ResourceActionDialog.vue # 详情业务动作与危险确认 + │ ├── ResourceAccountSummary.vue # 头像选择与账户身份摘要 + │ ├── use-resource-avatar.ts # 头像预览、上传和清除状态 │ └── use-unsaved-record.ts # 未保存离开保护 └── views/shared/ └── ResourceListPage.vue # 跳转独立页面的标准列表 @@ -46,6 +48,8 @@ frontend/delivery_admin/ 页面布局与平台总后台保持一致:使用灰色页面背景、顶部面包屑和操作栏;详情由“基本信息”“关联记录”“业务操作”分区卡片组成;新建和编辑使用双列响应式表单,并将保存、取消操作固定在表单内容底部。 +配送人员和用户账户参考 5173 使用头像身份摘要卡片。新建、编辑时点击头像可选择不超过 2 MB 的 JPG/PNG 文件,保存时先上传到受控头像目录,再把返回 URI 写入资源;详情页通过配送点范围鉴权接口读取头像。未选择新头像时不会清空已有头像。 + `resource-record-form.ts` 为五类可编辑资源声明后端更新字段白名单,防止用户名、合同编号等只读字段出现在编辑页或被无效提交。 支付与退款资源统一使用后端正式名称 `payment_order`、`payment_refund`,菜单地址仍保持 `/finance/payments`、`/finance/refunds`,避免接口路径不一致导致 404。 diff --git a/frontend/delivery_admin/scripts/check-resource-pages.mjs b/frontend/delivery_admin/scripts/check-resource-pages.mjs index 27c1d11..76e4e5a 100644 --- a/frontend/delivery_admin/scripts/check-resource-pages.mjs +++ b/frontend/delivery_admin/scripts/check-resource-pages.mjs @@ -60,5 +60,10 @@ assert(resourcePage.includes('ResourceListPage'), '标准资源列表尚未切 assert(!resourcePage.includes('CrudListPage'), '活动列表仍依赖抽屉式 CrudListPage'); assert(definitions.includes("define('payment_order'"), '支付资源必须使用后端名称 payment_order'); assert(definitions.includes("define('payment_refund'"), '退款资源必须使用后端名称 payment_refund'); +assert(routeKeys.has('GET /staff_account/:identity/avatar'), '配送人员缺少受保护头像读取接口'); +assert(routeKeys.has('GET /user_account/:identity/avatar'), '用户账户缺少受保护头像读取接口'); +const recordPage = read('src/views/resource/ResourceRecordPage.vue'); +assert(recordPage.includes('ResourceAccountSummary'), '账户资源页尚未接入 5173 头像摘要卡片'); +assert(recordPage.includes("field.key !== 'avatar'"), '头像字段仍可能显示为普通文本框'); console.log(`独立资源页面契约通过:详情 ${listResources.length},新建 ${creatable.size},编辑 ${editable.size}`); diff --git a/frontend/delivery_admin/src/api/avatar.ts b/frontend/delivery_admin/src/api/avatar.ts new file mode 100644 index 0000000..f018267 --- /dev/null +++ b/frontend/delivery_admin/src/api/avatar.ts @@ -0,0 +1,50 @@ +/** + * 功能描述:提供配送点资源头像上传与鉴权读取。 + * 版本:v1.0.0。 + */ +import { getToken } from '@/utils/auth'; + +const deliveryApiBaseURL = + import.meta.env.VITE_API_BASE_URL || 'http://localhost:12426/heqi/delivery/v1'; + +export type AvatarUploadReply = { + uri: string; + original_name: string; + content_type: string; + size: number; +}; + +type ApiEnvelope = { code?: number; message?: string; details?: T }; + +/** 返回与现有配送点请求一致的 JWT 请求头。 */ +function authorizationHeaders(): Record { + const token = getToken(); + return token ? { Authorization: token } : {}; +} + +/** 上传经过前端预检的头像文件。 */ +async function upload(file: File): Promise { + const form = new FormData(); + form.append('file', file); + const baseURL = new URL(deliveryApiBaseURL, window.location.origin); + const response = await fetch(new URL('/upload/avatar', baseURL.origin), { + method: 'POST', headers: authorizationHeaders(), body: form, + }); + const payload = (await response.json()) as ApiEnvelope; + if (!response.ok || payload.code !== 0 || !payload.details) + throw new Error(payload.message || '头像上传失败'); + return payload.details; +} + +/** 读取配送点权限范围内的受保护头像。 */ +async function load(resource: string, identity: string): Promise { + const response = await fetch( + `${deliveryApiBaseURL}${resource}/${encodeURIComponent(identity)}/avatar`, + { headers: authorizationHeaders() }, + ); + if (response.status === 404) return undefined; + if (!response.ok) throw new Error('头像读取失败'); + return response.blob(); +} + +export const avatarApi = { upload, load }; diff --git a/frontend/delivery_admin/src/contracts/delivery-resources.json b/frontend/delivery_admin/src/contracts/delivery-resources.json index a0c2b01..6a92ac1 100644 --- a/frontend/delivery_admin/src/contracts/delivery-resources.json +++ b/frontend/delivery_admin/src/contracts/delivery-resources.json @@ -1 +1 @@ -{"resources":[{"domain":"profile","name":"delivery_profile","path":"/delivery_profile","pageKind":"list","mode":"readonly"},{"domain":"staff","name":"staff_account","path":"/staff_account","pageKind":"list","mode":"writable"},{"domain":"staff","name":"staff_credential","path":"/staff_credential","pageKind":"list","mode":"writable"},{"domain":"user","name":"user_account","path":"/user_account","pageKind":"list","mode":"writable"},{"domain":"user","name":"user_address","path":"/user_address","pageKind":"list","mode":"writable"},{"domain":"contract","name":"gasorder_contract","path":"/gasorder_contract","pageKind":"list","mode":"managed"},{"domain":"contract","name":"gasorder_contract_product","path":"/gasorder_contract_product","pageKind":"list","mode":"append_only"},{"domain":"contract","name":"gasorder_contract_revision","path":"/gasorder_contract_revision","pageKind":"list","mode":"readonly"},{"domain":"contract","name":"product_info","path":"/product_info","pageKind":"list","mode":"readonly"},{"domain":"gasorder","name":"gasorder_basic","path":"/gasorder_basic","pageKind":"list","mode":"append_only"},{"domain":"finance","name":"wallet_basic","path":"/wallet_basic","pageKind":"list","mode":"readonly"},{"domain":"finance","name":"wallet_bank","path":"/wallet_bank","pageKind":"list","mode":"readonly"},{"domain":"finance","name":"payment_order","path":"/payment_order","pageKind":"list","mode":"readonly"},{"domain":"finance","name":"wallet_record","path":"/wallet_record","pageKind":"list","mode":"readonly"},{"domain":"finance","name":"payment_refund","path":"/payment_refund","pageKind":"list","mode":"readonly"},{"domain":"finance","name":"wallet_recharge","path":"/wallet_recharge","pageKind":"list","mode":"append_only"},{"domain":"finance","name":"wallet_apply_cash","path":"/wallet_apply_cash","pageKind":"list","mode":"append_only"},{"domain":"finance","name":"fin_settlement","path":"/fin_settlement","pageKind":"list","mode":"readonly"}],"routes":[{"method":"POST","path":"/gasorder_basic"},{"method":"POST","path":"/gasorder_basic/:identity/assign"},{"method":"POST","path":"/gasorder_basic/:identity/adjust-amount"},{"method":"POST","path":"/gasorder_basic/:identity/reclaim"},{"method":"POST","path":"/gasorder_basic/:identity/recover"},{"method":"POST","path":"/gasorder_basic/:identity/exception"},{"method":"POST","path":"/gasorder_basic/:identity/cancel"},{"method":"POST","path":"/gasorder_contract"},{"method":"POST","path":"/gasorder_contract/:identity/activate"},{"method":"POST","path":"/gasorder_contract/:identity/renew"},{"method":"POST","path":"/gasorder_contract/:identity/terminate"},{"method":"POST","path":"/gasorder_contract_product"},{"method":"POST","path":"/gasorder_contract_product/:identity/unbind"},{"method":"POST","path":"/wallet_basic/recharge"},{"method":"POST","path":"/wallet_recharge"},{"method":"POST","path":"/wallet_apply_cash"},{"method":"POST","path":"/staff_account"},{"method":"POST","path":"/staff_credential"},{"method":"POST","path":"/user_account"},{"method":"POST","path":"/user_address"},{"method":"POST","path":"/auth/login"},{"method":"GET","path":"/wallet_basic"},{"method":"GET","path":"/wallet_basic/:identity"},{"method":"GET","path":"/wallet_bank"},{"method":"GET","path":"/wallet_bank/:identity"},{"method":"GET","path":"/wallet_recharge"},{"method":"GET","path":"/wallet_recharge/:identity"},{"method":"GET","path":"/wallet_record"},{"method":"GET","path":"/wallet_record/:identity"},{"method":"GET","path":"/wallet_apply_cash"},{"method":"GET","path":"/wallet_apply_cash/:identity"},{"method":"GET","path":"/gasorder_contract"},{"method":"GET","path":"/gasorder_contract_product"},{"method":"GET","path":"/gasorder_contract_product/:identity"},{"method":"GET","path":"/gasorder_contract_revision"},{"method":"GET","path":"/gasorder_contract_revision/:identity"},{"method":"GET","path":"/gasorder_contract/:identity"},{"method":"GET","path":"/gasorder_basic"},{"method":"GET","path":"/gasorder_basic/:identity"},{"method":"GET","path":"/payment_order"},{"method":"GET","path":"/payment_order/:identity"},{"method":"GET","path":"/payment_refund"},{"method":"GET","path":"/payment_refund/:identity"},{"method":"GET","path":"/product_info"},{"method":"GET","path":"/product_info/:identity"},{"method":"GET","path":"/dashboard/overview"},{"method":"GET","path":"/dashboard/reports"},{"method":"GET","path":"/delivery_menu"},{"method":"GET","path":"/delivery_profile"},{"method":"GET","path":"/staff_account"},{"method":"GET","path":"/staff_account/:identity"},{"method":"GET","path":"/staff_credential"},{"method":"GET","path":"/staff_credential/:identity"},{"method":"GET","path":"/user_account"},{"method":"GET","path":"/user_account/:identity"},{"method":"GET","path":"/user_address"},{"method":"GET","path":"/user_address/:identity"},{"method":"GET","path":"/fin_settlement"},{"method":"GET","path":"/fin_settlement/:identity"},{"method":"GET","path":"/auth/profile"},{"method":"GET","path":"/invitation/qrcode"},{"method":"PUT","path":"/staff_account/:identity"},{"method":"PUT","path":"/staff_account/:identity/password"},{"method":"PUT","path":"/staff_credential/:identity"},{"method":"PUT","path":"/user_account/:identity"},{"method":"PUT","path":"/user_account/:identity/password"},{"method":"PUT","path":"/user_address/:identity"},{"method":"PUT","path":"/auth/password"},{"method":"PUT","path":"/gasorder_contract/:identity"},{"method":"PATCH","path":"/staff_account/:identity/status"},{"method":"PATCH","path":"/staff_credential/:identity/status"},{"method":"PATCH","path":"/user_account/:identity/status"},{"method":"PATCH","path":"/user_address/:identity/status"},{"method":"DELETE","path":"/staff_account/:identity"},{"method":"DELETE","path":"/staff_credential/:identity"},{"method":"DELETE","path":"/user_account/:identity"},{"method":"DELETE","path":"/user_address/:identity"}]} +{"resources":[{"domain":"profile","name":"delivery_profile","path":"/delivery_profile","pageKind":"list","mode":"readonly"},{"domain":"staff","name":"staff_account","path":"/staff_account","pageKind":"list","mode":"writable"},{"domain":"staff","name":"staff_credential","path":"/staff_credential","pageKind":"list","mode":"writable"},{"domain":"user","name":"user_account","path":"/user_account","pageKind":"list","mode":"writable"},{"domain":"user","name":"user_address","path":"/user_address","pageKind":"list","mode":"writable"},{"domain":"contract","name":"gasorder_contract","path":"/gasorder_contract","pageKind":"list","mode":"managed"},{"domain":"contract","name":"gasorder_contract_product","path":"/gasorder_contract_product","pageKind":"list","mode":"append_only"},{"domain":"contract","name":"gasorder_contract_revision","path":"/gasorder_contract_revision","pageKind":"list","mode":"readonly"},{"domain":"contract","name":"product_info","path":"/product_info","pageKind":"list","mode":"readonly"},{"domain":"gasorder","name":"gasorder_basic","path":"/gasorder_basic","pageKind":"list","mode":"append_only"},{"domain":"finance","name":"wallet_basic","path":"/wallet_basic","pageKind":"list","mode":"readonly"},{"domain":"finance","name":"wallet_bank","path":"/wallet_bank","pageKind":"list","mode":"readonly"},{"domain":"finance","name":"payment_order","path":"/payment_order","pageKind":"list","mode":"readonly"},{"domain":"finance","name":"wallet_record","path":"/wallet_record","pageKind":"list","mode":"readonly"},{"domain":"finance","name":"payment_refund","path":"/payment_refund","pageKind":"list","mode":"readonly"},{"domain":"finance","name":"wallet_recharge","path":"/wallet_recharge","pageKind":"list","mode":"append_only"},{"domain":"finance","name":"wallet_apply_cash","path":"/wallet_apply_cash","pageKind":"list","mode":"append_only"},{"domain":"finance","name":"fin_settlement","path":"/fin_settlement","pageKind":"list","mode":"readonly"}],"routes":[{"method":"POST","path":"/gasorder_basic"},{"method":"POST","path":"/gasorder_basic/:identity/assign"},{"method":"POST","path":"/gasorder_basic/:identity/adjust-amount"},{"method":"POST","path":"/gasorder_basic/:identity/reclaim"},{"method":"POST","path":"/gasorder_basic/:identity/recover"},{"method":"POST","path":"/gasorder_basic/:identity/exception"},{"method":"POST","path":"/gasorder_basic/:identity/cancel"},{"method":"POST","path":"/gasorder_contract"},{"method":"POST","path":"/gasorder_contract/:identity/activate"},{"method":"POST","path":"/gasorder_contract/:identity/renew"},{"method":"POST","path":"/gasorder_contract/:identity/terminate"},{"method":"POST","path":"/gasorder_contract_product"},{"method":"POST","path":"/gasorder_contract_product/:identity/unbind"},{"method":"POST","path":"/wallet_basic/recharge"},{"method":"POST","path":"/wallet_recharge"},{"method":"POST","path":"/wallet_apply_cash"},{"method":"POST","path":"/staff_account"},{"method":"POST","path":"/staff_credential"},{"method":"POST","path":"/user_account"},{"method":"POST","path":"/user_address"},{"method":"POST","path":"/auth/login"},{"method":"GET","path":"/wallet_basic"},{"method":"GET","path":"/wallet_basic/:identity"},{"method":"GET","path":"/wallet_bank"},{"method":"GET","path":"/wallet_bank/:identity"},{"method":"GET","path":"/wallet_recharge"},{"method":"GET","path":"/wallet_recharge/:identity"},{"method":"GET","path":"/wallet_record"},{"method":"GET","path":"/wallet_record/:identity"},{"method":"GET","path":"/wallet_apply_cash"},{"method":"GET","path":"/wallet_apply_cash/:identity"},{"method":"GET","path":"/gasorder_contract"},{"method":"GET","path":"/gasorder_contract_product"},{"method":"GET","path":"/gasorder_contract_product/:identity"},{"method":"GET","path":"/gasorder_contract_revision"},{"method":"GET","path":"/gasorder_contract_revision/:identity"},{"method":"GET","path":"/gasorder_contract/:identity"},{"method":"GET","path":"/gasorder_basic"},{"method":"GET","path":"/gasorder_basic/:identity"},{"method":"GET","path":"/payment_order"},{"method":"GET","path":"/payment_order/:identity"},{"method":"GET","path":"/payment_refund"},{"method":"GET","path":"/payment_refund/:identity"},{"method":"GET","path":"/product_info"},{"method":"GET","path":"/product_info/:identity"},{"method":"GET","path":"/staff_account"},{"method":"GET","path":"/staff_account/:identity"},{"method":"GET","path":"/staff_account/:identity/avatar"},{"method":"GET","path":"/staff_credential"},{"method":"GET","path":"/staff_credential/:identity"},{"method":"GET","path":"/user_account"},{"method":"GET","path":"/user_account/:identity"},{"method":"GET","path":"/user_account/:identity/avatar"},{"method":"GET","path":"/user_address"},{"method":"GET","path":"/user_address/:identity"},{"method":"GET","path":"/dashboard/overview"},{"method":"GET","path":"/dashboard/reports"},{"method":"GET","path":"/delivery_menu"},{"method":"GET","path":"/delivery_profile"},{"method":"GET","path":"/fin_settlement"},{"method":"GET","path":"/fin_settlement/:identity"},{"method":"GET","path":"/auth/profile"},{"method":"GET","path":"/invitation/qrcode"},{"method":"PUT","path":"/staff_account/:identity"},{"method":"PUT","path":"/staff_account/:identity/password"},{"method":"PUT","path":"/staff_credential/:identity"},{"method":"PUT","path":"/user_account/:identity"},{"method":"PUT","path":"/user_account/:identity/password"},{"method":"PUT","path":"/user_address/:identity"},{"method":"PUT","path":"/auth/password"},{"method":"PUT","path":"/gasorder_contract/:identity"},{"method":"PATCH","path":"/staff_account/:identity/status"},{"method":"PATCH","path":"/staff_credential/:identity/status"},{"method":"PATCH","path":"/user_account/:identity/status"},{"method":"PATCH","path":"/user_address/:identity/status"},{"method":"DELETE","path":"/staff_account/:identity"},{"method":"DELETE","path":"/staff_credential/:identity"},{"method":"DELETE","path":"/user_account/:identity"},{"method":"DELETE","path":"/user_address/:identity"}]} diff --git a/frontend/delivery_admin/src/views/resource/ResourceAccountSummary.vue b/frontend/delivery_admin/src/views/resource/ResourceAccountSummary.vue new file mode 100644 index 0000000..89338ab --- /dev/null +++ b/frontend/delivery_admin/src/views/resource/ResourceAccountSummary.vue @@ -0,0 +1,98 @@ + + + + + + diff --git a/frontend/delivery_admin/src/views/resource/ResourceDetailContent.vue b/frontend/delivery_admin/src/views/resource/ResourceDetailContent.vue index 2b20c6d..3c644a6 100644 --- a/frontend/delivery_admin/src/views/resource/ResourceDetailContent.vue +++ b/frontend/delivery_admin/src/views/resource/ResourceDetailContent.vue @@ -69,6 +69,9 @@ const entries = computed(() => Object.entries(record.value).filter( ([key, value]) => key !== 'id' && + key !== 'avatar' && + key !== 'password' && + key !== 'password_hash' && key !== 'DeletedAt' && key !== 'deleted_at' && !key.endsWith('_id') && diff --git a/frontend/delivery_admin/src/views/resource/ResourceRecordPage.vue b/frontend/delivery_admin/src/views/resource/ResourceRecordPage.vue index 3f2c70a..f868e8b 100644 --- a/frontend/delivery_admin/src/views/resource/ResourceRecordPage.vue +++ b/frontend/delivery_admin/src/views/resource/ResourceRecordPage.vue @@ -29,6 +29,16 @@