马良AI写作初始化仓库
This commit is contained in:
85
AINoval/lib/models/admin/admin_auth_models.dart
Normal file
85
AINoval/lib/models/admin/admin_auth_models.dart
Normal file
@@ -0,0 +1,85 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
/// 管理员认证请求
|
||||
class AdminAuthRequest extends Equatable {
|
||||
final String username;
|
||||
final String password;
|
||||
|
||||
const AdminAuthRequest({
|
||||
required this.username,
|
||||
required this.password,
|
||||
});
|
||||
|
||||
factory AdminAuthRequest.fromJson(Map<String, dynamic> json) {
|
||||
return AdminAuthRequest(
|
||||
username: json['username'] as String,
|
||||
password: json['password'] as String,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'username': username,
|
||||
'password': password,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [username, password];
|
||||
}
|
||||
|
||||
/// 管理员认证响应
|
||||
class AdminAuthResponse extends Equatable {
|
||||
final String token;
|
||||
final String refreshToken;
|
||||
final String userId;
|
||||
final String username;
|
||||
final String? displayName;
|
||||
final List<String> roles;
|
||||
final List<String> permissions;
|
||||
|
||||
const AdminAuthResponse({
|
||||
required this.token,
|
||||
required this.refreshToken,
|
||||
required this.userId,
|
||||
required this.username,
|
||||
this.displayName,
|
||||
required this.roles,
|
||||
required this.permissions,
|
||||
});
|
||||
|
||||
factory AdminAuthResponse.fromJson(Map<String, dynamic> json) {
|
||||
return AdminAuthResponse(
|
||||
token: json['token'] as String,
|
||||
refreshToken: json['refreshToken'] as String,
|
||||
userId: json['userId'] as String,
|
||||
username: json['username'] as String,
|
||||
displayName: json['displayName'] as String?,
|
||||
roles: List<String>.from(json['roles'] as List? ?? []),
|
||||
permissions: List<String>.from(json['permissions'] as List? ?? []),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'token': token,
|
||||
'refreshToken': refreshToken,
|
||||
'userId': userId,
|
||||
'username': username,
|
||||
'displayName': displayName,
|
||||
'roles': roles,
|
||||
'permissions': permissions,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
token,
|
||||
refreshToken,
|
||||
userId,
|
||||
username,
|
||||
displayName,
|
||||
roles,
|
||||
permissions,
|
||||
];
|
||||
}
|
||||
295
AINoval/lib/models/admin/admin_models.dart
Normal file
295
AINoval/lib/models/admin/admin_models.dart
Normal file
@@ -0,0 +1,295 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import '../../utils/date_time_parser.dart';
|
||||
|
||||
part 'admin_models.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
class AdminDashboardStats extends Equatable {
|
||||
final int totalUsers;
|
||||
final int activeUsers;
|
||||
final int totalNovels;
|
||||
final int aiRequestsToday;
|
||||
final double creditsConsumed;
|
||||
final List<ChartData> userGrowthData;
|
||||
final List<ChartData> requestsData;
|
||||
final List<ActivityItem> recentActivities;
|
||||
|
||||
const AdminDashboardStats({
|
||||
required this.totalUsers,
|
||||
required this.activeUsers,
|
||||
required this.totalNovels,
|
||||
required this.aiRequestsToday,
|
||||
required this.creditsConsumed,
|
||||
required this.userGrowthData,
|
||||
required this.requestsData,
|
||||
required this.recentActivities,
|
||||
});
|
||||
|
||||
factory AdminDashboardStats.fromJson(Map<String, dynamic> json) =>
|
||||
_$AdminDashboardStatsFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$AdminDashboardStatsToJson(this);
|
||||
|
||||
@override
|
||||
List<Object> get props => [
|
||||
totalUsers,
|
||||
activeUsers,
|
||||
totalNovels,
|
||||
aiRequestsToday,
|
||||
creditsConsumed,
|
||||
userGrowthData,
|
||||
requestsData,
|
||||
recentActivities,
|
||||
];
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class ChartData extends Equatable {
|
||||
final String label;
|
||||
final double value;
|
||||
final DateTime date;
|
||||
|
||||
const ChartData({
|
||||
required this.label,
|
||||
required this.value,
|
||||
required this.date,
|
||||
});
|
||||
|
||||
|
||||
factory ChartData.fromJson(Map<String, dynamic> json) {
|
||||
return ChartData(
|
||||
label: json['label'] as String,
|
||||
value: (json['value'] as num).toDouble(),
|
||||
date: parseBackendDateTime(json['date']),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => _$ChartDataToJson(this);
|
||||
|
||||
@override
|
||||
List<Object> get props => [label, value, date];
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class ActivityItem extends Equatable {
|
||||
final String id;
|
||||
final String userId;
|
||||
final String userName;
|
||||
final String action;
|
||||
final String description;
|
||||
final DateTime timestamp;
|
||||
final String? metadata;
|
||||
|
||||
const ActivityItem({
|
||||
required this.id,
|
||||
required this.userId,
|
||||
required this.userName,
|
||||
required this.action,
|
||||
required this.description,
|
||||
required this.timestamp,
|
||||
this.metadata,
|
||||
});
|
||||
|
||||
factory ActivityItem.fromJson(Map<String, dynamic> json) {
|
||||
return ActivityItem(
|
||||
id: json['id'] as String,
|
||||
userId: json['userId'] as String,
|
||||
userName: json['userName'] as String,
|
||||
action: json['action'] as String,
|
||||
description: json['description'] as String,
|
||||
timestamp: parseBackendDateTime(json['timestamp']),
|
||||
metadata: json['metadata'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => _$ActivityItemToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
id,
|
||||
userId,
|
||||
userName,
|
||||
action,
|
||||
description,
|
||||
timestamp,
|
||||
metadata,
|
||||
];
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class AdminUser extends Equatable {
|
||||
final String id;
|
||||
final String username;
|
||||
final String email; // 后端可能返回 null,这里统一转换为空串
|
||||
final String? displayName;
|
||||
final String accountStatus;
|
||||
final int credits;
|
||||
final List<String> roles;
|
||||
final DateTime createdAt;
|
||||
final DateTime? updatedAt;
|
||||
|
||||
const AdminUser({
|
||||
required this.id,
|
||||
required this.username,
|
||||
required this.email,
|
||||
this.displayName,
|
||||
required this.accountStatus,
|
||||
required this.credits,
|
||||
required this.roles,
|
||||
required this.createdAt,
|
||||
this.updatedAt,
|
||||
});
|
||||
|
||||
factory AdminUser.fromJson(Map<String, dynamic> json) {
|
||||
return AdminUser(
|
||||
id: json['id'] as String,
|
||||
username: json['username'] as String,
|
||||
email: (json['email'] as String?) ?? '',
|
||||
displayName: json['displayName'] as String?,
|
||||
accountStatus: json['accountStatus']?.toString() ?? 'ACTIVE',
|
||||
credits: (json['credits'] as num?)?.toInt() ?? 0,
|
||||
roles: (json['roles'] as List?)?.map((e) => e.toString()).toList() ?? [],
|
||||
createdAt: parseBackendDateTime(json['createdAt']),
|
||||
updatedAt: json['updatedAt'] != null ? parseBackendDateTime(json['updatedAt']) : null,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => _$AdminUserToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
id,
|
||||
username,
|
||||
email,
|
||||
displayName,
|
||||
accountStatus,
|
||||
credits,
|
||||
roles,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
];
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class AdminRole extends Equatable {
|
||||
final String? id;
|
||||
final String roleName;
|
||||
final String displayName;
|
||||
final String? description;
|
||||
final List<String> permissions;
|
||||
final bool enabled;
|
||||
final int priority;
|
||||
|
||||
const AdminRole({
|
||||
this.id,
|
||||
required this.roleName,
|
||||
required this.displayName,
|
||||
this.description,
|
||||
required this.permissions,
|
||||
required this.enabled,
|
||||
required this.priority,
|
||||
});
|
||||
|
||||
factory AdminRole.fromJson(Map<String, dynamic> json) =>
|
||||
_$AdminRoleFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$AdminRoleToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
id,
|
||||
roleName,
|
||||
displayName,
|
||||
description,
|
||||
permissions,
|
||||
enabled,
|
||||
priority,
|
||||
];
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class AdminModelConfig extends Equatable {
|
||||
final String? id;
|
||||
final String provider;
|
||||
final String modelId;
|
||||
final String? displayName;
|
||||
final bool enabled;
|
||||
final List<String> enabledForFeatures;
|
||||
final double creditRateMultiplier;
|
||||
final int maxConcurrentRequests;
|
||||
final int dailyRequestLimit;
|
||||
final String? description;
|
||||
|
||||
const AdminModelConfig({
|
||||
this.id,
|
||||
required this.provider,
|
||||
required this.modelId,
|
||||
this.displayName,
|
||||
required this.enabled,
|
||||
required this.enabledForFeatures,
|
||||
required this.creditRateMultiplier,
|
||||
required this.maxConcurrentRequests,
|
||||
required this.dailyRequestLimit,
|
||||
this.description,
|
||||
});
|
||||
|
||||
factory AdminModelConfig.fromJson(Map<String, dynamic> json) =>
|
||||
_$AdminModelConfigFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$AdminModelConfigToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
id,
|
||||
provider,
|
||||
modelId,
|
||||
displayName,
|
||||
enabled,
|
||||
enabledForFeatures,
|
||||
creditRateMultiplier,
|
||||
maxConcurrentRequests,
|
||||
dailyRequestLimit,
|
||||
description,
|
||||
];
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class AdminSystemConfig extends Equatable {
|
||||
final String id;
|
||||
final String configKey;
|
||||
final String configValue;
|
||||
final String? description;
|
||||
final String configType;
|
||||
final String? configGroup;
|
||||
final bool enabled;
|
||||
final bool readOnly;
|
||||
|
||||
const AdminSystemConfig({
|
||||
required this.id,
|
||||
required this.configKey,
|
||||
required this.configValue,
|
||||
this.description,
|
||||
required this.configType,
|
||||
this.configGroup,
|
||||
required this.enabled,
|
||||
required this.readOnly,
|
||||
});
|
||||
|
||||
factory AdminSystemConfig.fromJson(Map<String, dynamic> json) =>
|
||||
_$AdminSystemConfigFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$AdminSystemConfigToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
id,
|
||||
configKey,
|
||||
configValue,
|
||||
description,
|
||||
configType,
|
||||
configGroup,
|
||||
enabled,
|
||||
readOnly,
|
||||
];
|
||||
}
|
||||
282
AINoval/lib/models/admin/admin_models.g.dart
Normal file
282
AINoval/lib/models/admin/admin_models.g.dart
Normal file
@@ -0,0 +1,282 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'admin_models.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
AdminDashboardStats _$AdminDashboardStatsFromJson(Map<String, dynamic> json) =>
|
||||
$checkedCreate(
|
||||
'AdminDashboardStats',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = AdminDashboardStats(
|
||||
totalUsers: $checkedConvert('totalUsers', (v) => (v as num).toInt()),
|
||||
activeUsers:
|
||||
$checkedConvert('activeUsers', (v) => (v as num).toInt()),
|
||||
totalNovels:
|
||||
$checkedConvert('totalNovels', (v) => (v as num).toInt()),
|
||||
aiRequestsToday:
|
||||
$checkedConvert('aiRequestsToday', (v) => (v as num).toInt()),
|
||||
creditsConsumed:
|
||||
$checkedConvert('creditsConsumed', (v) => (v as num).toDouble()),
|
||||
userGrowthData: $checkedConvert(
|
||||
'userGrowthData',
|
||||
(v) => (v as List<dynamic>)
|
||||
.map((e) => ChartData.fromJson(e as Map<String, dynamic>))
|
||||
.toList()),
|
||||
requestsData: $checkedConvert(
|
||||
'requestsData',
|
||||
(v) => (v as List<dynamic>)
|
||||
.map((e) => ChartData.fromJson(e as Map<String, dynamic>))
|
||||
.toList()),
|
||||
recentActivities: $checkedConvert(
|
||||
'recentActivities',
|
||||
(v) => (v as List<dynamic>)
|
||||
.map((e) => ActivityItem.fromJson(e as Map<String, dynamic>))
|
||||
.toList()),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$AdminDashboardStatsToJson(
|
||||
AdminDashboardStats instance) =>
|
||||
<String, dynamic>{
|
||||
'totalUsers': instance.totalUsers,
|
||||
'activeUsers': instance.activeUsers,
|
||||
'totalNovels': instance.totalNovels,
|
||||
'aiRequestsToday': instance.aiRequestsToday,
|
||||
'creditsConsumed': instance.creditsConsumed,
|
||||
'userGrowthData': instance.userGrowthData.map((e) => e.toJson()).toList(),
|
||||
'requestsData': instance.requestsData.map((e) => e.toJson()).toList(),
|
||||
'recentActivities':
|
||||
instance.recentActivities.map((e) => e.toJson()).toList(),
|
||||
};
|
||||
|
||||
ChartData _$ChartDataFromJson(Map<String, dynamic> json) => $checkedCreate(
|
||||
'ChartData',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = ChartData(
|
||||
label: $checkedConvert('label', (v) => v as String),
|
||||
value: $checkedConvert('value', (v) => (v as num).toDouble()),
|
||||
date: $checkedConvert('date', (v) => DateTime.parse(v as String)),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$ChartDataToJson(ChartData instance) => <String, dynamic>{
|
||||
'label': instance.label,
|
||||
'value': instance.value,
|
||||
'date': instance.date.toIso8601String(),
|
||||
};
|
||||
|
||||
ActivityItem _$ActivityItemFromJson(Map<String, dynamic> json) =>
|
||||
$checkedCreate(
|
||||
'ActivityItem',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = ActivityItem(
|
||||
id: $checkedConvert('id', (v) => v as String),
|
||||
userId: $checkedConvert('userId', (v) => v as String),
|
||||
userName: $checkedConvert('userName', (v) => v as String),
|
||||
action: $checkedConvert('action', (v) => v as String),
|
||||
description: $checkedConvert('description', (v) => v as String),
|
||||
timestamp:
|
||||
$checkedConvert('timestamp', (v) => DateTime.parse(v as String)),
|
||||
metadata: $checkedConvert('metadata', (v) => v as String?),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$ActivityItemToJson(ActivityItem instance) {
|
||||
final val = <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'userId': instance.userId,
|
||||
'userName': instance.userName,
|
||||
'action': instance.action,
|
||||
'description': instance.description,
|
||||
'timestamp': instance.timestamp.toIso8601String(),
|
||||
};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('metadata', instance.metadata);
|
||||
return val;
|
||||
}
|
||||
|
||||
AdminUser _$AdminUserFromJson(Map<String, dynamic> json) => $checkedCreate(
|
||||
'AdminUser',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = AdminUser(
|
||||
id: $checkedConvert('id', (v) => v as String),
|
||||
username: $checkedConvert('username', (v) => v as String),
|
||||
email: $checkedConvert('email', (v) => v as String),
|
||||
displayName: $checkedConvert('displayName', (v) => v as String?),
|
||||
accountStatus: $checkedConvert('accountStatus', (v) => v as String),
|
||||
credits: $checkedConvert('credits', (v) => (v as num).toInt()),
|
||||
roles: $checkedConvert('roles',
|
||||
(v) => (v as List<dynamic>).map((e) => e as String).toList()),
|
||||
createdAt:
|
||||
$checkedConvert('createdAt', (v) => DateTime.parse(v as String)),
|
||||
updatedAt: $checkedConvert('updatedAt',
|
||||
(v) => v == null ? null : DateTime.parse(v as String)),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$AdminUserToJson(AdminUser instance) {
|
||||
final val = <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'username': instance.username,
|
||||
'email': instance.email,
|
||||
};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('displayName', instance.displayName);
|
||||
val['accountStatus'] = instance.accountStatus;
|
||||
val['credits'] = instance.credits;
|
||||
val['roles'] = instance.roles;
|
||||
val['createdAt'] = instance.createdAt.toIso8601String();
|
||||
writeNotNull('updatedAt', instance.updatedAt?.toIso8601String());
|
||||
return val;
|
||||
}
|
||||
|
||||
AdminRole _$AdminRoleFromJson(Map<String, dynamic> json) => $checkedCreate(
|
||||
'AdminRole',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = AdminRole(
|
||||
id: $checkedConvert('id', (v) => v as String?),
|
||||
roleName: $checkedConvert('roleName', (v) => v as String),
|
||||
displayName: $checkedConvert('displayName', (v) => v as String),
|
||||
description: $checkedConvert('description', (v) => v as String?),
|
||||
permissions: $checkedConvert('permissions',
|
||||
(v) => (v as List<dynamic>).map((e) => e as String).toList()),
|
||||
enabled: $checkedConvert('enabled', (v) => v as bool),
|
||||
priority: $checkedConvert('priority', (v) => (v as num).toInt()),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$AdminRoleToJson(AdminRole instance) {
|
||||
final val = <String, dynamic>{};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('id', instance.id);
|
||||
val['roleName'] = instance.roleName;
|
||||
val['displayName'] = instance.displayName;
|
||||
writeNotNull('description', instance.description);
|
||||
val['permissions'] = instance.permissions;
|
||||
val['enabled'] = instance.enabled;
|
||||
val['priority'] = instance.priority;
|
||||
return val;
|
||||
}
|
||||
|
||||
AdminModelConfig _$AdminModelConfigFromJson(Map<String, dynamic> json) =>
|
||||
$checkedCreate(
|
||||
'AdminModelConfig',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = AdminModelConfig(
|
||||
id: $checkedConvert('id', (v) => v as String?),
|
||||
provider: $checkedConvert('provider', (v) => v as String),
|
||||
modelId: $checkedConvert('modelId', (v) => v as String),
|
||||
displayName: $checkedConvert('displayName', (v) => v as String?),
|
||||
enabled: $checkedConvert('enabled', (v) => v as bool),
|
||||
enabledForFeatures: $checkedConvert('enabledForFeatures',
|
||||
(v) => (v as List<dynamic>).map((e) => e as String).toList()),
|
||||
creditRateMultiplier: $checkedConvert(
|
||||
'creditRateMultiplier', (v) => (v as num).toDouble()),
|
||||
maxConcurrentRequests: $checkedConvert(
|
||||
'maxConcurrentRequests', (v) => (v as num).toInt()),
|
||||
dailyRequestLimit:
|
||||
$checkedConvert('dailyRequestLimit', (v) => (v as num).toInt()),
|
||||
description: $checkedConvert('description', (v) => v as String?),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$AdminModelConfigToJson(AdminModelConfig instance) {
|
||||
final val = <String, dynamic>{};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('id', instance.id);
|
||||
val['provider'] = instance.provider;
|
||||
val['modelId'] = instance.modelId;
|
||||
writeNotNull('displayName', instance.displayName);
|
||||
val['enabled'] = instance.enabled;
|
||||
val['enabledForFeatures'] = instance.enabledForFeatures;
|
||||
val['creditRateMultiplier'] = instance.creditRateMultiplier;
|
||||
val['maxConcurrentRequests'] = instance.maxConcurrentRequests;
|
||||
val['dailyRequestLimit'] = instance.dailyRequestLimit;
|
||||
writeNotNull('description', instance.description);
|
||||
return val;
|
||||
}
|
||||
|
||||
AdminSystemConfig _$AdminSystemConfigFromJson(Map<String, dynamic> json) =>
|
||||
$checkedCreate(
|
||||
'AdminSystemConfig',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = AdminSystemConfig(
|
||||
id: $checkedConvert('id', (v) => v as String),
|
||||
configKey: $checkedConvert('configKey', (v) => v as String),
|
||||
configValue: $checkedConvert('configValue', (v) => v as String),
|
||||
description: $checkedConvert('description', (v) => v as String?),
|
||||
configType: $checkedConvert('configType', (v) => v as String),
|
||||
configGroup: $checkedConvert('configGroup', (v) => v as String?),
|
||||
enabled: $checkedConvert('enabled', (v) => v as bool),
|
||||
readOnly: $checkedConvert('readOnly', (v) => v as bool),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$AdminSystemConfigToJson(AdminSystemConfig instance) {
|
||||
final val = <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'configKey': instance.configKey,
|
||||
'configValue': instance.configValue,
|
||||
};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('description', instance.description);
|
||||
val['configType'] = instance.configType;
|
||||
writeNotNull('configGroup', instance.configGroup);
|
||||
val['enabled'] = instance.enabled;
|
||||
val['readOnly'] = instance.readOnly;
|
||||
return val;
|
||||
}
|
||||
54
AINoval/lib/models/admin/billing_models.dart
Normal file
54
AINoval/lib/models/admin/billing_models.dart
Normal file
@@ -0,0 +1,54 @@
|
||||
class CreditTransactionModel {
|
||||
final String traceId;
|
||||
final String? userId;
|
||||
final String? provider;
|
||||
final String? modelId;
|
||||
final String? featureType;
|
||||
final int? inputTokens;
|
||||
final int? outputTokens;
|
||||
final int? creditsDeducted;
|
||||
final String status; // PENDING, DEDUCTED, FAILED, COMPENSATED
|
||||
final String? errorMessage;
|
||||
final String? reversalOfTraceId;
|
||||
final String? operatorUserId;
|
||||
final String? auditNote;
|
||||
final String? createdAt; // ISO8601 from backend
|
||||
|
||||
CreditTransactionModel({
|
||||
required this.traceId,
|
||||
required this.status,
|
||||
this.userId,
|
||||
this.provider,
|
||||
this.modelId,
|
||||
this.featureType,
|
||||
this.inputTokens,
|
||||
this.outputTokens,
|
||||
this.creditsDeducted,
|
||||
this.errorMessage,
|
||||
this.reversalOfTraceId,
|
||||
this.operatorUserId,
|
||||
this.auditNote,
|
||||
this.createdAt,
|
||||
});
|
||||
|
||||
factory CreditTransactionModel.fromJson(Map<String, dynamic> json) {
|
||||
return CreditTransactionModel(
|
||||
traceId: (json['traceId'] ?? '').toString(),
|
||||
userId: json['userId']?.toString(),
|
||||
provider: json['provider']?.toString(),
|
||||
modelId: json['modelId']?.toString(),
|
||||
featureType: json['featureType']?.toString(),
|
||||
inputTokens: json['inputTokens'] is int ? json['inputTokens'] as int : int.tryParse('${json['inputTokens'] ?? ''}'),
|
||||
outputTokens: json['outputTokens'] is int ? json['outputTokens'] as int : int.tryParse('${json['outputTokens'] ?? ''}'),
|
||||
creditsDeducted: json['creditsDeducted'] is int ? json['creditsDeducted'] as int : int.tryParse('${json['creditsDeducted'] ?? ''}'),
|
||||
status: (json['status'] ?? '').toString(),
|
||||
errorMessage: json['errorMessage']?.toString(),
|
||||
reversalOfTraceId: json['reversalOfTraceId']?.toString(),
|
||||
operatorUserId: json['operatorUserId']?.toString(),
|
||||
auditNote: json['auditNote']?.toString(),
|
||||
createdAt: json['createdAt']?.toString(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
702
AINoval/lib/models/admin/llm_observability_models.dart
Normal file
702
AINoval/lib/models/admin/llm_observability_models.dart
Normal file
@@ -0,0 +1,702 @@
|
||||
/// LLM可观测性相关数据模型
|
||||
/// 用于管理后台查看和分析大模型调用日志
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import '../../utils/date_time_parser.dart';
|
||||
|
||||
part 'llm_observability_models.g.dart';
|
||||
|
||||
/// 自定义时间戳转换器
|
||||
class TimestampConverter implements JsonConverter<DateTime, dynamic> {
|
||||
const TimestampConverter();
|
||||
|
||||
@override
|
||||
DateTime fromJson(dynamic timestamp) {
|
||||
return parseBackendDateTime(timestamp);
|
||||
}
|
||||
|
||||
@override
|
||||
dynamic toJson(DateTime timestamp) {
|
||||
return timestamp.toIso8601String();
|
||||
}
|
||||
}
|
||||
|
||||
/// LLM调用日志
|
||||
@JsonSerializable()
|
||||
class LLMTrace extends Equatable {
|
||||
final String id;
|
||||
final String traceId;
|
||||
final String provider;
|
||||
final String model;
|
||||
final String? userId;
|
||||
final String? sessionId;
|
||||
@JsonKey(name: 'createdAt')
|
||||
@TimestampConverter()
|
||||
final DateTime timestamp;
|
||||
|
||||
// 请求信息
|
||||
final LLMRequest request;
|
||||
|
||||
// 响应信息
|
||||
final LLMResponse? response;
|
||||
|
||||
// 性能指标
|
||||
final LLMPerformanceMetrics? performance;
|
||||
|
||||
// 错误信息
|
||||
final LLMError? error;
|
||||
|
||||
// 工具调用
|
||||
final List<LLMToolCall>? toolCalls;
|
||||
|
||||
// 元数据
|
||||
final Map<String, dynamic>? metadata;
|
||||
|
||||
// 状态
|
||||
@JsonKey(defaultValue: LLMTraceStatus.pending)
|
||||
final LLMTraceStatus status;
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool isStreaming;
|
||||
|
||||
const LLMTrace({
|
||||
required this.id,
|
||||
required this.traceId,
|
||||
required this.provider,
|
||||
required this.model,
|
||||
this.userId,
|
||||
this.sessionId,
|
||||
required this.timestamp,
|
||||
required this.request,
|
||||
this.response,
|
||||
this.performance,
|
||||
this.error,
|
||||
this.toolCalls,
|
||||
this.metadata,
|
||||
this.status = LLMTraceStatus.pending,
|
||||
this.isStreaming = false,
|
||||
});
|
||||
|
||||
factory LLMTrace.fromJson(Map<String, dynamic> json) => _$LLMTraceFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$LLMTraceToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id, traceId, provider, model, userId, sessionId, timestamp, request, response, performance, error, toolCalls, metadata, status, isStreaming];
|
||||
}
|
||||
|
||||
/// LLM请求信息
|
||||
@JsonSerializable()
|
||||
class LLMRequest extends Equatable {
|
||||
final List<LLMMessage>? messages;
|
||||
|
||||
// 模型参数
|
||||
final double? temperature;
|
||||
final double? topP;
|
||||
final int? topK;
|
||||
final int? maxTokens;
|
||||
final int? seed;
|
||||
|
||||
// 工具调用
|
||||
final List<LLMTool>? tools;
|
||||
final String? toolChoice;
|
||||
|
||||
// 格式设置
|
||||
final String? responseFormat;
|
||||
|
||||
// 其他参数
|
||||
final Map<String, dynamic>? additionalParameters;
|
||||
|
||||
const LLMRequest({
|
||||
this.messages,
|
||||
this.temperature,
|
||||
this.topP,
|
||||
this.topK,
|
||||
this.maxTokens,
|
||||
this.seed,
|
||||
this.tools,
|
||||
this.toolChoice,
|
||||
this.responseFormat,
|
||||
this.additionalParameters,
|
||||
});
|
||||
|
||||
factory LLMRequest.fromJson(Map<String, dynamic> json) => _$LLMRequestFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$LLMRequestToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [messages, temperature, topP, topK, maxTokens, seed, tools, toolChoice, responseFormat, additionalParameters];
|
||||
}
|
||||
|
||||
/// LLM响应信息
|
||||
@JsonSerializable()
|
||||
class LLMResponse extends Equatable {
|
||||
final String? id;
|
||||
final String? content;
|
||||
|
||||
// Token使用情况
|
||||
final LLMTokenUsage? tokenUsage;
|
||||
|
||||
// 完成原因
|
||||
final String? finishReason;
|
||||
|
||||
// 工具调用结果
|
||||
final List<LLMToolCallResult>? toolCallResults;
|
||||
|
||||
// 元数据
|
||||
final Map<String, dynamic>? metadata;
|
||||
|
||||
// 流式数据
|
||||
final List<String>? streamChunks;
|
||||
|
||||
const LLMResponse({
|
||||
this.id,
|
||||
this.content,
|
||||
this.tokenUsage,
|
||||
this.finishReason,
|
||||
this.toolCallResults,
|
||||
this.metadata,
|
||||
this.streamChunks,
|
||||
});
|
||||
|
||||
factory LLMResponse.fromJson(Map<String, dynamic> json) => _$LLMResponseFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$LLMResponseToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id, content, tokenUsage, finishReason, toolCallResults, metadata, streamChunks];
|
||||
}
|
||||
|
||||
/// LLM消息
|
||||
@JsonSerializable()
|
||||
class LLMMessage extends Equatable {
|
||||
final String role;
|
||||
final String? content;
|
||||
final String? name;
|
||||
final Map<String, dynamic>? metadata;
|
||||
|
||||
const LLMMessage({
|
||||
required this.role,
|
||||
this.content,
|
||||
this.name,
|
||||
this.metadata,
|
||||
});
|
||||
|
||||
factory LLMMessage.fromJson(Map<String, dynamic> json) => _$LLMMessageFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$LLMMessageToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [role, content, name, metadata];
|
||||
}
|
||||
|
||||
/// LLM工具定义
|
||||
@JsonSerializable()
|
||||
class LLMTool extends Equatable {
|
||||
final String name;
|
||||
final String? description;
|
||||
final Map<String, dynamic>? parameters;
|
||||
|
||||
const LLMTool({
|
||||
required this.name,
|
||||
this.description,
|
||||
this.parameters,
|
||||
});
|
||||
|
||||
factory LLMTool.fromJson(Map<String, dynamic> json) => _$LLMToolFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$LLMToolToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [name, description, parameters];
|
||||
}
|
||||
|
||||
/// LLM工具调用
|
||||
@JsonSerializable()
|
||||
class LLMToolCall extends Equatable {
|
||||
final String id;
|
||||
final String name;
|
||||
final Map<String, dynamic>? arguments;
|
||||
final DateTime? timestamp;
|
||||
|
||||
const LLMToolCall({
|
||||
required this.id,
|
||||
required this.name,
|
||||
this.arguments,
|
||||
this.timestamp,
|
||||
});
|
||||
|
||||
factory LLMToolCall.fromJson(Map<String, dynamic> json) => _$LLMToolCallFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$LLMToolCallToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id, name, arguments, timestamp];
|
||||
}
|
||||
|
||||
/// LLM工具调用结果
|
||||
@JsonSerializable()
|
||||
class LLMToolCallResult extends Equatable {
|
||||
final String toolCallId;
|
||||
final String? result;
|
||||
final LLMError? error;
|
||||
|
||||
const LLMToolCallResult({
|
||||
required this.toolCallId,
|
||||
this.result,
|
||||
this.error,
|
||||
});
|
||||
|
||||
factory LLMToolCallResult.fromJson(Map<String, dynamic> json) => _$LLMToolCallResultFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$LLMToolCallResultToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [toolCallId, result, error];
|
||||
}
|
||||
|
||||
/// Token使用情况
|
||||
@JsonSerializable()
|
||||
class LLMTokenUsage extends Equatable {
|
||||
final int? promptTokens;
|
||||
final int? completionTokens;
|
||||
final int? totalTokens;
|
||||
|
||||
// 详细分解
|
||||
final int? inputTokens;
|
||||
final int? outputTokens;
|
||||
final int? reasoningTokens;
|
||||
final int? cachedTokens;
|
||||
|
||||
const LLMTokenUsage({
|
||||
this.promptTokens,
|
||||
this.completionTokens,
|
||||
this.totalTokens,
|
||||
this.inputTokens,
|
||||
this.outputTokens,
|
||||
this.reasoningTokens,
|
||||
this.cachedTokens,
|
||||
});
|
||||
|
||||
factory LLMTokenUsage.fromJson(Map<String, dynamic> json) => _$LLMTokenUsageFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$LLMTokenUsageToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [promptTokens, completionTokens, totalTokens, inputTokens, outputTokens, reasoningTokens, cachedTokens];
|
||||
}
|
||||
|
||||
/// 性能指标
|
||||
@JsonSerializable()
|
||||
class LLMPerformanceMetrics extends Equatable {
|
||||
final int? requestLatencyMs;
|
||||
final int? firstTokenLatencyMs;
|
||||
final int? totalDurationMs;
|
||||
|
||||
// 吞吐量
|
||||
final double? tokensPerSecond;
|
||||
final double? charactersPerSecond;
|
||||
|
||||
// 队列时间
|
||||
final int? queueTimeMs;
|
||||
final int? processingTimeMs;
|
||||
|
||||
const LLMPerformanceMetrics({
|
||||
this.requestLatencyMs,
|
||||
this.firstTokenLatencyMs,
|
||||
this.totalDurationMs,
|
||||
this.tokensPerSecond,
|
||||
this.charactersPerSecond,
|
||||
this.queueTimeMs,
|
||||
this.processingTimeMs,
|
||||
});
|
||||
|
||||
factory LLMPerformanceMetrics.fromJson(Map<String, dynamic> json) => _$LLMPerformanceMetricsFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$LLMPerformanceMetricsToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [requestLatencyMs, firstTokenLatencyMs, totalDurationMs, tokensPerSecond, charactersPerSecond, queueTimeMs, processingTimeMs];
|
||||
}
|
||||
|
||||
/// 错误信息
|
||||
@JsonSerializable()
|
||||
class LLMError extends Equatable {
|
||||
final String? type;
|
||||
final String? message;
|
||||
final String? code;
|
||||
final String? stackTrace;
|
||||
final Map<String, dynamic>? details;
|
||||
|
||||
const LLMError({
|
||||
this.type,
|
||||
this.message,
|
||||
this.code,
|
||||
this.stackTrace,
|
||||
this.details,
|
||||
});
|
||||
|
||||
factory LLMError.fromJson(Map<String, dynamic> json) => _$LLMErrorFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$LLMErrorToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [type, message, code, stackTrace, details];
|
||||
}
|
||||
|
||||
/// LLM调用状态
|
||||
enum LLMTraceStatus {
|
||||
@JsonValue('pending')
|
||||
pending,
|
||||
@JsonValue('success')
|
||||
success,
|
||||
@JsonValue('error')
|
||||
error,
|
||||
@JsonValue('timeout')
|
||||
timeout,
|
||||
@JsonValue('cancelled')
|
||||
cancelled,
|
||||
}
|
||||
|
||||
/// 统计信息基类
|
||||
@JsonSerializable()
|
||||
class LLMStatistics extends Equatable {
|
||||
final int totalCalls;
|
||||
final int successfulCalls;
|
||||
final int failedCalls;
|
||||
final double successRate;
|
||||
final double averageLatency;
|
||||
final int totalTokens;
|
||||
|
||||
// 时间范围
|
||||
final DateTime? startTime;
|
||||
final DateTime? endTime;
|
||||
|
||||
// 详细统计
|
||||
final Map<String, dynamic>? details;
|
||||
|
||||
const LLMStatistics({
|
||||
required this.totalCalls,
|
||||
required this.successfulCalls,
|
||||
required this.failedCalls,
|
||||
required this.successRate,
|
||||
required this.averageLatency,
|
||||
required this.totalTokens,
|
||||
this.startTime,
|
||||
this.endTime,
|
||||
this.details,
|
||||
});
|
||||
|
||||
factory LLMStatistics.fromJson(Map<String, dynamic> json) => _$LLMStatisticsFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$LLMStatisticsToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [totalCalls, successfulCalls, failedCalls, successRate, averageLatency, totalTokens, startTime, endTime, details];
|
||||
}
|
||||
|
||||
/// 提供商统计
|
||||
@JsonSerializable()
|
||||
class ProviderStatistics extends Equatable {
|
||||
final String provider;
|
||||
final LLMStatistics statistics;
|
||||
final List<ModelStatistics> models;
|
||||
|
||||
const ProviderStatistics({
|
||||
required this.provider,
|
||||
required this.statistics,
|
||||
required this.models,
|
||||
});
|
||||
|
||||
factory ProviderStatistics.fromJson(Map<String, dynamic> json) => _$ProviderStatisticsFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$ProviderStatisticsToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [provider, statistics, models];
|
||||
}
|
||||
|
||||
/// 模型统计
|
||||
@JsonSerializable()
|
||||
class ModelStatistics extends Equatable {
|
||||
final String modelName;
|
||||
final String provider;
|
||||
final LLMStatistics statistics;
|
||||
|
||||
const ModelStatistics({
|
||||
required this.modelName,
|
||||
required this.provider,
|
||||
required this.statistics,
|
||||
});
|
||||
|
||||
factory ModelStatistics.fromJson(Map<String, dynamic> json) => _$ModelStatisticsFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$ModelStatisticsToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [modelName, provider, statistics];
|
||||
}
|
||||
|
||||
/// 用户统计
|
||||
@JsonSerializable()
|
||||
class UserStatistics extends Equatable {
|
||||
final String userId;
|
||||
final String? username;
|
||||
final LLMStatistics statistics;
|
||||
final List<String> topModels;
|
||||
final List<String> topProviders;
|
||||
|
||||
const UserStatistics({
|
||||
required this.userId,
|
||||
this.username,
|
||||
required this.statistics,
|
||||
required this.topModels,
|
||||
required this.topProviders,
|
||||
});
|
||||
|
||||
factory UserStatistics.fromJson(Map<String, dynamic> json) => _$UserStatisticsFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$UserStatisticsToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [userId, username, statistics, topModels, topProviders];
|
||||
}
|
||||
|
||||
/// 错误统计
|
||||
@JsonSerializable()
|
||||
class ErrorStatistics extends Equatable {
|
||||
final String errorType;
|
||||
final int count;
|
||||
final double percentage;
|
||||
final List<String> topErrorMessages;
|
||||
final List<String> affectedModels;
|
||||
|
||||
const ErrorStatistics({
|
||||
required this.errorType,
|
||||
required this.count,
|
||||
required this.percentage,
|
||||
required this.topErrorMessages,
|
||||
required this.affectedModels,
|
||||
});
|
||||
|
||||
factory ErrorStatistics.fromJson(Map<String, dynamic> json) => _$ErrorStatisticsFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$ErrorStatisticsToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [errorType, count, percentage, topErrorMessages, affectedModels];
|
||||
}
|
||||
|
||||
/// 性能统计
|
||||
@JsonSerializable()
|
||||
class PerformanceStatistics extends Equatable {
|
||||
final double averageLatency;
|
||||
final double medianLatency;
|
||||
final double p95Latency;
|
||||
final double p99Latency;
|
||||
final double averageThroughput;
|
||||
|
||||
// 按时间分组的统计
|
||||
final List<TimeBasedMetric> latencyTrends;
|
||||
final List<TimeBasedMetric> throughputTrends;
|
||||
|
||||
const PerformanceStatistics({
|
||||
required this.averageLatency,
|
||||
required this.medianLatency,
|
||||
required this.p95Latency,
|
||||
required this.p99Latency,
|
||||
required this.averageThroughput,
|
||||
required this.latencyTrends,
|
||||
required this.throughputTrends,
|
||||
});
|
||||
|
||||
factory PerformanceStatistics.fromJson(Map<String, dynamic> json) => _$PerformanceStatisticsFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$PerformanceStatisticsToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [averageLatency, medianLatency, p95Latency, p99Latency, averageThroughput, latencyTrends, throughputTrends];
|
||||
}
|
||||
|
||||
/// 基于时间的指标
|
||||
@JsonSerializable()
|
||||
class TimeBasedMetric extends Equatable {
|
||||
final DateTime timestamp;
|
||||
final double value;
|
||||
final String? label;
|
||||
|
||||
const TimeBasedMetric({
|
||||
required this.timestamp,
|
||||
required this.value,
|
||||
this.label,
|
||||
});
|
||||
|
||||
factory TimeBasedMetric.fromJson(Map<String, dynamic> json) => _$TimeBasedMetricFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$TimeBasedMetricToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [timestamp, value, label];
|
||||
}
|
||||
|
||||
/// 系统健康状态
|
||||
@JsonSerializable()
|
||||
class SystemHealthStatus extends Equatable {
|
||||
@JsonKey(defaultValue: HealthStatus.healthy)
|
||||
final HealthStatus status;
|
||||
final Map<String, ComponentHealth> components;
|
||||
final String? message;
|
||||
final DateTime? lastChecked;
|
||||
|
||||
const SystemHealthStatus({
|
||||
this.status = HealthStatus.healthy,
|
||||
required this.components,
|
||||
this.message,
|
||||
this.lastChecked,
|
||||
});
|
||||
|
||||
factory SystemHealthStatus.fromJson(Map<String, dynamic> json) => _$SystemHealthStatusFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$SystemHealthStatusToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [status, components, message, lastChecked];
|
||||
}
|
||||
|
||||
/// 组件健康状态
|
||||
@JsonSerializable()
|
||||
class ComponentHealth extends Equatable {
|
||||
@JsonKey(defaultValue: HealthStatus.healthy)
|
||||
final HealthStatus status;
|
||||
final String? message;
|
||||
final Map<String, dynamic>? metrics;
|
||||
|
||||
const ComponentHealth({
|
||||
this.status = HealthStatus.healthy,
|
||||
this.message,
|
||||
this.metrics,
|
||||
});
|
||||
|
||||
factory ComponentHealth.fromJson(Map<String, dynamic> json) => _$ComponentHealthFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$ComponentHealthToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [status, message, metrics];
|
||||
}
|
||||
|
||||
/// 健康状态枚举
|
||||
enum HealthStatus {
|
||||
@JsonValue('healthy')
|
||||
healthy,
|
||||
@JsonValue('degraded')
|
||||
degraded,
|
||||
@JsonValue('unhealthy')
|
||||
unhealthy,
|
||||
@JsonValue('unknown')
|
||||
unknown,
|
||||
}
|
||||
|
||||
/// LLM日志搜索条件
|
||||
@JsonSerializable()
|
||||
class LLMTraceSearchCriteria extends Equatable {
|
||||
final String? userId;
|
||||
final String? provider;
|
||||
final String? model;
|
||||
final String? sessionId;
|
||||
final bool? hasError;
|
||||
final LLMTraceStatus? status;
|
||||
final DateTime? startTime;
|
||||
final DateTime? endTime;
|
||||
|
||||
// 分页
|
||||
@JsonKey(defaultValue: 0)
|
||||
final int page;
|
||||
@JsonKey(defaultValue: 20)
|
||||
final int size;
|
||||
@JsonKey(defaultValue: 'timestamp')
|
||||
final String sortBy;
|
||||
@JsonKey(defaultValue: 'desc')
|
||||
final String sortDir;
|
||||
|
||||
const LLMTraceSearchCriteria({
|
||||
this.userId,
|
||||
this.provider,
|
||||
this.model,
|
||||
this.sessionId,
|
||||
this.hasError,
|
||||
this.status,
|
||||
this.startTime,
|
||||
this.endTime,
|
||||
this.page = 0,
|
||||
this.size = 20,
|
||||
this.sortBy = 'timestamp',
|
||||
this.sortDir = 'desc',
|
||||
});
|
||||
|
||||
factory LLMTraceSearchCriteria.fromJson(Map<String, dynamic> json) => _$LLMTraceSearchCriteriaFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$LLMTraceSearchCriteriaToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [userId, provider, model, sessionId, hasError, status, startTime, endTime, page, size, sortBy, sortDir];
|
||||
}
|
||||
|
||||
/// API响应包装类
|
||||
@JsonSerializable(genericArgumentFactories: true)
|
||||
class ApiResponse<T> extends Equatable {
|
||||
final bool success;
|
||||
final String? message;
|
||||
final T? data;
|
||||
final String? error;
|
||||
|
||||
const ApiResponse({
|
||||
required this.success,
|
||||
this.message,
|
||||
this.data,
|
||||
this.error,
|
||||
});
|
||||
|
||||
factory ApiResponse.fromJson(Map<String, dynamic> json, T Function(Object? json) fromJsonT) =>
|
||||
_$ApiResponseFromJson(json, fromJsonT);
|
||||
Map<String, dynamic> toJson(Object? Function(T value) toJsonT) =>
|
||||
_$ApiResponseToJson(this, toJsonT);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [success, message, data, error];
|
||||
}
|
||||
|
||||
/// 分页响应
|
||||
@JsonSerializable(genericArgumentFactories: true)
|
||||
class PagedResponse<T> extends Equatable {
|
||||
final List<T> content;
|
||||
final int page;
|
||||
final int size;
|
||||
final int totalElements;
|
||||
final int totalPages;
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool first;
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool last;
|
||||
|
||||
const PagedResponse({
|
||||
required this.content,
|
||||
required this.page,
|
||||
required this.size,
|
||||
required this.totalElements,
|
||||
required this.totalPages,
|
||||
this.first = false,
|
||||
this.last = false,
|
||||
});
|
||||
|
||||
factory PagedResponse.fromJson(Map<String, dynamic> json, T Function(Object? json) fromJsonT) =>
|
||||
_$PagedResponseFromJson(json, fromJsonT);
|
||||
Map<String, dynamic> toJson(Object? Function(T value) toJsonT) =>
|
||||
_$PagedResponseToJson(this, toJsonT);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [content, page, size, totalElements, totalPages, first, last];
|
||||
}
|
||||
|
||||
/// 游标分页响应
|
||||
@JsonSerializable(genericArgumentFactories: true)
|
||||
class CursorPageResponse<T> extends Equatable {
|
||||
final List<T> items;
|
||||
final String? nextCursor;
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool hasMore;
|
||||
|
||||
const CursorPageResponse({
|
||||
required this.items,
|
||||
this.nextCursor,
|
||||
this.hasMore = false,
|
||||
});
|
||||
|
||||
factory CursorPageResponse.fromJson(Map<String, dynamic> json, T Function(Object? json) fromJsonT) =>
|
||||
_$CursorPageResponseFromJson(json, fromJsonT);
|
||||
Map<String, dynamic> toJson(Object? Function(T value) toJsonT) =>
|
||||
_$CursorPageResponseToJson(this, toJsonT);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [items, nextCursor, hasMore];
|
||||
}
|
||||
951
AINoval/lib/models/admin/llm_observability_models.g.dart
Normal file
951
AINoval/lib/models/admin/llm_observability_models.g.dart
Normal file
@@ -0,0 +1,951 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'llm_observability_models.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
LLMTrace _$LLMTraceFromJson(Map<String, dynamic> json) => $checkedCreate(
|
||||
'LLMTrace',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = LLMTrace(
|
||||
id: $checkedConvert('id', (v) => v as String),
|
||||
traceId: $checkedConvert('traceId', (v) => v as String),
|
||||
provider: $checkedConvert('provider', (v) => v as String),
|
||||
model: $checkedConvert('model', (v) => v as String),
|
||||
userId: $checkedConvert('userId', (v) => v as String?),
|
||||
sessionId: $checkedConvert('sessionId', (v) => v as String?),
|
||||
timestamp: $checkedConvert(
|
||||
'createdAt', (v) => const TimestampConverter().fromJson(v)),
|
||||
request: $checkedConvert(
|
||||
'request', (v) => LLMRequest.fromJson(v as Map<String, dynamic>)),
|
||||
response: $checkedConvert(
|
||||
'response',
|
||||
(v) => v == null
|
||||
? null
|
||||
: LLMResponse.fromJson(v as Map<String, dynamic>)),
|
||||
performance: $checkedConvert(
|
||||
'performance',
|
||||
(v) => v == null
|
||||
? null
|
||||
: LLMPerformanceMetrics.fromJson(v as Map<String, dynamic>)),
|
||||
error: $checkedConvert(
|
||||
'error',
|
||||
(v) => v == null
|
||||
? null
|
||||
: LLMError.fromJson(v as Map<String, dynamic>)),
|
||||
toolCalls: $checkedConvert(
|
||||
'toolCalls',
|
||||
(v) => (v as List<dynamic>?)
|
||||
?.map((e) => LLMToolCall.fromJson(e as Map<String, dynamic>))
|
||||
.toList()),
|
||||
metadata:
|
||||
$checkedConvert('metadata', (v) => v as Map<String, dynamic>?),
|
||||
status: $checkedConvert(
|
||||
'status',
|
||||
(v) =>
|
||||
$enumDecodeNullable(_$LLMTraceStatusEnumMap, v) ??
|
||||
LLMTraceStatus.pending),
|
||||
isStreaming:
|
||||
$checkedConvert('isStreaming', (v) => v as bool? ?? false),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
fieldKeyMap: const {'timestamp': 'createdAt'},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$LLMTraceToJson(LLMTrace instance) {
|
||||
final val = <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'traceId': instance.traceId,
|
||||
'provider': instance.provider,
|
||||
'model': instance.model,
|
||||
};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('userId', instance.userId);
|
||||
writeNotNull('sessionId', instance.sessionId);
|
||||
writeNotNull(
|
||||
'createdAt', const TimestampConverter().toJson(instance.timestamp));
|
||||
val['request'] = instance.request.toJson();
|
||||
writeNotNull('response', instance.response?.toJson());
|
||||
writeNotNull('performance', instance.performance?.toJson());
|
||||
writeNotNull('error', instance.error?.toJson());
|
||||
writeNotNull(
|
||||
'toolCalls', instance.toolCalls?.map((e) => e.toJson()).toList());
|
||||
writeNotNull('metadata', instance.metadata);
|
||||
val['status'] = _$LLMTraceStatusEnumMap[instance.status]!;
|
||||
val['isStreaming'] = instance.isStreaming;
|
||||
return val;
|
||||
}
|
||||
|
||||
const _$LLMTraceStatusEnumMap = {
|
||||
LLMTraceStatus.pending: 'pending',
|
||||
LLMTraceStatus.success: 'success',
|
||||
LLMTraceStatus.error: 'error',
|
||||
LLMTraceStatus.timeout: 'timeout',
|
||||
LLMTraceStatus.cancelled: 'cancelled',
|
||||
};
|
||||
|
||||
LLMRequest _$LLMRequestFromJson(Map<String, dynamic> json) => $checkedCreate(
|
||||
'LLMRequest',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = LLMRequest(
|
||||
messages: $checkedConvert(
|
||||
'messages',
|
||||
(v) => (v as List<dynamic>?)
|
||||
?.map((e) => LLMMessage.fromJson(e as Map<String, dynamic>))
|
||||
.toList()),
|
||||
temperature:
|
||||
$checkedConvert('temperature', (v) => (v as num?)?.toDouble()),
|
||||
topP: $checkedConvert('topP', (v) => (v as num?)?.toDouble()),
|
||||
topK: $checkedConvert('topK', (v) => (v as num?)?.toInt()),
|
||||
maxTokens: $checkedConvert('maxTokens', (v) => (v as num?)?.toInt()),
|
||||
seed: $checkedConvert('seed', (v) => (v as num?)?.toInt()),
|
||||
tools: $checkedConvert(
|
||||
'tools',
|
||||
(v) => (v as List<dynamic>?)
|
||||
?.map((e) => LLMTool.fromJson(e as Map<String, dynamic>))
|
||||
.toList()),
|
||||
toolChoice: $checkedConvert('toolChoice', (v) => v as String?),
|
||||
responseFormat:
|
||||
$checkedConvert('responseFormat', (v) => v as String?),
|
||||
additionalParameters: $checkedConvert(
|
||||
'additionalParameters', (v) => v as Map<String, dynamic>?),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$LLMRequestToJson(LLMRequest instance) {
|
||||
final val = <String, dynamic>{};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('messages', instance.messages?.map((e) => e.toJson()).toList());
|
||||
writeNotNull('temperature', instance.temperature);
|
||||
writeNotNull('topP', instance.topP);
|
||||
writeNotNull('topK', instance.topK);
|
||||
writeNotNull('maxTokens', instance.maxTokens);
|
||||
writeNotNull('seed', instance.seed);
|
||||
writeNotNull('tools', instance.tools?.map((e) => e.toJson()).toList());
|
||||
writeNotNull('toolChoice', instance.toolChoice);
|
||||
writeNotNull('responseFormat', instance.responseFormat);
|
||||
writeNotNull('additionalParameters', instance.additionalParameters);
|
||||
return val;
|
||||
}
|
||||
|
||||
LLMResponse _$LLMResponseFromJson(Map<String, dynamic> json) => $checkedCreate(
|
||||
'LLMResponse',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = LLMResponse(
|
||||
id: $checkedConvert('id', (v) => v as String?),
|
||||
content: $checkedConvert('content', (v) => v as String?),
|
||||
tokenUsage: $checkedConvert(
|
||||
'tokenUsage',
|
||||
(v) => v == null
|
||||
? null
|
||||
: LLMTokenUsage.fromJson(v as Map<String, dynamic>)),
|
||||
finishReason: $checkedConvert('finishReason', (v) => v as String?),
|
||||
toolCallResults: $checkedConvert(
|
||||
'toolCallResults',
|
||||
(v) => (v as List<dynamic>?)
|
||||
?.map((e) =>
|
||||
LLMToolCallResult.fromJson(e as Map<String, dynamic>))
|
||||
.toList()),
|
||||
metadata:
|
||||
$checkedConvert('metadata', (v) => v as Map<String, dynamic>?),
|
||||
streamChunks: $checkedConvert('streamChunks',
|
||||
(v) => (v as List<dynamic>?)?.map((e) => e as String).toList()),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$LLMResponseToJson(LLMResponse instance) {
|
||||
final val = <String, dynamic>{};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('id', instance.id);
|
||||
writeNotNull('content', instance.content);
|
||||
writeNotNull('tokenUsage', instance.tokenUsage?.toJson());
|
||||
writeNotNull('finishReason', instance.finishReason);
|
||||
writeNotNull('toolCallResults',
|
||||
instance.toolCallResults?.map((e) => e.toJson()).toList());
|
||||
writeNotNull('metadata', instance.metadata);
|
||||
writeNotNull('streamChunks', instance.streamChunks);
|
||||
return val;
|
||||
}
|
||||
|
||||
LLMMessage _$LLMMessageFromJson(Map<String, dynamic> json) => $checkedCreate(
|
||||
'LLMMessage',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = LLMMessage(
|
||||
role: $checkedConvert('role', (v) => v as String),
|
||||
content: $checkedConvert('content', (v) => v as String?),
|
||||
name: $checkedConvert('name', (v) => v as String?),
|
||||
metadata:
|
||||
$checkedConvert('metadata', (v) => v as Map<String, dynamic>?),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$LLMMessageToJson(LLMMessage instance) {
|
||||
final val = <String, dynamic>{
|
||||
'role': instance.role,
|
||||
};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('content', instance.content);
|
||||
writeNotNull('name', instance.name);
|
||||
writeNotNull('metadata', instance.metadata);
|
||||
return val;
|
||||
}
|
||||
|
||||
LLMTool _$LLMToolFromJson(Map<String, dynamic> json) => $checkedCreate(
|
||||
'LLMTool',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = LLMTool(
|
||||
name: $checkedConvert('name', (v) => v as String),
|
||||
description: $checkedConvert('description', (v) => v as String?),
|
||||
parameters:
|
||||
$checkedConvert('parameters', (v) => v as Map<String, dynamic>?),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$LLMToolToJson(LLMTool instance) {
|
||||
final val = <String, dynamic>{
|
||||
'name': instance.name,
|
||||
};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('description', instance.description);
|
||||
writeNotNull('parameters', instance.parameters);
|
||||
return val;
|
||||
}
|
||||
|
||||
LLMToolCall _$LLMToolCallFromJson(Map<String, dynamic> json) => $checkedCreate(
|
||||
'LLMToolCall',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = LLMToolCall(
|
||||
id: $checkedConvert('id', (v) => v as String),
|
||||
name: $checkedConvert('name', (v) => v as String),
|
||||
arguments:
|
||||
$checkedConvert('arguments', (v) => v as Map<String, dynamic>?),
|
||||
timestamp: $checkedConvert('timestamp',
|
||||
(v) => v == null ? null : DateTime.parse(v as String)),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$LLMToolCallToJson(LLMToolCall instance) {
|
||||
final val = <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'name': instance.name,
|
||||
};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('arguments', instance.arguments);
|
||||
writeNotNull('timestamp', instance.timestamp?.toIso8601String());
|
||||
return val;
|
||||
}
|
||||
|
||||
LLMToolCallResult _$LLMToolCallResultFromJson(Map<String, dynamic> json) =>
|
||||
$checkedCreate(
|
||||
'LLMToolCallResult',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = LLMToolCallResult(
|
||||
toolCallId: $checkedConvert('toolCallId', (v) => v as String),
|
||||
result: $checkedConvert('result', (v) => v as String?),
|
||||
error: $checkedConvert(
|
||||
'error',
|
||||
(v) => v == null
|
||||
? null
|
||||
: LLMError.fromJson(v as Map<String, dynamic>)),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$LLMToolCallResultToJson(LLMToolCallResult instance) {
|
||||
final val = <String, dynamic>{
|
||||
'toolCallId': instance.toolCallId,
|
||||
};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('result', instance.result);
|
||||
writeNotNull('error', instance.error?.toJson());
|
||||
return val;
|
||||
}
|
||||
|
||||
LLMTokenUsage _$LLMTokenUsageFromJson(Map<String, dynamic> json) =>
|
||||
$checkedCreate(
|
||||
'LLMTokenUsage',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = LLMTokenUsage(
|
||||
promptTokens:
|
||||
$checkedConvert('promptTokens', (v) => (v as num?)?.toInt()),
|
||||
completionTokens:
|
||||
$checkedConvert('completionTokens', (v) => (v as num?)?.toInt()),
|
||||
totalTokens:
|
||||
$checkedConvert('totalTokens', (v) => (v as num?)?.toInt()),
|
||||
inputTokens:
|
||||
$checkedConvert('inputTokens', (v) => (v as num?)?.toInt()),
|
||||
outputTokens:
|
||||
$checkedConvert('outputTokens', (v) => (v as num?)?.toInt()),
|
||||
reasoningTokens:
|
||||
$checkedConvert('reasoningTokens', (v) => (v as num?)?.toInt()),
|
||||
cachedTokens:
|
||||
$checkedConvert('cachedTokens', (v) => (v as num?)?.toInt()),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$LLMTokenUsageToJson(LLMTokenUsage instance) {
|
||||
final val = <String, dynamic>{};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('promptTokens', instance.promptTokens);
|
||||
writeNotNull('completionTokens', instance.completionTokens);
|
||||
writeNotNull('totalTokens', instance.totalTokens);
|
||||
writeNotNull('inputTokens', instance.inputTokens);
|
||||
writeNotNull('outputTokens', instance.outputTokens);
|
||||
writeNotNull('reasoningTokens', instance.reasoningTokens);
|
||||
writeNotNull('cachedTokens', instance.cachedTokens);
|
||||
return val;
|
||||
}
|
||||
|
||||
LLMPerformanceMetrics _$LLMPerformanceMetricsFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
$checkedCreate(
|
||||
'LLMPerformanceMetrics',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = LLMPerformanceMetrics(
|
||||
requestLatencyMs:
|
||||
$checkedConvert('requestLatencyMs', (v) => (v as num?)?.toInt()),
|
||||
firstTokenLatencyMs: $checkedConvert(
|
||||
'firstTokenLatencyMs', (v) => (v as num?)?.toInt()),
|
||||
totalDurationMs:
|
||||
$checkedConvert('totalDurationMs', (v) => (v as num?)?.toInt()),
|
||||
tokensPerSecond: $checkedConvert(
|
||||
'tokensPerSecond', (v) => (v as num?)?.toDouble()),
|
||||
charactersPerSecond: $checkedConvert(
|
||||
'charactersPerSecond', (v) => (v as num?)?.toDouble()),
|
||||
queueTimeMs:
|
||||
$checkedConvert('queueTimeMs', (v) => (v as num?)?.toInt()),
|
||||
processingTimeMs:
|
||||
$checkedConvert('processingTimeMs', (v) => (v as num?)?.toInt()),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$LLMPerformanceMetricsToJson(
|
||||
LLMPerformanceMetrics instance) {
|
||||
final val = <String, dynamic>{};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('requestLatencyMs', instance.requestLatencyMs);
|
||||
writeNotNull('firstTokenLatencyMs', instance.firstTokenLatencyMs);
|
||||
writeNotNull('totalDurationMs', instance.totalDurationMs);
|
||||
writeNotNull('tokensPerSecond', instance.tokensPerSecond);
|
||||
writeNotNull('charactersPerSecond', instance.charactersPerSecond);
|
||||
writeNotNull('queueTimeMs', instance.queueTimeMs);
|
||||
writeNotNull('processingTimeMs', instance.processingTimeMs);
|
||||
return val;
|
||||
}
|
||||
|
||||
LLMError _$LLMErrorFromJson(Map<String, dynamic> json) => $checkedCreate(
|
||||
'LLMError',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = LLMError(
|
||||
type: $checkedConvert('type', (v) => v as String?),
|
||||
message: $checkedConvert('message', (v) => v as String?),
|
||||
code: $checkedConvert('code', (v) => v as String?),
|
||||
stackTrace: $checkedConvert('stackTrace', (v) => v as String?),
|
||||
details:
|
||||
$checkedConvert('details', (v) => v as Map<String, dynamic>?),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$LLMErrorToJson(LLMError instance) {
|
||||
final val = <String, dynamic>{};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('type', instance.type);
|
||||
writeNotNull('message', instance.message);
|
||||
writeNotNull('code', instance.code);
|
||||
writeNotNull('stackTrace', instance.stackTrace);
|
||||
writeNotNull('details', instance.details);
|
||||
return val;
|
||||
}
|
||||
|
||||
LLMStatistics _$LLMStatisticsFromJson(Map<String, dynamic> json) =>
|
||||
$checkedCreate(
|
||||
'LLMStatistics',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = LLMStatistics(
|
||||
totalCalls: $checkedConvert('totalCalls', (v) => (v as num).toInt()),
|
||||
successfulCalls:
|
||||
$checkedConvert('successfulCalls', (v) => (v as num).toInt()),
|
||||
failedCalls:
|
||||
$checkedConvert('failedCalls', (v) => (v as num).toInt()),
|
||||
successRate:
|
||||
$checkedConvert('successRate', (v) => (v as num).toDouble()),
|
||||
averageLatency:
|
||||
$checkedConvert('averageLatency', (v) => (v as num).toDouble()),
|
||||
totalTokens:
|
||||
$checkedConvert('totalTokens', (v) => (v as num).toInt()),
|
||||
startTime: $checkedConvert('startTime',
|
||||
(v) => v == null ? null : DateTime.parse(v as String)),
|
||||
endTime: $checkedConvert(
|
||||
'endTime', (v) => v == null ? null : DateTime.parse(v as String)),
|
||||
details:
|
||||
$checkedConvert('details', (v) => v as Map<String, dynamic>?),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$LLMStatisticsToJson(LLMStatistics instance) {
|
||||
final val = <String, dynamic>{
|
||||
'totalCalls': instance.totalCalls,
|
||||
'successfulCalls': instance.successfulCalls,
|
||||
'failedCalls': instance.failedCalls,
|
||||
'successRate': instance.successRate,
|
||||
'averageLatency': instance.averageLatency,
|
||||
'totalTokens': instance.totalTokens,
|
||||
};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('startTime', instance.startTime?.toIso8601String());
|
||||
writeNotNull('endTime', instance.endTime?.toIso8601String());
|
||||
writeNotNull('details', instance.details);
|
||||
return val;
|
||||
}
|
||||
|
||||
ProviderStatistics _$ProviderStatisticsFromJson(Map<String, dynamic> json) =>
|
||||
$checkedCreate(
|
||||
'ProviderStatistics',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = ProviderStatistics(
|
||||
provider: $checkedConvert('provider', (v) => v as String),
|
||||
statistics: $checkedConvert('statistics',
|
||||
(v) => LLMStatistics.fromJson(v as Map<String, dynamic>)),
|
||||
models: $checkedConvert(
|
||||
'models',
|
||||
(v) => (v as List<dynamic>)
|
||||
.map((e) =>
|
||||
ModelStatistics.fromJson(e as Map<String, dynamic>))
|
||||
.toList()),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$ProviderStatisticsToJson(ProviderStatistics instance) =>
|
||||
<String, dynamic>{
|
||||
'provider': instance.provider,
|
||||
'statistics': instance.statistics.toJson(),
|
||||
'models': instance.models.map((e) => e.toJson()).toList(),
|
||||
};
|
||||
|
||||
ModelStatistics _$ModelStatisticsFromJson(Map<String, dynamic> json) =>
|
||||
$checkedCreate(
|
||||
'ModelStatistics',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = ModelStatistics(
|
||||
modelName: $checkedConvert('modelName', (v) => v as String),
|
||||
provider: $checkedConvert('provider', (v) => v as String),
|
||||
statistics: $checkedConvert('statistics',
|
||||
(v) => LLMStatistics.fromJson(v as Map<String, dynamic>)),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$ModelStatisticsToJson(ModelStatistics instance) =>
|
||||
<String, dynamic>{
|
||||
'modelName': instance.modelName,
|
||||
'provider': instance.provider,
|
||||
'statistics': instance.statistics.toJson(),
|
||||
};
|
||||
|
||||
UserStatistics _$UserStatisticsFromJson(Map<String, dynamic> json) =>
|
||||
$checkedCreate(
|
||||
'UserStatistics',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = UserStatistics(
|
||||
userId: $checkedConvert('userId', (v) => v as String),
|
||||
username: $checkedConvert('username', (v) => v as String?),
|
||||
statistics: $checkedConvert('statistics',
|
||||
(v) => LLMStatistics.fromJson(v as Map<String, dynamic>)),
|
||||
topModels: $checkedConvert('topModels',
|
||||
(v) => (v as List<dynamic>).map((e) => e as String).toList()),
|
||||
topProviders: $checkedConvert('topProviders',
|
||||
(v) => (v as List<dynamic>).map((e) => e as String).toList()),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$UserStatisticsToJson(UserStatistics instance) {
|
||||
final val = <String, dynamic>{
|
||||
'userId': instance.userId,
|
||||
};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('username', instance.username);
|
||||
val['statistics'] = instance.statistics.toJson();
|
||||
val['topModels'] = instance.topModels;
|
||||
val['topProviders'] = instance.topProviders;
|
||||
return val;
|
||||
}
|
||||
|
||||
ErrorStatistics _$ErrorStatisticsFromJson(Map<String, dynamic> json) =>
|
||||
$checkedCreate(
|
||||
'ErrorStatistics',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = ErrorStatistics(
|
||||
errorType: $checkedConvert('errorType', (v) => v as String),
|
||||
count: $checkedConvert('count', (v) => (v as num).toInt()),
|
||||
percentage:
|
||||
$checkedConvert('percentage', (v) => (v as num).toDouble()),
|
||||
topErrorMessages: $checkedConvert('topErrorMessages',
|
||||
(v) => (v as List<dynamic>).map((e) => e as String).toList()),
|
||||
affectedModels: $checkedConvert('affectedModels',
|
||||
(v) => (v as List<dynamic>).map((e) => e as String).toList()),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$ErrorStatisticsToJson(ErrorStatistics instance) =>
|
||||
<String, dynamic>{
|
||||
'errorType': instance.errorType,
|
||||
'count': instance.count,
|
||||
'percentage': instance.percentage,
|
||||
'topErrorMessages': instance.topErrorMessages,
|
||||
'affectedModels': instance.affectedModels,
|
||||
};
|
||||
|
||||
PerformanceStatistics _$PerformanceStatisticsFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
$checkedCreate(
|
||||
'PerformanceStatistics',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = PerformanceStatistics(
|
||||
averageLatency:
|
||||
$checkedConvert('averageLatency', (v) => (v as num).toDouble()),
|
||||
medianLatency:
|
||||
$checkedConvert('medianLatency', (v) => (v as num).toDouble()),
|
||||
p95Latency:
|
||||
$checkedConvert('p95Latency', (v) => (v as num).toDouble()),
|
||||
p99Latency:
|
||||
$checkedConvert('p99Latency', (v) => (v as num).toDouble()),
|
||||
averageThroughput: $checkedConvert(
|
||||
'averageThroughput', (v) => (v as num).toDouble()),
|
||||
latencyTrends: $checkedConvert(
|
||||
'latencyTrends',
|
||||
(v) => (v as List<dynamic>)
|
||||
.map((e) =>
|
||||
TimeBasedMetric.fromJson(e as Map<String, dynamic>))
|
||||
.toList()),
|
||||
throughputTrends: $checkedConvert(
|
||||
'throughputTrends',
|
||||
(v) => (v as List<dynamic>)
|
||||
.map((e) =>
|
||||
TimeBasedMetric.fromJson(e as Map<String, dynamic>))
|
||||
.toList()),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$PerformanceStatisticsToJson(
|
||||
PerformanceStatistics instance) =>
|
||||
<String, dynamic>{
|
||||
'averageLatency': instance.averageLatency,
|
||||
'medianLatency': instance.medianLatency,
|
||||
'p95Latency': instance.p95Latency,
|
||||
'p99Latency': instance.p99Latency,
|
||||
'averageThroughput': instance.averageThroughput,
|
||||
'latencyTrends': instance.latencyTrends.map((e) => e.toJson()).toList(),
|
||||
'throughputTrends':
|
||||
instance.throughputTrends.map((e) => e.toJson()).toList(),
|
||||
};
|
||||
|
||||
TimeBasedMetric _$TimeBasedMetricFromJson(Map<String, dynamic> json) =>
|
||||
$checkedCreate(
|
||||
'TimeBasedMetric',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = TimeBasedMetric(
|
||||
timestamp:
|
||||
$checkedConvert('timestamp', (v) => DateTime.parse(v as String)),
|
||||
value: $checkedConvert('value', (v) => (v as num).toDouble()),
|
||||
label: $checkedConvert('label', (v) => v as String?),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$TimeBasedMetricToJson(TimeBasedMetric instance) {
|
||||
final val = <String, dynamic>{
|
||||
'timestamp': instance.timestamp.toIso8601String(),
|
||||
'value': instance.value,
|
||||
};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('label', instance.label);
|
||||
return val;
|
||||
}
|
||||
|
||||
SystemHealthStatus _$SystemHealthStatusFromJson(Map<String, dynamic> json) =>
|
||||
$checkedCreate(
|
||||
'SystemHealthStatus',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = SystemHealthStatus(
|
||||
status: $checkedConvert(
|
||||
'status',
|
||||
(v) =>
|
||||
$enumDecodeNullable(_$HealthStatusEnumMap, v) ??
|
||||
HealthStatus.healthy),
|
||||
components: $checkedConvert(
|
||||
'components',
|
||||
(v) => (v as Map<String, dynamic>).map(
|
||||
(k, e) => MapEntry(
|
||||
k, ComponentHealth.fromJson(e as Map<String, dynamic>)),
|
||||
)),
|
||||
message: $checkedConvert('message', (v) => v as String?),
|
||||
lastChecked: $checkedConvert('lastChecked',
|
||||
(v) => v == null ? null : DateTime.parse(v as String)),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SystemHealthStatusToJson(SystemHealthStatus instance) {
|
||||
final val = <String, dynamic>{
|
||||
'status': _$HealthStatusEnumMap[instance.status]!,
|
||||
'components': instance.components.map((k, e) => MapEntry(k, e.toJson())),
|
||||
};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('message', instance.message);
|
||||
writeNotNull('lastChecked', instance.lastChecked?.toIso8601String());
|
||||
return val;
|
||||
}
|
||||
|
||||
const _$HealthStatusEnumMap = {
|
||||
HealthStatus.healthy: 'healthy',
|
||||
HealthStatus.degraded: 'degraded',
|
||||
HealthStatus.unhealthy: 'unhealthy',
|
||||
HealthStatus.unknown: 'unknown',
|
||||
};
|
||||
|
||||
ComponentHealth _$ComponentHealthFromJson(Map<String, dynamic> json) =>
|
||||
$checkedCreate(
|
||||
'ComponentHealth',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = ComponentHealth(
|
||||
status: $checkedConvert(
|
||||
'status',
|
||||
(v) =>
|
||||
$enumDecodeNullable(_$HealthStatusEnumMap, v) ??
|
||||
HealthStatus.healthy),
|
||||
message: $checkedConvert('message', (v) => v as String?),
|
||||
metrics:
|
||||
$checkedConvert('metrics', (v) => v as Map<String, dynamic>?),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$ComponentHealthToJson(ComponentHealth instance) {
|
||||
final val = <String, dynamic>{
|
||||
'status': _$HealthStatusEnumMap[instance.status]!,
|
||||
};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('message', instance.message);
|
||||
writeNotNull('metrics', instance.metrics);
|
||||
return val;
|
||||
}
|
||||
|
||||
LLMTraceSearchCriteria _$LLMTraceSearchCriteriaFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
$checkedCreate(
|
||||
'LLMTraceSearchCriteria',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = LLMTraceSearchCriteria(
|
||||
userId: $checkedConvert('userId', (v) => v as String?),
|
||||
provider: $checkedConvert('provider', (v) => v as String?),
|
||||
model: $checkedConvert('model', (v) => v as String?),
|
||||
sessionId: $checkedConvert('sessionId', (v) => v as String?),
|
||||
hasError: $checkedConvert('hasError', (v) => v as bool?),
|
||||
status: $checkedConvert(
|
||||
'status', (v) => $enumDecodeNullable(_$LLMTraceStatusEnumMap, v)),
|
||||
startTime: $checkedConvert('startTime',
|
||||
(v) => v == null ? null : DateTime.parse(v as String)),
|
||||
endTime: $checkedConvert(
|
||||
'endTime', (v) => v == null ? null : DateTime.parse(v as String)),
|
||||
page: $checkedConvert('page', (v) => (v as num?)?.toInt() ?? 0),
|
||||
size: $checkedConvert('size', (v) => (v as num?)?.toInt() ?? 20),
|
||||
sortBy: $checkedConvert('sortBy', (v) => v as String? ?? 'timestamp'),
|
||||
sortDir: $checkedConvert('sortDir', (v) => v as String? ?? 'desc'),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$LLMTraceSearchCriteriaToJson(
|
||||
LLMTraceSearchCriteria instance) {
|
||||
final val = <String, dynamic>{};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('userId', instance.userId);
|
||||
writeNotNull('provider', instance.provider);
|
||||
writeNotNull('model', instance.model);
|
||||
writeNotNull('sessionId', instance.sessionId);
|
||||
writeNotNull('hasError', instance.hasError);
|
||||
writeNotNull('status', _$LLMTraceStatusEnumMap[instance.status]);
|
||||
writeNotNull('startTime', instance.startTime?.toIso8601String());
|
||||
writeNotNull('endTime', instance.endTime?.toIso8601String());
|
||||
val['page'] = instance.page;
|
||||
val['size'] = instance.size;
|
||||
val['sortBy'] = instance.sortBy;
|
||||
val['sortDir'] = instance.sortDir;
|
||||
return val;
|
||||
}
|
||||
|
||||
ApiResponse<T> _$ApiResponseFromJson<T>(
|
||||
Map<String, dynamic> json,
|
||||
T Function(Object? json) fromJsonT,
|
||||
) =>
|
||||
$checkedCreate(
|
||||
'ApiResponse',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = ApiResponse<T>(
|
||||
success: $checkedConvert('success', (v) => v as bool),
|
||||
message: $checkedConvert('message', (v) => v as String?),
|
||||
data: $checkedConvert(
|
||||
'data', (v) => _$nullableGenericFromJson(v, fromJsonT)),
|
||||
error: $checkedConvert('error', (v) => v as String?),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$ApiResponseToJson<T>(
|
||||
ApiResponse<T> instance,
|
||||
Object? Function(T value) toJsonT,
|
||||
) {
|
||||
final val = <String, dynamic>{
|
||||
'success': instance.success,
|
||||
};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('message', instance.message);
|
||||
writeNotNull('data', _$nullableGenericToJson(instance.data, toJsonT));
|
||||
writeNotNull('error', instance.error);
|
||||
return val;
|
||||
}
|
||||
|
||||
T? _$nullableGenericFromJson<T>(
|
||||
Object? input,
|
||||
T Function(Object? json) fromJson,
|
||||
) =>
|
||||
input == null ? null : fromJson(input);
|
||||
|
||||
Object? _$nullableGenericToJson<T>(
|
||||
T? input,
|
||||
Object? Function(T value) toJson,
|
||||
) =>
|
||||
input == null ? null : toJson(input);
|
||||
|
||||
PagedResponse<T> _$PagedResponseFromJson<T>(
|
||||
Map<String, dynamic> json,
|
||||
T Function(Object? json) fromJsonT,
|
||||
) =>
|
||||
$checkedCreate(
|
||||
'PagedResponse',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = PagedResponse<T>(
|
||||
content: $checkedConvert(
|
||||
'content', (v) => (v as List<dynamic>).map(fromJsonT).toList()),
|
||||
page: $checkedConvert('page', (v) => (v as num).toInt()),
|
||||
size: $checkedConvert('size', (v) => (v as num).toInt()),
|
||||
totalElements:
|
||||
$checkedConvert('totalElements', (v) => (v as num).toInt()),
|
||||
totalPages: $checkedConvert('totalPages', (v) => (v as num).toInt()),
|
||||
first: $checkedConvert('first', (v) => v as bool? ?? false),
|
||||
last: $checkedConvert('last', (v) => v as bool? ?? false),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$PagedResponseToJson<T>(
|
||||
PagedResponse<T> instance,
|
||||
Object? Function(T value) toJsonT,
|
||||
) =>
|
||||
<String, dynamic>{
|
||||
'content': instance.content.map(toJsonT).toList(),
|
||||
'page': instance.page,
|
||||
'size': instance.size,
|
||||
'totalElements': instance.totalElements,
|
||||
'totalPages': instance.totalPages,
|
||||
'first': instance.first,
|
||||
'last': instance.last,
|
||||
};
|
||||
|
||||
CursorPageResponse<T> _$CursorPageResponseFromJson<T>(
|
||||
Map<String, dynamic> json,
|
||||
T Function(Object? json) fromJsonT,
|
||||
) =>
|
||||
$checkedCreate(
|
||||
'CursorPageResponse',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = CursorPageResponse<T>(
|
||||
items: $checkedConvert(
|
||||
'items', (v) => (v as List<dynamic>).map(fromJsonT).toList()),
|
||||
nextCursor: $checkedConvert('nextCursor', (v) => v as String?),
|
||||
hasMore: $checkedConvert('hasMore', (v) => v as bool? ?? false),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$CursorPageResponseToJson<T>(
|
||||
CursorPageResponse<T> instance,
|
||||
Object? Function(T value) toJsonT,
|
||||
) {
|
||||
final val = <String, dynamic>{
|
||||
'items': instance.items.map(toJsonT).toList(),
|
||||
};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('nextCursor', instance.nextCursor);
|
||||
val['hasMore'] = instance.hasMore;
|
||||
return val;
|
||||
}
|
||||
429
AINoval/lib/models/admin/subscription_models.dart
Normal file
429
AINoval/lib/models/admin/subscription_models.dart
Normal file
@@ -0,0 +1,429 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import '../../utils/date_time_parser.dart';
|
||||
|
||||
part 'subscription_models.g.dart';
|
||||
|
||||
/// 订阅计划模型
|
||||
@JsonSerializable()
|
||||
class SubscriptionPlan extends Equatable {
|
||||
final String? id;
|
||||
final String planName;
|
||||
final String? description;
|
||||
final double price;
|
||||
final String currency;
|
||||
final BillingCycle billingCycle;
|
||||
final String? roleId;
|
||||
final int? creditsGranted;
|
||||
final bool active;
|
||||
final bool recommended;
|
||||
final int priority;
|
||||
final Map<String, dynamic>? features;
|
||||
final int trialDays;
|
||||
final int maxUsers;
|
||||
final DateTime? createdAt;
|
||||
final DateTime? updatedAt;
|
||||
|
||||
const SubscriptionPlan({
|
||||
this.id,
|
||||
required this.planName,
|
||||
this.description,
|
||||
required this.price,
|
||||
required this.currency,
|
||||
required this.billingCycle,
|
||||
this.roleId,
|
||||
this.creditsGranted,
|
||||
this.active = true,
|
||||
this.recommended = false,
|
||||
this.priority = 0,
|
||||
this.features,
|
||||
this.trialDays = 0,
|
||||
this.maxUsers = -1,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
});
|
||||
|
||||
factory SubscriptionPlan.fromJson(Map<String, dynamic> json) {
|
||||
// 兼容后端字段可能为空或类型不一致(如 BigDecimal 序列化为字符串)
|
||||
final dynamic priceRaw = json['price'];
|
||||
final double parsedPrice = priceRaw is num
|
||||
? priceRaw.toDouble()
|
||||
: (priceRaw is String ? double.tryParse(priceRaw) ?? 0.0 : 0.0);
|
||||
|
||||
final dynamic priorityRaw = json['priority'];
|
||||
final int parsedPriority = priorityRaw is num
|
||||
? priorityRaw.toInt()
|
||||
: (priorityRaw is String ? int.tryParse(priorityRaw) ?? 0 : 0);
|
||||
|
||||
final dynamic creditsRaw = json['creditsGranted'];
|
||||
final int? parsedCredits = creditsRaw == null
|
||||
? null
|
||||
: (creditsRaw is num
|
||||
? creditsRaw.toInt()
|
||||
: (creditsRaw is String ? int.tryParse(creditsRaw) : null));
|
||||
|
||||
final dynamic activeRaw = json['active'];
|
||||
final bool parsedActive = activeRaw is bool
|
||||
? activeRaw
|
||||
: (activeRaw is String ? activeRaw.toLowerCase() == 'true' : true);
|
||||
|
||||
final dynamic recommendedRaw = json['recommended'];
|
||||
final bool parsedRecommended = recommendedRaw is bool
|
||||
? recommendedRaw
|
||||
: (recommendedRaw is String ? recommendedRaw.toLowerCase() == 'true' : false);
|
||||
|
||||
final featuresRaw = json['features'];
|
||||
final Map<String, dynamic>? parsedFeatures =
|
||||
featuresRaw is Map<String, dynamic> ? featuresRaw : null;
|
||||
|
||||
return SubscriptionPlan(
|
||||
id: json['id'] as String?,
|
||||
planName: (json['planName'] as String?) ?? '未命名套餐',
|
||||
description: json['description'] as String?,
|
||||
price: parsedPrice,
|
||||
currency: (json['currency'] as String?) ?? 'CNY',
|
||||
billingCycle: _parseBillingCycle(json['billingCycle']),
|
||||
roleId: json['roleId'] as String?,
|
||||
creditsGranted: parsedCredits,
|
||||
active: parsedActive,
|
||||
recommended: parsedRecommended,
|
||||
priority: parsedPriority,
|
||||
features: parsedFeatures,
|
||||
trialDays: ((json['trialDays'] is String)
|
||||
? int.tryParse(json['trialDays'])
|
||||
: (json['trialDays'] as num?))
|
||||
?.toInt() ?? 0,
|
||||
maxUsers: ((json['maxUsers'] is String)
|
||||
? int.tryParse(json['maxUsers'])
|
||||
: (json['maxUsers'] as num?))
|
||||
?.toInt() ?? -1,
|
||||
createdAt: json['createdAt'] != null ? parseBackendDateTime(json['createdAt']) : null,
|
||||
updatedAt: json['updatedAt'] != null ? parseBackendDateTime(json['updatedAt']) : null,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => _$SubscriptionPlanToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
id,
|
||||
planName,
|
||||
description,
|
||||
price,
|
||||
currency,
|
||||
billingCycle,
|
||||
roleId,
|
||||
creditsGranted,
|
||||
active,
|
||||
recommended,
|
||||
priority,
|
||||
features,
|
||||
trialDays,
|
||||
maxUsers,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
];
|
||||
|
||||
/// 获取月度等价价格
|
||||
double get monthlyEquivalentPrice {
|
||||
switch (billingCycle) {
|
||||
case BillingCycle.monthly:
|
||||
return price;
|
||||
case BillingCycle.quarterly:
|
||||
return price / 3;
|
||||
case BillingCycle.yearly:
|
||||
return price / 12;
|
||||
case BillingCycle.lifetime:
|
||||
return price / 120; // 假设10年使用期
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取计费周期显示文本
|
||||
String get billingCycleText {
|
||||
switch (billingCycle) {
|
||||
case BillingCycle.monthly:
|
||||
return '月付';
|
||||
case BillingCycle.quarterly:
|
||||
return '季付';
|
||||
case BillingCycle.yearly:
|
||||
return '年付';
|
||||
case BillingCycle.lifetime:
|
||||
return '终身';
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取格式化价格
|
||||
String get formattedPrice {
|
||||
return '$currency ${price.toStringAsFixed(2)}';
|
||||
}
|
||||
|
||||
/// 解析BillingCycle枚举
|
||||
static BillingCycle _parseBillingCycle(dynamic value) {
|
||||
if (value == null) return BillingCycle.monthly;
|
||||
|
||||
final stringValue = value.toString().toUpperCase();
|
||||
switch (stringValue) {
|
||||
case 'MONTHLY':
|
||||
return BillingCycle.monthly;
|
||||
case 'QUARTERLY':
|
||||
return BillingCycle.quarterly;
|
||||
case 'YEARLY':
|
||||
return BillingCycle.yearly;
|
||||
case 'LIFETIME':
|
||||
return BillingCycle.lifetime;
|
||||
default:
|
||||
return BillingCycle.monthly;
|
||||
}
|
||||
}
|
||||
|
||||
/// 创建副本
|
||||
SubscriptionPlan copyWith({
|
||||
String? id,
|
||||
String? planName,
|
||||
String? description,
|
||||
double? price,
|
||||
String? currency,
|
||||
BillingCycle? billingCycle,
|
||||
String? roleId,
|
||||
int? creditsGranted,
|
||||
bool? active,
|
||||
bool? recommended,
|
||||
int? priority,
|
||||
Map<String, dynamic>? features,
|
||||
int? trialDays,
|
||||
int? maxUsers,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
}) {
|
||||
return SubscriptionPlan(
|
||||
id: id ?? this.id,
|
||||
planName: planName ?? this.planName,
|
||||
description: description ?? this.description,
|
||||
price: price ?? this.price,
|
||||
currency: currency ?? this.currency,
|
||||
billingCycle: billingCycle ?? this.billingCycle,
|
||||
roleId: roleId ?? this.roleId,
|
||||
creditsGranted: creditsGranted ?? this.creditsGranted,
|
||||
active: active ?? this.active,
|
||||
recommended: recommended ?? this.recommended,
|
||||
priority: priority ?? this.priority,
|
||||
features: features ?? this.features,
|
||||
trialDays: trialDays ?? this.trialDays,
|
||||
maxUsers: maxUsers ?? this.maxUsers,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
updatedAt: updatedAt ?? this.updatedAt,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 计费周期枚举
|
||||
enum BillingCycle {
|
||||
@JsonValue('MONTHLY')
|
||||
monthly,
|
||||
@JsonValue('QUARTERLY')
|
||||
quarterly,
|
||||
@JsonValue('YEARLY')
|
||||
yearly,
|
||||
@JsonValue('LIFETIME')
|
||||
lifetime,
|
||||
}
|
||||
|
||||
/// 用户订阅模型
|
||||
@JsonSerializable()
|
||||
class UserSubscription extends Equatable {
|
||||
final String? id;
|
||||
final String userId;
|
||||
final String planId;
|
||||
final DateTime? startDate;
|
||||
final DateTime? endDate;
|
||||
final SubscriptionStatus status;
|
||||
final bool autoRenewal;
|
||||
final String? paymentMethod;
|
||||
final String? transactionId;
|
||||
final int creditsUsed;
|
||||
final int totalCredits;
|
||||
final DateTime? canceledAt;
|
||||
final String? cancelReason;
|
||||
final DateTime? trialEndDate;
|
||||
final bool isTrial;
|
||||
final DateTime? createdAt;
|
||||
final DateTime? updatedAt;
|
||||
|
||||
const UserSubscription({
|
||||
this.id,
|
||||
required this.userId,
|
||||
required this.planId,
|
||||
this.startDate,
|
||||
this.endDate,
|
||||
required this.status,
|
||||
this.autoRenewal = false,
|
||||
this.paymentMethod,
|
||||
this.transactionId,
|
||||
this.creditsUsed = 0,
|
||||
this.totalCredits = 0,
|
||||
this.canceledAt,
|
||||
this.cancelReason,
|
||||
this.trialEndDate,
|
||||
this.isTrial = false,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
});
|
||||
|
||||
factory UserSubscription.fromJson(Map<String, dynamic> json) {
|
||||
return UserSubscription(
|
||||
id: json['id'] as String?,
|
||||
userId: json['userId'] as String,
|
||||
planId: json['planId'] as String,
|
||||
startDate: json['startDate'] != null ? parseBackendDateTime(json['startDate']) : null,
|
||||
endDate: json['endDate'] != null ? parseBackendDateTime(json['endDate']) : null,
|
||||
status: _parseSubscriptionStatus(json['status']),
|
||||
autoRenewal: json['autoRenewal'] as bool? ?? false,
|
||||
paymentMethod: json['paymentMethod'] as String?,
|
||||
transactionId: json['transactionId'] as String?,
|
||||
creditsUsed: (json['creditsUsed'] as num?)?.toInt() ?? 0,
|
||||
totalCredits: (json['totalCredits'] as num?)?.toInt() ?? 0,
|
||||
canceledAt: json['canceledAt'] != null ? parseBackendDateTime(json['canceledAt']) : null,
|
||||
cancelReason: json['cancelReason'] as String?,
|
||||
trialEndDate: json['trialEndDate'] != null ? parseBackendDateTime(json['trialEndDate']) : null,
|
||||
isTrial: json['isTrial'] as bool? ?? false,
|
||||
createdAt: json['createdAt'] != null ? parseBackendDateTime(json['createdAt']) : null,
|
||||
updatedAt: json['updatedAt'] != null ? parseBackendDateTime(json['updatedAt']) : null,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => _$UserSubscriptionToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
id,
|
||||
userId,
|
||||
planId,
|
||||
startDate,
|
||||
endDate,
|
||||
status,
|
||||
autoRenewal,
|
||||
paymentMethod,
|
||||
transactionId,
|
||||
creditsUsed,
|
||||
totalCredits,
|
||||
canceledAt,
|
||||
cancelReason,
|
||||
trialEndDate,
|
||||
isTrial,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
];
|
||||
|
||||
/// 获取剩余积分
|
||||
int get remainingCredits => (totalCredits - creditsUsed).clamp(0, totalCredits);
|
||||
|
||||
/// 检查订阅是否有效
|
||||
bool get isValid {
|
||||
final now = DateTime.now();
|
||||
return (status == SubscriptionStatus.active || status == SubscriptionStatus.trial) &&
|
||||
(endDate == null || endDate!.isAfter(now));
|
||||
}
|
||||
|
||||
/// 检查是否即将过期(7天内)
|
||||
bool get isExpiringSoon {
|
||||
if (endDate == null) return false;
|
||||
final now = DateTime.now();
|
||||
final sevenDaysLater = now.add(const Duration(days: 7));
|
||||
return endDate!.isBefore(sevenDaysLater) && endDate!.isAfter(now);
|
||||
}
|
||||
|
||||
/// 解析SubscriptionStatus枚举
|
||||
static SubscriptionStatus _parseSubscriptionStatus(dynamic value) {
|
||||
if (value == null) return SubscriptionStatus.active;
|
||||
|
||||
final stringValue = value.toString().toUpperCase();
|
||||
switch (stringValue) {
|
||||
case 'ACTIVE':
|
||||
return SubscriptionStatus.active;
|
||||
case 'TRIAL':
|
||||
return SubscriptionStatus.trial;
|
||||
case 'CANCELED':
|
||||
return SubscriptionStatus.canceled;
|
||||
case 'EXPIRED':
|
||||
return SubscriptionStatus.expired;
|
||||
case 'SUSPENDED':
|
||||
return SubscriptionStatus.suspended;
|
||||
case 'REFUNDED':
|
||||
return SubscriptionStatus.refunded;
|
||||
default:
|
||||
return SubscriptionStatus.active;
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取状态显示文本
|
||||
String get statusText {
|
||||
switch (status) {
|
||||
case SubscriptionStatus.active:
|
||||
return '活跃';
|
||||
case SubscriptionStatus.trial:
|
||||
return '试用期';
|
||||
case SubscriptionStatus.canceled:
|
||||
return '已取消';
|
||||
case SubscriptionStatus.expired:
|
||||
return '已过期';
|
||||
case SubscriptionStatus.suspended:
|
||||
return '暂停';
|
||||
case SubscriptionStatus.refunded:
|
||||
return '已退款';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 订阅状态枚举
|
||||
enum SubscriptionStatus {
|
||||
@JsonValue('ACTIVE')
|
||||
active,
|
||||
@JsonValue('TRIAL')
|
||||
trial,
|
||||
@JsonValue('CANCELED')
|
||||
canceled,
|
||||
@JsonValue('EXPIRED')
|
||||
expired,
|
||||
@JsonValue('SUSPENDED')
|
||||
suspended,
|
||||
@JsonValue('REFUNDED')
|
||||
refunded,
|
||||
}
|
||||
|
||||
/// 订阅统计信息
|
||||
@JsonSerializable()
|
||||
class SubscriptionStatistics extends Equatable {
|
||||
final int totalPlans;
|
||||
final int activePlans;
|
||||
final int totalSubscriptions;
|
||||
final int activeSubscriptions;
|
||||
final int trialSubscriptions;
|
||||
final double monthlyRevenue;
|
||||
final double yearlyRevenue;
|
||||
|
||||
const SubscriptionStatistics({
|
||||
required this.totalPlans,
|
||||
required this.activePlans,
|
||||
required this.totalSubscriptions,
|
||||
required this.activeSubscriptions,
|
||||
required this.trialSubscriptions,
|
||||
required this.monthlyRevenue,
|
||||
required this.yearlyRevenue,
|
||||
});
|
||||
|
||||
factory SubscriptionStatistics.fromJson(Map<String, dynamic> json) =>
|
||||
_$SubscriptionStatisticsFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$SubscriptionStatisticsToJson(this);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
totalPlans,
|
||||
activePlans,
|
||||
totalSubscriptions,
|
||||
activeSubscriptions,
|
||||
trialSubscriptions,
|
||||
monthlyRevenue,
|
||||
yearlyRevenue,
|
||||
];
|
||||
}
|
||||
191
AINoval/lib/models/admin/subscription_models.g.dart
Normal file
191
AINoval/lib/models/admin/subscription_models.g.dart
Normal file
@@ -0,0 +1,191 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'subscription_models.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
SubscriptionPlan _$SubscriptionPlanFromJson(Map<String, dynamic> json) =>
|
||||
$checkedCreate(
|
||||
'SubscriptionPlan',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = SubscriptionPlan(
|
||||
id: $checkedConvert('id', (v) => v as String?),
|
||||
planName: $checkedConvert('planName', (v) => v as String),
|
||||
description: $checkedConvert('description', (v) => v as String?),
|
||||
price: $checkedConvert('price', (v) => (v as num).toDouble()),
|
||||
currency: $checkedConvert('currency', (v) => v as String),
|
||||
billingCycle: $checkedConvert(
|
||||
'billingCycle', (v) => $enumDecode(_$BillingCycleEnumMap, v)),
|
||||
roleId: $checkedConvert('roleId', (v) => v as String?),
|
||||
creditsGranted:
|
||||
$checkedConvert('creditsGranted', (v) => (v as num?)?.toInt()),
|
||||
active: $checkedConvert('active', (v) => v as bool? ?? true),
|
||||
recommended:
|
||||
$checkedConvert('recommended', (v) => v as bool? ?? false),
|
||||
priority:
|
||||
$checkedConvert('priority', (v) => (v as num?)?.toInt() ?? 0),
|
||||
features:
|
||||
$checkedConvert('features', (v) => v as Map<String, dynamic>?),
|
||||
trialDays:
|
||||
$checkedConvert('trialDays', (v) => (v as num?)?.toInt() ?? 0),
|
||||
maxUsers:
|
||||
$checkedConvert('maxUsers', (v) => (v as num?)?.toInt() ?? -1),
|
||||
createdAt: $checkedConvert('createdAt',
|
||||
(v) => v == null ? null : DateTime.parse(v as String)),
|
||||
updatedAt: $checkedConvert('updatedAt',
|
||||
(v) => v == null ? null : DateTime.parse(v as String)),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SubscriptionPlanToJson(SubscriptionPlan instance) {
|
||||
final val = <String, dynamic>{};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('id', instance.id);
|
||||
val['planName'] = instance.planName;
|
||||
writeNotNull('description', instance.description);
|
||||
val['price'] = instance.price;
|
||||
val['currency'] = instance.currency;
|
||||
val['billingCycle'] = _$BillingCycleEnumMap[instance.billingCycle]!;
|
||||
writeNotNull('roleId', instance.roleId);
|
||||
writeNotNull('creditsGranted', instance.creditsGranted);
|
||||
val['active'] = instance.active;
|
||||
val['recommended'] = instance.recommended;
|
||||
val['priority'] = instance.priority;
|
||||
writeNotNull('features', instance.features);
|
||||
val['trialDays'] = instance.trialDays;
|
||||
val['maxUsers'] = instance.maxUsers;
|
||||
writeNotNull('createdAt', instance.createdAt?.toIso8601String());
|
||||
writeNotNull('updatedAt', instance.updatedAt?.toIso8601String());
|
||||
return val;
|
||||
}
|
||||
|
||||
const _$BillingCycleEnumMap = {
|
||||
BillingCycle.monthly: 'MONTHLY',
|
||||
BillingCycle.quarterly: 'QUARTERLY',
|
||||
BillingCycle.yearly: 'YEARLY',
|
||||
BillingCycle.lifetime: 'LIFETIME',
|
||||
};
|
||||
|
||||
UserSubscription _$UserSubscriptionFromJson(Map<String, dynamic> json) =>
|
||||
$checkedCreate(
|
||||
'UserSubscription',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = UserSubscription(
|
||||
id: $checkedConvert('id', (v) => v as String?),
|
||||
userId: $checkedConvert('userId', (v) => v as String),
|
||||
planId: $checkedConvert('planId', (v) => v as String),
|
||||
startDate: $checkedConvert('startDate',
|
||||
(v) => v == null ? null : DateTime.parse(v as String)),
|
||||
endDate: $checkedConvert(
|
||||
'endDate', (v) => v == null ? null : DateTime.parse(v as String)),
|
||||
status: $checkedConvert(
|
||||
'status', (v) => $enumDecode(_$SubscriptionStatusEnumMap, v)),
|
||||
autoRenewal:
|
||||
$checkedConvert('autoRenewal', (v) => v as bool? ?? false),
|
||||
paymentMethod: $checkedConvert('paymentMethod', (v) => v as String?),
|
||||
transactionId: $checkedConvert('transactionId', (v) => v as String?),
|
||||
creditsUsed:
|
||||
$checkedConvert('creditsUsed', (v) => (v as num?)?.toInt() ?? 0),
|
||||
totalCredits:
|
||||
$checkedConvert('totalCredits', (v) => (v as num?)?.toInt() ?? 0),
|
||||
canceledAt: $checkedConvert('canceledAt',
|
||||
(v) => v == null ? null : DateTime.parse(v as String)),
|
||||
cancelReason: $checkedConvert('cancelReason', (v) => v as String?),
|
||||
trialEndDate: $checkedConvert('trialEndDate',
|
||||
(v) => v == null ? null : DateTime.parse(v as String)),
|
||||
isTrial: $checkedConvert('isTrial', (v) => v as bool? ?? false),
|
||||
createdAt: $checkedConvert('createdAt',
|
||||
(v) => v == null ? null : DateTime.parse(v as String)),
|
||||
updatedAt: $checkedConvert('updatedAt',
|
||||
(v) => v == null ? null : DateTime.parse(v as String)),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$UserSubscriptionToJson(UserSubscription instance) {
|
||||
final val = <String, dynamic>{};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('id', instance.id);
|
||||
val['userId'] = instance.userId;
|
||||
val['planId'] = instance.planId;
|
||||
writeNotNull('startDate', instance.startDate?.toIso8601String());
|
||||
writeNotNull('endDate', instance.endDate?.toIso8601String());
|
||||
val['status'] = _$SubscriptionStatusEnumMap[instance.status]!;
|
||||
val['autoRenewal'] = instance.autoRenewal;
|
||||
writeNotNull('paymentMethod', instance.paymentMethod);
|
||||
writeNotNull('transactionId', instance.transactionId);
|
||||
val['creditsUsed'] = instance.creditsUsed;
|
||||
val['totalCredits'] = instance.totalCredits;
|
||||
writeNotNull('canceledAt', instance.canceledAt?.toIso8601String());
|
||||
writeNotNull('cancelReason', instance.cancelReason);
|
||||
writeNotNull('trialEndDate', instance.trialEndDate?.toIso8601String());
|
||||
val['isTrial'] = instance.isTrial;
|
||||
writeNotNull('createdAt', instance.createdAt?.toIso8601String());
|
||||
writeNotNull('updatedAt', instance.updatedAt?.toIso8601String());
|
||||
return val;
|
||||
}
|
||||
|
||||
const _$SubscriptionStatusEnumMap = {
|
||||
SubscriptionStatus.active: 'ACTIVE',
|
||||
SubscriptionStatus.trial: 'TRIAL',
|
||||
SubscriptionStatus.canceled: 'CANCELED',
|
||||
SubscriptionStatus.expired: 'EXPIRED',
|
||||
SubscriptionStatus.suspended: 'SUSPENDED',
|
||||
SubscriptionStatus.refunded: 'REFUNDED',
|
||||
};
|
||||
|
||||
SubscriptionStatistics _$SubscriptionStatisticsFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
$checkedCreate(
|
||||
'SubscriptionStatistics',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = SubscriptionStatistics(
|
||||
totalPlans: $checkedConvert('totalPlans', (v) => (v as num).toInt()),
|
||||
activePlans:
|
||||
$checkedConvert('activePlans', (v) => (v as num).toInt()),
|
||||
totalSubscriptions:
|
||||
$checkedConvert('totalSubscriptions', (v) => (v as num).toInt()),
|
||||
activeSubscriptions:
|
||||
$checkedConvert('activeSubscriptions', (v) => (v as num).toInt()),
|
||||
trialSubscriptions:
|
||||
$checkedConvert('trialSubscriptions', (v) => (v as num).toInt()),
|
||||
monthlyRevenue:
|
||||
$checkedConvert('monthlyRevenue', (v) => (v as num).toDouble()),
|
||||
yearlyRevenue:
|
||||
$checkedConvert('yearlyRevenue', (v) => (v as num).toDouble()),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SubscriptionStatisticsToJson(
|
||||
SubscriptionStatistics instance) =>
|
||||
<String, dynamic>{
|
||||
'totalPlans': instance.totalPlans,
|
||||
'activePlans': instance.activePlans,
|
||||
'totalSubscriptions': instance.totalSubscriptions,
|
||||
'activeSubscriptions': instance.activeSubscriptions,
|
||||
'trialSubscriptions': instance.trialSubscriptions,
|
||||
'monthlyRevenue': instance.monthlyRevenue,
|
||||
'yearlyRevenue': instance.yearlyRevenue,
|
||||
};
|
||||
Reference in New Issue
Block a user