马良AI写作初始化仓库

This commit is contained in:
邓滨杰
2025-09-10 00:07:52 +08:00
parent 3c06bb1a03
commit 39c0f8840f
1309 changed files with 318528 additions and 0 deletions

View File

@@ -0,0 +1,165 @@
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:ainoval/utils/web_theme.dart';
import 'package:ainoval/models/admin/billing_models.dart';
import 'package:ainoval/services/api_service/repositories/impl/admin/billing_repository_impl.dart';
class BillingAuditScreen extends StatefulWidget {
const BillingAuditScreen({super.key});
@override
State<BillingAuditScreen> createState() => _BillingAuditScreenState();
}
class _BillingAuditScreenState extends State<BillingAuditScreen> {
late BillingRepositoryImpl _repo;
int _page = 0;
final int _size = 20;
String? _status;
String? _userId;
bool _loading = false;
List<CreditTransactionModel> _items = const [];
int _total = 0;
@override
void initState() {
super.initState();
_repo = GetIt.instance<BillingRepositoryImpl>();
_load();
}
Future<void> _load() async {
setState(() { _loading = true; });
try {
final results = await Future.wait([
_repo.listTransactions(page: _page, size: _size, status: _status, userId: _userId),
_repo.countTransactions(status: _status, userId: _userId),
]);
setState(() {
_items = results[0] as List<CreditTransactionModel>;
_total = results[1] as int;
});
} finally {
if (mounted) setState(() { _loading = false; });
}
}
Future<void> _reverse(CreditTransactionModel tx) async {
final controller = TextEditingController();
final reason = await showDialog<String>(context: context, builder: (ctx) {
return AlertDialog(
title: const Text('输入冲正原因'),
content: TextField(controller: controller, decoration: const InputDecoration(hintText: '原因...')),
actions: [
TextButton(onPressed: () => Navigator.pop(ctx), child: const Text('取消')),
ElevatedButton(onPressed: () => Navigator.pop(ctx, controller.text.trim()), child: const Text('确认')),
],
);
});
if (reason == null || reason.isEmpty) return;
await _repo.reverse(tx.traceId, operatorUserId: 'admin', reason: reason);
await _load();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: WebTheme.getBackgroundColor(context),
appBar: AppBar(
backgroundColor: WebTheme.getBackgroundColor(context),
foregroundColor: WebTheme.getTextColor(context),
title: Text('计费审计', style: TextStyle(color: WebTheme.getTextColor(context))),
actions: [
IconButton(onPressed: _load, icon: const Icon(Icons.refresh)),
],
),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
Row(children: [
SizedBox(
width: 200,
child: DropdownButtonFormField<String>(
decoration: const InputDecoration(labelText: '状态'),
value: _status,
items: const [
DropdownMenuItem(value: null, child: Text('全部')),
DropdownMenuItem(value: 'PENDING', child: Text('PENDING')),
DropdownMenuItem(value: 'FAILED', child: Text('FAILED')),
DropdownMenuItem(value: 'DEDUCTED', child: Text('DEDUCTED')),
DropdownMenuItem(value: 'COMPENSATED', child: Text('COMPENSATED')),
],
onChanged: (v) { setState(() { _status = v; _page = 0; }); _load(); },
),
),
const SizedBox(width: 16),
SizedBox(
width: 260,
child: TextField(
decoration: const InputDecoration(labelText: '用户ID'),
onSubmitted: (v) { setState(() { _userId = v.trim().isEmpty ? null : v.trim(); _page = 0; }); _load(); },
),
),
]),
const SizedBox(height: 12),
Expanded(
child: _loading
? const Center(child: CircularProgressIndicator())
: SingleChildScrollView(
child: DataTable(
columns: const [
DataColumn(label: Text('TraceID')),
DataColumn(label: Text('User')),
DataColumn(label: Text('Model')),
DataColumn(label: Text('Feature')),
DataColumn(label: Text('In/Out')),
DataColumn(label: Text('Credits')),
DataColumn(label: Text('Status')),
DataColumn(label: Text('Action')),
],
rows: _items.map((tx) {
final model = [tx.provider ?? '-', tx.modelId ?? '-'].where((e) => e != '-').join(':');
final io = '${tx.inputTokens ?? 0}/${tx.outputTokens ?? 0}';
final canReverse = tx.status == 'DEDUCTED' || tx.status == 'COMPENSATED';
return DataRow(cells: [
DataCell(Text(tx.traceId, overflow: TextOverflow.ellipsis)),
DataCell(Text(tx.userId ?? '-')),
DataCell(Text(model.isEmpty ? '-' : model)),
DataCell(Text(tx.featureType ?? '-')),
DataCell(Text(io)),
DataCell(Text('${tx.creditsDeducted ?? 0}')),
DataCell(Text(tx.status)),
DataCell(Row(children: [
if (canReverse) ElevatedButton.icon(onPressed: () => _reverse(tx), icon: const Icon(Icons.undo), label: const Text('冲正')),
])),
]);
}).toList(),
),
),
),
const SizedBox(height: 8),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text('$_total'),
const SizedBox(width: 16),
IconButton(
onPressed: _page > 0 ? () { setState(() { _page--; }); _load(); } : null,
icon: const Icon(Icons.chevron_left),
),
Text('${_page + 1}'),
IconButton(
onPressed: ((_page + 1) * _size) < _total ? () { setState(() { _page++; }); _load(); } : null,
icon: const Icon(Icons.chevron_right),
),
],
),
],
),
),
);
}
}