feat(mobile): album management pages with qr share
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -30,12 +30,16 @@ class RecordedRequest {
|
||||
const RecordedRequest({
|
||||
required this.method,
|
||||
required this.path,
|
||||
required this.uri,
|
||||
required this.headers,
|
||||
required this.body,
|
||||
});
|
||||
|
||||
final String method;
|
||||
final String path;
|
||||
|
||||
/// 完整 URI(含 query,游标/过滤参数断言用)。
|
||||
final Uri uri;
|
||||
final Map<String, dynamic> headers;
|
||||
final Object? body;
|
||||
}
|
||||
@@ -61,6 +65,7 @@ class FakeAdapter implements HttpClientAdapter {
|
||||
RecordedRequest(
|
||||
method: options.method,
|
||||
path: options.path,
|
||||
uri: options.uri,
|
||||
headers: Map<String, dynamic>.from(options.headers),
|
||||
body: options.data,
|
||||
),
|
||||
@@ -98,3 +103,144 @@ Map<String, dynamic> errorBody(String code) => <String, dynamic>{
|
||||
'message': 'stub message',
|
||||
'requestId': 'req-stub',
|
||||
};
|
||||
|
||||
// ── 相册域 fixtures(P3 计划 Task 4;形状对齐 openapi.yaml schemas)──
|
||||
|
||||
/// 契约 `Album` 响应体(GET/POST /albums、PATCH /albums/{id})。
|
||||
Map<String, dynamic> albumJson({
|
||||
String id = 'alb-1',
|
||||
String publicToken = 'sharetoken000000000001',
|
||||
String ownerId = 'u-owner',
|
||||
String status = 'active',
|
||||
String defaultLocale = 'zh-CN',
|
||||
String timezone = 'Asia/Shanghai',
|
||||
String startAt = '2026-09-18T06:30:00Z', // 上海墙钟 14:30
|
||||
String? endAt,
|
||||
bool uploadEnabled = true,
|
||||
bool publicEnabled = true,
|
||||
bool downloadEnabled = true,
|
||||
bool originalDownloadEnabled = false,
|
||||
List<Map<String, dynamic>>? translations,
|
||||
List<Map<String, dynamic>> categories = const <Map<String, dynamic>>[],
|
||||
}) =>
|
||||
<String, dynamic>{
|
||||
'id': id,
|
||||
'publicToken': publicToken,
|
||||
'ownerId': ownerId,
|
||||
'status': status,
|
||||
'defaultLocale': defaultLocale,
|
||||
'timezone': timezone,
|
||||
'startAt': startAt,
|
||||
'endAt': endAt,
|
||||
'uploadEnabled': uploadEnabled,
|
||||
'publicEnabled': publicEnabled,
|
||||
'downloadEnabled': downloadEnabled,
|
||||
'originalDownloadEnabled': originalDownloadEnabled,
|
||||
'watermarkVersion': 0,
|
||||
'translations': translations ??
|
||||
<Map<String, dynamic>>[
|
||||
<String, dynamic>{
|
||||
'locale': 'zh-CN',
|
||||
'title': '开幕晚宴',
|
||||
'description': null,
|
||||
'venue': '大宴会厅',
|
||||
'address': null,
|
||||
},
|
||||
<String, dynamic>{
|
||||
'locale': 'en',
|
||||
'title': 'Opening Gala',
|
||||
'description': null,
|
||||
'venue': null,
|
||||
'address': null,
|
||||
},
|
||||
],
|
||||
'categories': categories,
|
||||
'createdAt': '2026-09-01T00:00:00Z',
|
||||
'updatedAt': '2026-09-01T00:00:00Z',
|
||||
'statsSyncedAt': null,
|
||||
};
|
||||
|
||||
/// 契约 `Category` 响应体。
|
||||
Map<String, dynamic> categoryJson({
|
||||
String id = 'cat-1',
|
||||
String albumId = 'alb-1',
|
||||
int sortOrder = 0,
|
||||
List<Map<String, dynamic>>? translations,
|
||||
}) =>
|
||||
<String, dynamic>{
|
||||
'id': id,
|
||||
'albumId': albumId,
|
||||
'sortOrder': sortOrder,
|
||||
'translations': translations ??
|
||||
<Map<String, dynamic>>[
|
||||
<String, dynamic>{'locale': 'zh-CN', 'name': '仪式'},
|
||||
<String, dynamic>{'locale': 'en', 'name': 'Ceremony'},
|
||||
],
|
||||
};
|
||||
|
||||
/// 契约 `Member` 响应体。
|
||||
Map<String, dynamic> memberJson({
|
||||
String userId = 'u-2',
|
||||
String account = 'staff02',
|
||||
String displayName = 'Staff Two',
|
||||
String role = 'collaborator',
|
||||
}) =>
|
||||
<String, dynamic>{
|
||||
'userId': userId,
|
||||
'account': account,
|
||||
'displayName': displayName,
|
||||
'role': role,
|
||||
'status': 'active',
|
||||
};
|
||||
|
||||
/// 契约 `AdminUserLookupItem` 响应体。
|
||||
Map<String, dynamic> lookupUserJson({
|
||||
String id = 'u-9',
|
||||
String account = 'staff09',
|
||||
String displayName = 'Staff Nine',
|
||||
}) =>
|
||||
<String, dynamic>{
|
||||
'id': id,
|
||||
'account': account,
|
||||
'displayName': displayName,
|
||||
};
|
||||
|
||||
/// 契约 `AdminPhoto` 响应体。
|
||||
Map<String, dynamic> adminPhotoJson({
|
||||
String photoId = 'ph-00000001',
|
||||
String albumId = 'alb-1',
|
||||
String visibility = 'published',
|
||||
String processingState = 'ready',
|
||||
int bytes = 123456,
|
||||
}) =>
|
||||
<String, dynamic>{
|
||||
'photoId': photoId,
|
||||
'albumId': albumId,
|
||||
'categoryId': null,
|
||||
'uploaderId': 'u-2',
|
||||
'visibility': visibility,
|
||||
'processingState': processingState,
|
||||
'bytes': bytes,
|
||||
'width': 4000,
|
||||
'height': 3000,
|
||||
'shotAt': null,
|
||||
'uploadedAt': '2026-09-18T07:00:00Z',
|
||||
'publishedAt': '2026-09-18T07:05:00Z',
|
||||
'likeCount': 0,
|
||||
'uploader': <String, dynamic>{
|
||||
'userId': 'u-2',
|
||||
'account': 'staff02',
|
||||
'displayName': 'Staff Two',
|
||||
},
|
||||
};
|
||||
|
||||
/// 契约游标分页响应体(hasMore 与 nextCursor 成对)。
|
||||
Map<String, dynamic> cursorPageBody(
|
||||
List<Map<String, dynamic>> items, {
|
||||
String? nextCursor,
|
||||
}) =>
|
||||
<String, dynamic>{
|
||||
'items': items,
|
||||
'nextCursor': nextCursor,
|
||||
'hasMore': nextCursor != null,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user