You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
251 lines
9.0 KiB
251 lines
9.0 KiB
import 'package:get_storage/get_storage.dart';
|
|
import 'package:get/get.dart';
|
|
import '../../../core/utils/logger.dart';
|
|
|
|
class User {
|
|
// 单例实例
|
|
static User? _instance;
|
|
|
|
/// 全局刷新信号(当用户信息更新时 +1,用于驱动UI重建)
|
|
static final RxInt refreshTick = 0.obs;
|
|
|
|
/// 安全地检查用户是否已经登录(即单例是否已初始化)
|
|
static bool isLoggedIn() {
|
|
return _instance != null;
|
|
}
|
|
|
|
// 单例访问器(增加空安全保护)
|
|
static User get instance {
|
|
if (_instance == null) {
|
|
throw Exception("User must be initialized first");
|
|
}
|
|
return _instance!;
|
|
}
|
|
|
|
// --- 新增 ---
|
|
/// 清理所有与用户会话相关的数据
|
|
static Future<void> clearUserSession() async {
|
|
final GetStorage storage = GetStorage();
|
|
// 1. 清理本地存储
|
|
await storage.remove('logintoken');
|
|
await storage.remove('user_info');
|
|
// 2. 清理内存中的单例
|
|
_instance = null;
|
|
Logger.i("User", "用户会话数据已安全清理。");
|
|
}
|
|
|
|
// 最终属性(不可变)
|
|
String name;
|
|
String uid;
|
|
String avatar;
|
|
String language;
|
|
String token;
|
|
String mail;
|
|
String phone;
|
|
String phonemac;
|
|
String password;
|
|
int viplv = 0; //添加会员等级字段,0表示普通用户
|
|
int vipexptime = 0; // 会员到期/剩余时间(秒/毫秒,按后端定义)
|
|
int aichatintegral = 0; // ai聊天积分
|
|
int aichattotalintegral = 0; // ai聊天总积分
|
|
int tradeintegral = 0; // 翻译积分
|
|
int tradetotalintegral = 0; // 翻译总积分
|
|
int meetintegral = 0; // 会议积分
|
|
int meettotalintegral = 0; // 会议总积分
|
|
int gender = 0; // 性别: 0=未设置, 1=男, 2=女
|
|
|
|
List<UserDevice> devices;
|
|
|
|
// 私有构造函数
|
|
User._({
|
|
required this.name,
|
|
required this.uid,
|
|
required this.avatar,
|
|
required this.language,
|
|
required this.token,
|
|
required this.mail,
|
|
required this.phone,
|
|
required this.phonemac,
|
|
required this.password,
|
|
required this.viplv,
|
|
required this.vipexptime,
|
|
required this.aichatintegral,
|
|
required this.aichattotalintegral,
|
|
required this.tradeintegral,
|
|
required this.tradetotalintegral,
|
|
required this.meetintegral,
|
|
required this.meettotalintegral,
|
|
required this.gender,
|
|
required this.devices,
|
|
});
|
|
|
|
factory User.fromJson(Map<String, dynamic> json) {
|
|
// 修复1:安全获取嵌套的 user 字段
|
|
final userData = json['user'] as Map<String, dynamic>?; // 允许空值
|
|
final devicesData = json['devices'] as List<dynamic>?; // 允许空值
|
|
//final token = json['data']['token'] as String? ?? '';
|
|
//final token = '';
|
|
final u = User._(
|
|
token: '',
|
|
name: (userData?['name'] as String?) ?? '默认名称',
|
|
uid: (userData?['uid'] as String?) ?? '',
|
|
avatar: (userData?['avatar'] as String?) ?? '',
|
|
language: (userData?['language'] as String?) ?? 'en',
|
|
mail: (userData?['mail'] as String?) ?? '',
|
|
phone: (userData?['phone'] as String?) ?? '',
|
|
phonemac: (userData?['phonemac'] as String?) ?? '',
|
|
password: (userData?['password'] as String?) ?? '',
|
|
viplv: (userData?['viplv'] as int?) ?? 0, // 提供默认值
|
|
vipexptime: (userData?['vipexptime'] as int?) ?? 0, // 提供默认值
|
|
|
|
aichatintegral: (userData?['aichatintegral'] as int?) ?? 0,
|
|
aichattotalintegral: (userData?['aichattotalintegral'] as int?) ?? 0,
|
|
tradeintegral: (userData?['tradeintegral'] as int?) ?? 0,
|
|
tradetotalintegral: (userData?['tradetotalintegral'] as int?) ?? 0,
|
|
meetintegral: (userData?['meetintegral'] as int?) ?? 0,
|
|
meettotalintegral: (userData?['meettotalintegral'] as int?) ?? 0,
|
|
gender: (userData?['gender'] as int?) ?? 0,
|
|
devices: devicesData
|
|
?.map((e) => UserDevice.fromJson(e as Map<String, dynamic>))
|
|
.toList() ??
|
|
[],
|
|
);
|
|
_instance = u;
|
|
Logger.i("User",
|
|
"初始化用户: uid=${u.uid}, name=${u.name}, gender=${u.gender}, viplv=${u.viplv}, vipexptime=${u.vipexptime}, ai聊天=${u.aichatintegral}/${u.aichattotalintegral}, 翻译=${u.tradeintegral}/${u.tradetotalintegral}, 会议=${u.meetintegral}/${u.meettotalintegral}");
|
|
return u;
|
|
}
|
|
|
|
factory User.fronTokenJson(Map<String, dynamic> json) {
|
|
// 修复1:安全获取嵌套的 user 字段
|
|
final userData = json['user'] as Map<String, dynamic>?; // 允许空值
|
|
final devicesData = json['devices'] as List<dynamic>?; // 允许空值
|
|
Logger.d("User",
|
|
"fronTokenJson: user=$userData, devices=${devicesData?.length ?? 0}");
|
|
final u = User._(
|
|
token: '',
|
|
name: (userData?['name'] as String?) ?? '默认名称',
|
|
uid: (userData?['uid'] as String?) ?? '',
|
|
avatar: (userData?['avatar'] as String?) ?? '',
|
|
language: (userData?['language'] as String?) ?? 'en',
|
|
mail: (userData?['mail'] as String?) ?? '',
|
|
phone: (userData?['phone'] as String?) ?? '',
|
|
phonemac: (userData?['phonemac'] as String?) ?? '',
|
|
password: (userData?['password'] as String?) ?? '',
|
|
viplv: (userData?['viplv'] as int?) ?? 0, // 提供默认值
|
|
vipexptime: (userData?['vipexptime'] as int?) ?? 0, // 提供默认值
|
|
aichatintegral: (userData?['aichatintegral'] as int?) ?? 0,
|
|
aichattotalintegral: (userData?['aichattotalintegral'] as int?) ?? 0,
|
|
tradeintegral: (userData?['tradeintegral'] as int?) ?? 0,
|
|
tradetotalintegral: (userData?['tradetotalintegral'] as int?) ?? 0,
|
|
meetintegral: (userData?['meetintegral'] as int?) ?? 0,
|
|
meettotalintegral: (userData?['meettotalintegral'] as int?) ?? 0,
|
|
gender: (userData?['gender'] as int?) ?? 0,
|
|
devices: devicesData != null
|
|
? (devicesData)
|
|
.map((e) => UserDevice.fromJson(e as Map<String, dynamic>))
|
|
.toList()
|
|
: [],
|
|
);
|
|
_instance = u;
|
|
Logger.i("User",
|
|
"初始化用户(token): uid=${u.uid}, name=${u.name}, gender=${u.gender}, viplv=${u.viplv}, vipexptime=${u.vipexptime}, ai聊天=${u.aichatintegral}/${u.aichattotalintegral}, 翻译=${u.tradeintegral}/${u.tradetotalintegral}, 会议=${u.meetintegral}/${u.meettotalintegral}");
|
|
return u;
|
|
}
|
|
|
|
updateUserInfo(Map<String, dynamic> user) {
|
|
name = user['name'] as String? ?? name;
|
|
uid = user['uid'] as String? ?? uid;
|
|
avatar = user['avatar'] as String? ?? avatar;
|
|
language = user['language'] as String? ?? language;
|
|
token = user['token'] as String? ?? token;
|
|
mail = user['mail'] as String? ?? mail;
|
|
phone = user['phone'] as String? ?? phone;
|
|
phonemac = user['phonemac'] as String? ?? phonemac;
|
|
password = user['password'] as String? ?? password;
|
|
viplv = user['viplv'] as int? ?? viplv;
|
|
vipexptime = user['vipexptime'] as int? ?? vipexptime;
|
|
aichatintegral = user['aichatintegral'] as int? ?? aichatintegral;
|
|
aichattotalintegral =
|
|
user['aichattotalintegral'] as int? ?? aichattotalintegral;
|
|
tradeintegral = user['tradeintegral'] as int? ?? tradeintegral;
|
|
tradetotalintegral =
|
|
user['tradetotalintegral'] as int? ?? tradetotalintegral;
|
|
meetintegral = user['meetintegral'] as int? ?? meetintegral;
|
|
meettotalintegral = user['meettotalintegral'] as int? ?? meettotalintegral;
|
|
gender = user['gender'] as int? ?? gender;
|
|
|
|
// 触发全局刷新信号,驱动依赖UI重建
|
|
refreshTick.value++;
|
|
}
|
|
|
|
// 完整的JSON序列化
|
|
Map<String, dynamic> toJson() => {
|
|
'user': {
|
|
'name': name,
|
|
'uid': uid,
|
|
'avatar': avatar,
|
|
'language': language,
|
|
'token': token,
|
|
'mail': mail,
|
|
'phone': phone,
|
|
'phonemac': phonemac,
|
|
'password': password,
|
|
'viplv': viplv,
|
|
'vipexptime': vipexptime,
|
|
'aichatintegral': aichatintegral,
|
|
'aichattotalintegral': aichattotalintegral,
|
|
'tradeintegral': tradeintegral,
|
|
'tradetotalintegral': tradetotalintegral,
|
|
'meetintegral': meetintegral,
|
|
'meettotalintegral': meettotalintegral,
|
|
'gender': gender,
|
|
'devices': devices.map((device) => device.toJson()).toList(),
|
|
},
|
|
};
|
|
|
|
// 添加设备
|
|
addUserDevice(UserDevice device) {
|
|
devices.add(device);
|
|
}
|
|
|
|
// 查找设备
|
|
removeUserDevice(int id) {
|
|
devices.removeWhere((device) => device.id == id);
|
|
}
|
|
}
|
|
|
|
class UserDevice {
|
|
int id;
|
|
String uid;
|
|
int devicetype;
|
|
String devicename;
|
|
String devicemac;
|
|
String license;
|
|
UserDevice({
|
|
required this.id,
|
|
required this.uid,
|
|
required this.devicetype,
|
|
required this.devicename,
|
|
required this.devicemac,
|
|
required this.license,
|
|
});
|
|
|
|
factory UserDevice.fromJson(Map<String, dynamic> json) => UserDevice(
|
|
id: json['id'] as int,
|
|
uid: json['uid'] as String,
|
|
devicetype: (json['devicetype'] as num).toInt(),
|
|
devicename: json['devicename'] as String,
|
|
devicemac: json['devicemac'] as String,
|
|
license: json['license'] as String,
|
|
);
|
|
|
|
toJson() => {
|
|
'id': id,
|
|
'uid': uid,
|
|
'devicetype': devicetype,
|
|
'devicename': devicename,
|
|
'devicemac': devicemac,
|
|
'license': license,
|
|
};
|
|
}
|
|
|