feat: 接入起卦后端流程并完善积分扣减链路

This commit is contained in:
qzl
2026-04-03 19:04:46 +08:00
parent a136e42290
commit d87b2e1e3a
56 changed files with 3310 additions and 809 deletions
@@ -1,17 +1,30 @@
import 'package:flutter/material.dart';
import '../../../../app/di/injection.dart';
import '../../../../core/auth/session_store.dart';
import '../../../../data/network/api_client.dart';
import '../../../../l10n/app_localizations.dart';
import '../../../../shared/theme/app_color_palette.dart';
import '../../../../shared/theme/design_tokens.dart';
import '../../../../shared/widgets/divination/divination_shared_widgets.dart';
import '../../../../shared/widgets/toast/toast.dart';
import '../../../../shared/widgets/toast/toast_type.dart';
import '../../data/apis/divination_api.dart';
import '../../data/models/divination_params.dart';
import '../../data/services/divination_run_service.dart';
import 'auto_divination_screen.dart';
import 'manual_divination_screen.dart';
class DivinationScreen extends StatefulWidget {
const DivinationScreen({super.key});
const DivinationScreen({
super.key,
required this.sessionStore,
required this.userId,
this.runServiceOverride,
});
final SessionStore sessionStore;
final String userId;
final DivinationRunService? runServiceOverride;
@override
State<DivinationScreen> createState() => _DivinationScreenState();
@@ -20,11 +33,26 @@ class DivinationScreen extends StatefulWidget {
class _DivinationScreenState extends State<DivinationScreen> {
late DivinationParams _params;
final TextEditingController _questionController = TextEditingController();
late final DivinationRunService _runService;
@override
void initState() {
super.initState();
_params = DivinationMockData.initial();
final apiClient = ApiClient(
baseUrl: appDependencies.backendUrl,
tokenProvider: widget.sessionStore.getToken,
);
_runService =
widget.runServiceOverride ??
DivinationRunService(api: DivinationApi(apiClient: apiClient));
_params = DivinationParams(
method: DivinationMethod.manual,
questionType: QuestionType.career,
question: '',
divinationTime: DateTime.now(),
coinBalance: 0,
userId: widget.userId,
);
_questionController.addListener(_syncQuestion);
}
@@ -58,7 +86,6 @@ class _DivinationScreenState extends State<DivinationScreen> {
}
Widget _buildBody(BuildContext context, AppLocalizations l10n) {
final palette = Theme.of(context).extension<AppColorPalette>()!;
return GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: SingleChildScrollView(
@@ -106,15 +133,6 @@ class _DivinationScreenState extends State<DivinationScreen> {
_QuestionTextField(controller: _questionController, l10n: l10n),
const SizedBox(height: AppSpacing.xl),
_StartButton(onPressed: _onStart, l10n: l10n),
const SizedBox(height: AppSpacing.sm),
Center(
child: Text(
l10n.divinationCoinBalance(_params.coinBalance),
style: Theme.of(
context,
).textTheme.bodySmall?.copyWith(color: palette.warning),
),
),
],
),
),
@@ -132,16 +150,14 @@ class _DivinationScreenState extends State<DivinationScreen> {
return;
}
if (_params.coinBalance <= 0) {
Toast.show(context, l10n.toastCoinInsufficient, type: ToastType.warning);
return;
}
if (_params.method == DivinationMethod.manual) {
final nextParams = _params.copyWith(divinationTime: DateTime.now());
Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (_) => ManualDivinationScreen(params: nextParams),
builder: (_) => ManualDivinationScreen(
params: nextParams,
runService: _runService,
),
),
);
return;
@@ -150,7 +166,8 @@ class _DivinationScreenState extends State<DivinationScreen> {
final nextParams = _params.copyWith(divinationTime: DateTime.now());
Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (_) => AutoDivinationScreen(params: nextParams),
builder: (_) =>
AutoDivinationScreen(params: nextParams, runService: _runService),
),
);
}