36e5677b7c
- feedback_repository + provider:图片上传 /feedback/images、提交 /feedback - 关于我们的反馈入口改为表单弹窗:多行文字 + 选图上传(缩略图/可删,最多9张), 提交到后台,不再走 mailto - 平台/版本随提交上报(web 安全:defaultTargetPlatform,不引 dart:io) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
79 lines
2.2 KiB
Dart
79 lines
2.2 KiB
Dart
import 'package:dio/dio.dart';
|
||
import 'package:flutter/foundation.dart';
|
||
import 'package:package_info_plus/package_info_plus.dart';
|
||
import '../core/api/api_client.dart';
|
||
import '../core/exceptions.dart';
|
||
|
||
class FeedbackRepository {
|
||
final ApiClient _client;
|
||
const FeedbackRepository(this._client);
|
||
|
||
/// 上传单张图片,返回服务器相对 URL(/images/feedback/...)。
|
||
Future<String> uploadImage({
|
||
Uint8List? bytes,
|
||
String? filePath,
|
||
String filename = 'image.jpg',
|
||
}) async {
|
||
try {
|
||
final MultipartFile file;
|
||
if (bytes != null) {
|
||
file = MultipartFile.fromBytes(bytes, filename: filename);
|
||
} else {
|
||
file = await MultipartFile.fromFile(filePath!);
|
||
}
|
||
final formData = FormData.fromMap({'file': file});
|
||
final resp = await _client.post('/feedback/images', data: formData);
|
||
return (resp.data as Map<String, dynamic>)['url'] as String;
|
||
} on DioException catch (e) {
|
||
throw AppException(
|
||
e.response?.data?['error'] as String? ?? '图片上传失败',
|
||
statusCode: e.response?.statusCode,
|
||
);
|
||
}
|
||
}
|
||
|
||
/// 提交反馈(bug / suggestion),文字 + 图片 URL 列表。
|
||
Future<void> submit({
|
||
required String type,
|
||
required String content,
|
||
required List<String> images,
|
||
}) async {
|
||
String appVersion = '';
|
||
try {
|
||
appVersion = (await PackageInfo.fromPlatform()).version;
|
||
} catch (_) {}
|
||
try {
|
||
await _client.post('/feedback', data: {
|
||
'type': type,
|
||
'content': content,
|
||
'images': images,
|
||
'app_version': appVersion,
|
||
'platform': _platform(),
|
||
});
|
||
} on DioException catch (e) {
|
||
throw AppException(
|
||
e.response?.data?['error'] as String? ?? '提交失败',
|
||
statusCode: e.response?.statusCode,
|
||
);
|
||
}
|
||
}
|
||
|
||
String _platform() {
|
||
if (kIsWeb) return 'web';
|
||
switch (defaultTargetPlatform) {
|
||
case TargetPlatform.windows:
|
||
return 'windows';
|
||
case TargetPlatform.macOS:
|
||
return 'macos';
|
||
case TargetPlatform.android:
|
||
return 'android';
|
||
case TargetPlatform.iOS:
|
||
return 'ios';
|
||
case TargetPlatform.linux:
|
||
return 'linux';
|
||
default:
|
||
return 'unknown';
|
||
}
|
||
}
|
||
}
|