- photo_upload_provider/photo_guide_page:4 类照片(大头照/正面/侧面/背面)拍照或相册上传 - body_provider/body_tune_page:身高 145-200cm / 体重 / 肤色 1-5 滑杆设置 - avatar_provider:化身构建(同步 + 异步轮询兜底) - profile_page:形象主页聚合化身/照片/身形状态 + 登出 - wardrobe_provider/wardrobe_page/wardrobe_upload_page:网格展示 + 分类筛选 + 长按删除 + 表单上传 - AppConfig.resolveUrl 相对路径拼接;新增 /photo-guide /body-tune /wardrobe-upload 路由
78 lines
2.1 KiB
Dart
78 lines
2.1 KiB
Dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
|
|
import '../../core/auth/auth_provider.dart';
|
|
|
|
/// 照片类型(与后端 consts.PhotoType 对应)
|
|
class PhotoType {
|
|
static const int headshot = 1;
|
|
static const int fullFront = 2;
|
|
static const int fullSide = 3;
|
|
static const int fullBack = 4;
|
|
|
|
static const Map<int, String> labels = {
|
|
headshot: '大头照',
|
|
fullFront: '全身正面',
|
|
fullSide: '全身侧面',
|
|
fullBack: '全身背面',
|
|
};
|
|
|
|
static const Map<int, String> descs = {
|
|
headshot: '清晰正脸、光线充足',
|
|
fullFront: '站立正面全身,拍全脚底',
|
|
fullSide: '站立侧面全身,自然放松',
|
|
fullBack: '站立背面全身,露出轮廓',
|
|
};
|
|
|
|
static const List<int> all = [headshot, fullFront, fullSide, fullBack];
|
|
}
|
|
|
|
class UserPhotoInfo {
|
|
final int id;
|
|
final int type;
|
|
final String url;
|
|
|
|
const UserPhotoInfo({
|
|
required this.id,
|
|
required this.type,
|
|
required this.url,
|
|
});
|
|
}
|
|
|
|
class PhotoNotifier extends AsyncNotifier<List<UserPhotoInfo>> {
|
|
@override
|
|
Future<List<UserPhotoInfo>> build() async {
|
|
final api = ref.read(apiClientProvider);
|
|
final list = await api.get<List<dynamic>>('/user-photo/list');
|
|
return list
|
|
.map((e) => UserPhotoInfo(
|
|
id: (e['id'] as num).toInt(),
|
|
type: (e['type'] as num).toInt(),
|
|
url: e['url'] as String? ?? '',
|
|
))
|
|
.toList();
|
|
}
|
|
|
|
Future<void> upload(int type, String filePath) async {
|
|
final api = ref.read(apiClientProvider);
|
|
await api.upload('/user-photo/upload', {'type': type}, 'file', filePath);
|
|
await refresh();
|
|
}
|
|
|
|
Future<void> delete(int id) async {
|
|
final api = ref.read(apiClientProvider);
|
|
await api.post('/user-photo/delete', {'id': id});
|
|
await refresh();
|
|
}
|
|
|
|
Future<void> refresh() async {
|
|
state = const AsyncLoading();
|
|
state = await AsyncValue.guard(build);
|
|
}
|
|
|
|
/// 某类型是否已上传
|
|
bool hasType(int type) => state.value?.any((p) => p.type == type) ?? false;
|
|
}
|
|
|
|
final photoProvider =
|
|
AsyncNotifierProvider<PhotoNotifier, List<UserPhotoInfo>>(PhotoNotifier.new);
|