feat(admin-order): 订单列表展示完整用户手机号便于客服定位

- backend: AdminOrderListItemDTO 不再脱敏 owner_phone/renter_phone,移除 order 包内已无用的 maskPhone
- frontend: 同步 AdminOrderListItem 类型注释
- tests: 更新后台列表用例为断言完整手机号,并继续校验不泄露账号快照
This commit is contained in:
yml2213
2026-09-16 14:46:12 +08:00
parent 5f5a57b81f
commit 6d31da1874
4 changed files with 10 additions and 14 deletions
+1 -1
View File
@@ -106,7 +106,7 @@ type UserOrderListItemDTO struct {
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time `json:"created_at"`
} }
// AdminOrderListItemDTO 是后台订单表格的最小展示数据,敏感详情仅由详情接口按权限获取。 // AdminOrderListItemDTO 是后台订单表格的最小展示数据;手机号按客服需要返回完整值,其余敏感详情仅由详情接口按权限获取。
type AdminOrderListItemDTO struct { type AdminOrderListItemDTO struct {
ID uint64 `json:"id"` ID uint64 `json:"id"`
OrderNo string `json:"order_no"` OrderNo string `json:"order_no"`
+2 -9
View File
@@ -205,8 +205,8 @@ func (row orderRow) toAdminListItem() AdminOrderListItemDTO {
OrderNo: row.OrderNo, OrderNo: row.OrderNo,
ListingID: row.ListingID, ListingID: row.ListingID,
ListingNo: row.ListingNo, ListingNo: row.ListingNo,
OwnerPhone: maskPhone(row.OwnerPhone), OwnerPhone: row.OwnerPhone,
RenterPhone: maskPhone(row.RenterPhone), RenterPhone: row.RenterPhone,
Title: row.Title, Title: row.Title,
ServerRegion: row.ServerRegion, ServerRegion: row.ServerRegion,
LoginPlatform: row.LoginPlatform, LoginPlatform: row.LoginPlatform,
@@ -221,13 +221,6 @@ func (row orderRow) toAdminListItem() AdminOrderListItemDTO {
} }
} }
func maskPhone(phone string) string {
if len(phone) < 7 {
return ""
}
return phone[:3] + "****" + phone[len(phone)-4:]
}
func effectiveHandoffMode(order model.RentalOrder) string { func effectiveHandoffMode(order model.RentalOrder) string {
if order.HandoffMode != "" { if order.HandoffMode != "" {
return order.HandoffMode return order.HandoffMode
@@ -72,7 +72,7 @@ func TestUserOrderListItemDoesNotSerializeDetailFields(t *testing.T) {
} }
} }
func TestAdminOrderListItemMasksPhonesAndOmitsSnapshot(t *testing.T) { func TestAdminOrderListItemShowsPhonesAndOmitsSnapshot(t *testing.T) {
row := orderRow{ row := orderRow{
RentalOrder: model.RentalOrder{ID: 1, OrderNo: "ORD-001", Status: orderStatusPendingPayment}, RentalOrder: model.RentalOrder{ID: 1, OrderNo: "ORD-001", Status: orderStatusPendingPayment},
OwnerPhone: "13800001234", OwnerPhone: "13800001234",
@@ -83,8 +83,11 @@ func TestAdminOrderListItemMasksPhonesAndOmitsSnapshot(t *testing.T) {
t.Fatalf("Marshal() error = %v", err) t.Fatalf("Marshal() error = %v", err)
} }
text := string(raw) text := string(raw)
if strings.Contains(text, "13800001234") || strings.Contains(text, "13900005678") { // 后台订单列表需要展示完整手机号,方便客服定位用户。
t.Fatalf("list response contains full phone number: %s", text) for _, phone := range []string{"13800001234", "13900005678"} {
if !strings.Contains(text, phone) {
t.Fatalf("list response should contain full phone %q: %s", phone, text)
}
} }
if strings.Contains(text, "account_snapshot") { if strings.Contains(text, "account_snapshot") {
t.Fatalf("list response contains account snapshot: %s", text) t.Fatalf("list response contains account snapshot: %s", text)
+1 -1
View File
@@ -98,7 +98,7 @@ export interface UserOrderListItem {
created_at: string created_at: string
} }
// 后台订单列表使用脱敏后的表格数据,敏感字段仅在详情接口中按权限返回。 // 后台订单列表返回客服需要的完整用户手机号,其余敏感字段仅在详情接口中按权限返回。
export interface AdminOrderListItem { export interface AdminOrderListItem {
id: number id: number
order_no: string order_no: string