| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- import 'package:dio/dio.dart';
- import 'package:flutter/material.dart';
- import '../l10n/app_localizations.dart';
- import '../network/api_response.dart';
- /// 从异常中提取用户可读的错误信息(只取业务 message,去掉 Dio/错误码前缀)
- String extractErrorMessage(Object e) {
- if (e is DioException) {
- final data = e.response?.data;
- if (data is Map) {
- final msg = data['message']?.toString().trim() ??
- data['msg']?.toString().trim() ??
- '';
- if (msg.isNotEmpty) {
- return msg;
- }
- }
- if (e.error is ApiException) {
- return (e.error as ApiException).message;
- }
- }
- if (e is ApiException) {
- return e.message;
- }
- return e.toString();
- }
- /// 通用确认弹框,返回 true 表示用户点击了确定
- Future<bool> showConfirmDialog(
- BuildContext context, {
- required String content,
- String? cancelText,
- String? confirmText,
- }) async {
- final l10n = AppLocalizations.of(context)!;
- final cancelLabel = cancelText ?? l10n.cancel;
- final confirmLabel = confirmText ?? l10n.confirm;
- final result = await showDialog<bool>(
- context: context,
- barrierDismissible: false,
- builder: (ctx) {
- final cs = Theme.of(ctx).colorScheme;
- return AlertDialog(
- shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
- contentPadding: const EdgeInsets.fromLTRB(24, 28, 24, 8),
- actionsPadding: EdgeInsets.zero,
- content: Text(
- content,
- textAlign: TextAlign.center,
- style: const TextStyle(fontSize: 15, height: 1.5),
- ),
- actions: [
- const Divider(height: 1),
- Row(
- children: [
- Expanded(
- child: TextButton(
- onPressed: () => Navigator.of(ctx).pop(false),
- style: TextButton.styleFrom(
- foregroundColor: Colors.grey,
- padding: const EdgeInsets.symmetric(vertical: 14),
- shape: const RoundedRectangleBorder(
- borderRadius: BorderRadius.only(
- bottomLeft: Radius.circular(16),
- ),
- ),
- ),
- child: Text(cancelLabel, style: const TextStyle(fontSize: 15)),
- ),
- ),
- const VerticalDivider(width: 1),
- Expanded(
- child: TextButton(
- onPressed: () => Navigator.of(ctx).pop(true),
- style: TextButton.styleFrom(
- foregroundColor: cs.onSurface,
- padding: const EdgeInsets.symmetric(vertical: 14),
- shape: const RoundedRectangleBorder(
- borderRadius: BorderRadius.only(
- bottomRight: Radius.circular(16),
- ),
- ),
- ),
- child: Text(
- confirmLabel,
- style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600),
- ),
- ),
- ),
- ],
- ),
- ],
- );
- },
- );
- return result ?? false;
- }
- /// 通用提示弹框(仅一个确定按钮)
- Future<void> showTipDialog(
- BuildContext context, {
- required String content,
- String? confirmText,
- }) async {
- final confirmLabel = confirmText ?? AppLocalizations.of(context)!.confirm;
- await showDialog<void>(
- context: context,
- builder: (ctx) {
- final cs = Theme.of(ctx).colorScheme;
- return AlertDialog(
- shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
- contentPadding: const EdgeInsets.fromLTRB(24, 28, 24, 8),
- actionsPadding: EdgeInsets.zero,
- content: Text(
- content,
- textAlign: TextAlign.center,
- style: const TextStyle(fontSize: 15, height: 1.5),
- ),
- actions: [
- const Divider(height: 1),
- SizedBox(
- width: double.infinity,
- child: TextButton(
- onPressed: () => Navigator.of(ctx).pop(),
- style: TextButton.styleFrom(
- foregroundColor: cs.onSurface,
- padding: const EdgeInsets.symmetric(vertical: 14),
- shape: const RoundedRectangleBorder(
- borderRadius: BorderRadius.only(
- bottomLeft: Radius.circular(16),
- bottomRight: Radius.circular(16),
- ),
- ),
- ),
- child: Text(
- confirmLabel,
- style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600),
- ),
- ),
- ),
- ],
- );
- },
- );
- }
|