修复账号切换后「我的」页当前账号展示错误,并统一举报摄影师首页 URI。

切换账号时以用户选中账号为准写入展示标题与业务作用域,避免沿用旧门店名称;同时将首页举报摄影师入口 URI 对齐为 report_photographer。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-01 17:21:04 +08:00
parent fcb86d43f5
commit 5ab9b1b324
23 changed files with 419 additions and 92 deletions

View File

@ -147,6 +147,40 @@ final class AccountContextLoaderTests: XCTestCase {
XCTAssertTrue(accountContext.storeScopes.isEmpty)
XCTAssertNil(accountContext.currentStore)
}
/// /
func testRefreshSupplementalContextPreservesExistingStoreScopesWhenStoreAPIFails() async throws {
let accountContext = AccountContext()
accountContext.applyLogin(accountType: V9StoreUser.accountTypeValue)
accountContext.replaceScopes(
scenic: [BusinessScope(id: 88, name: "东湖景区", kind: .scenic)],
stores: [BusinessScope(id: 66, name: "东湖门店", kind: .store, parentScenicId: 88)],
currentScenicId: 88,
currentStoreId: 66
)
let permissionContext = PermissionContext()
let api = MockAccountContextAPI()
api.roles = [
RolePermissionResponse(
role: RoleInfo(id: 7, name: "运营"),
scenic: [ScenicInfo(id: 88, name: "东湖景区")]
)
]
api.scenicResponse = ScenicListAllResponse(total: 1, list: [ScenicListItem(id: 88, name: "东湖景区")])
api.storeError = APIError.networkFailed("门店接口失败")
try await AccountContextLoader().refreshSupplementalContext(
accountContext: accountContext,
permissionContext: permissionContext,
profileAPI: MockUserProfileAPI(),
accountContextAPI: api,
cachedCurrentScenicId: 88,
cachedCurrentStoreId: 66
)
XCTAssertEqual(accountContext.storeScopes.map(\.name), ["东湖门店"])
XCTAssertEqual(accountContext.currentStore?.name, "东湖门店")
}
}
@MainActor

View File

@ -46,6 +46,32 @@ final class AccountContextTests: XCTestCase {
XCTAssertEqual(context.currentStore?.id, 20)
}
///
func testReplaceScopesExplicitSelectionClearsStoreForScenicAccount() {
let context = AccountContext()
context.replaceScopes(
scenic: [BusinessScope(id: 128, name: "伊犁那拉提景区-5A", kind: .scenic)],
stores: [BusinessScope(id: 37, name: "随心旅拍", kind: .store, parentScenicId: 128)],
currentScenicId: 128,
currentStoreId: 37,
explicitSelection: true
)
XCTAssertEqual(context.currentStore?.name, "随心旅拍")
context.applyLogin(accountType: V9ScenicUser.accountTypeValue, businessUserId: 41, displayTitle: "伊犁那拉提景区-5A")
context.replaceScopes(
scenic: [BusinessScope(id: 128, name: "伊犁那拉提景区-5A", kind: .scenic)],
stores: [BusinessScope(id: 37, name: "随心旅拍", kind: .store, parentScenicId: 128)],
currentScenicId: 128,
currentStoreId: nil,
explicitSelection: true
)
XCTAssertEqual(context.accountType, V9ScenicUser.accountTypeValue)
XCTAssertNil(context.currentStore)
XCTAssertEqual(context.currentAccountDisplayTitle, "伊犁那拉提景区-5A")
}
/// ID 退
func testReplaceScopesFallsBackToFirstScopeWhenCachedIdIsMissing() {
let context = AccountContext()

View File

@ -81,6 +81,69 @@ final class AuthModelsTests: XCTestCase {
XCTAssertEqual(response.primaryProfile?.displayName, "示例门店")
}
/// 使 isCurrent
func testV9AuthResponsePreferredScopeSelectionUsesCurrentStoreAccount() throws {
let scenicJSON = """
{
"account_type": "scenic_user",
"id": 101,
"user_id": 101,
"scenic_user_id": 101,
"ss_user_id": 101,
"username": "scenic_admin",
"real_name": "",
"nickname": "",
"phone": "13800138000",
"scenic_id": 1,
"scenic_name": "",
"is_current": false
}
"""
let storeJSON = """
{
"account_type": "store_user",
"id": 201,
"user_id": 201,
"store_user_id": 201,
"username": "store_admin",
"user_name": "store_admin",
"real_name": "",
"phone": "13800138000",
"avatar": "",
"scenic_id": 2,
"scenic_name": "",
"store_id": 20,
"store_name": "",
"is_current": true
}
"""
let scenicUser = try JSONDecoder().decode(V9ScenicUser.self, from: Data(scenicJSON.utf8))
let storeUser = try JSONDecoder().decode(V9StoreUser.self, from: Data(storeJSON.utf8))
let response = V9AuthResponse(token: "token", scenicUsers: [scenicUser], storeUsers: [storeUser])
XCTAssertEqual(response.currentAccountIdentity?.accountType, V9StoreUser.accountTypeValue)
XCTAssertEqual(response.currentAccountIdentity?.businessUserId, 201)
XCTAssertEqual(response.preferredScopeSelection.scenicId, 2)
XCTAssertEqual(response.preferredScopeSelection.storeId, 20)
let context = AccountContext()
context.replaceScopes(
scenic: [BusinessScope(id: 1, name: "旧景区", kind: .scenic)],
stores: [],
currentScenicId: 1,
currentStoreId: nil
)
context.replaceScopes(
scenic: response.scenicScopes,
stores: response.storeScopes,
currentScenicId: response.preferredScopeSelection.scenicId,
currentStoreId: response.preferredScopeSelection.storeId
)
XCTAssertEqual(context.currentScenic?.id, 2)
XCTAssertEqual(context.currentStore?.id, 20)
}
/// LoginRequest
func testLoginRequestEncodesExpectedDefaults() throws {
let request = LoginRequest(username: "18651857230", password: "secret123")

View File

@ -16,14 +16,14 @@ final class HomeAllFunctionsBuilderTests: XCTestCase {
topLevelPermissions: [
permission(name: "基本信息", uri: "basic_info"),
permission(name: "位置上报", uri: "location_report"),
permission(name: "举报摄影师", uri: "photographer_report"),
permission(name: "举报摄影师", uri: "report_photographer"),
permission(name: "相册管理", uri: "album_list"),
permission(name: "我的钱包", uri: "wallet")
],
commonURIs: []
)
XCTAssertEqual(snapshot.allFunctions.map(\.uri), ["location_report", "photographer_report", "wallet"])
XCTAssertEqual(snapshot.allFunctions.map(\.uri), ["location_report", "report_photographer", "wallet"])
}
/// API 使 preferredOrder

View File

@ -269,20 +269,20 @@ final class HomeCommonMenuStoreTests: XCTestCase {
XCTAssertEqual(uris, ["wallet", "message_center"])
}
/// photographer_report Android menuList
/// report_photographer Android menuList
func testPhotographerReportIsWhitelistedAndCanBeAddedToCommon() {
XCTAssertTrue(HomeCommonMenuStore.androidHomeMenuURIs.contains("photographer_report"))
XCTAssertTrue(HomeCommonMenuStore.androidHomeMenuURIs.contains("report_photographer"))
let store = HomeCommonMenuStore(defaults: makeIsolatedDefaults())
let uris = store.add(
"photographer_report",
"report_photographer",
current: ["location_report"],
topLevelPermissionURIs: ["location_report", "photographer_report"],
topLevelPermissionURIs: ["location_report", "report_photographer"],
roleCode: "photographer",
accountScope: "scenic_user_photographer_report"
accountScope: "scenic_user_report_photographer"
)
XCTAssertEqual(uris, ["location_report", "photographer_report"])
XCTAssertEqual(uris, ["location_report", "report_photographer"])
}
/// 4

View File

@ -47,7 +47,7 @@ final class HomeMenuRouterTests: XCTestCase {
("checkin_points", .destination(.punchPointList)),
("location_report", .destination(.locationReport)),
("location_report_history", .destination(.locationReportHistory)),
("photographer_report", .destination(.photographerReport)),
("report_photographer", .destination(.photographerReport)),
("pm", .destination(.projectManagement)),
("project_edit", .destination(.projectManagement)),
("pm_manager", .destination(.pmProjectManagement)),
@ -191,7 +191,7 @@ final class HomeMenuRouterTests: XCTestCase {
XCTAssertTrue(uris.contains("sample_management"))
XCTAssertTrue(uris.contains("checkin_points"))
XCTAssertTrue(uris.contains("location_report"))
XCTAssertTrue(uris.contains("photographer_report"))
XCTAssertTrue(uris.contains("report_photographer"))
XCTAssertTrue(uris.contains("pm"))
XCTAssertTrue(uris.contains("pm_manager"))
XCTAssertTrue(uris.contains("schedule_management"))
@ -209,7 +209,7 @@ final class HomeMenuRouterTests: XCTestCase {
XCTAssertEqual(HomeMenuRouter.resolve(uri: "sample_upload", title: ""), .destination(.sampleUpload))
XCTAssertEqual(HomeMenuRouter.resolve(uri: "checkin_points", title: ""), .destination(.punchPointList))
XCTAssertEqual(HomeMenuRouter.resolve(uri: "location_report", title: ""), .destination(.locationReport))
XCTAssertEqual(HomeMenuRouter.resolve(uri: "photographer_report", title: ""), .destination(.photographerReport))
XCTAssertEqual(HomeMenuRouter.resolve(uri: "report_photographer", title: ""), .destination(.photographerReport))
XCTAssertEqual(HomeMenuRouter.resolve(uri: "pm", title: ""), .destination(.projectManagement))
XCTAssertEqual(HomeMenuRouter.resolve(uri: "pm_manager", title: ""), .destination(.pmProjectManagement))
XCTAssertEqual(HomeMenuRouter.resolve(uri: "schedule_management", title: ""), .destination(.scheduleManagement))