chore: 批量代码优化与功能迭代更新
本次提交包含大量代码优化、功能新增与服务端配置更新: 1. 修复分析报告统计数据,调整CMake策略设置 2. 优化APP权限配置、编辑器与聊天界面组件 3. 更新依赖库版本与pubspec配置 4. 新增文件传输服务端、信令服务器相关配置与脚本 5. 完善用户注销功能与数据库迁移脚本 6. 优化多处动画效果、代码风格与日志输出 7. 新增多种调试与部署脚本,修复已知BUG
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
/// ============================================================
|
||||
/// 闲言APP — 用户数据模型
|
||||
/// 创建时间: 2026-04-28
|
||||
/// 更新时间: 2026-04-29
|
||||
/// 更新时间: 2026-05-11
|
||||
/// 作用: 用户信息数据模型,对应后端 tool_user 表
|
||||
/// 上次更新: 新增verification验证状态字段
|
||||
/// 上次更新: v10.0.0 UserDevice新增ipCity/ipRange字段
|
||||
/// ============================================================
|
||||
|
||||
class UserModel {
|
||||
@@ -12,6 +12,7 @@ class UserModel {
|
||||
required this.username,
|
||||
this.nickname = '',
|
||||
this.avatar = '',
|
||||
this.avatarUrl = '',
|
||||
this.email = '',
|
||||
this.mobile = '',
|
||||
this.score = 0,
|
||||
@@ -25,12 +26,19 @@ class UserModel {
|
||||
this.token,
|
||||
this.title,
|
||||
this.verification,
|
||||
this.isOnline = 0,
|
||||
this.vip,
|
||||
this.cloudSpace,
|
||||
this.devices = const [],
|
||||
this.extra,
|
||||
this.profileSlug = '',
|
||||
});
|
||||
|
||||
final int id;
|
||||
final String username;
|
||||
final String nickname;
|
||||
final String avatar;
|
||||
final String avatarUrl;
|
||||
final String email;
|
||||
final String mobile;
|
||||
final int score;
|
||||
@@ -45,20 +53,42 @@ class UserModel {
|
||||
final UserTitle? title;
|
||||
final UserVerification? verification;
|
||||
|
||||
final int isOnline;
|
||||
final UserVip? vip;
|
||||
final UserCloudSpace? cloudSpace;
|
||||
final List<UserDevice> devices;
|
||||
final UserExtra? extra;
|
||||
final String profileSlug;
|
||||
|
||||
String get displayName => nickname.isNotEmpty ? nickname : username;
|
||||
|
||||
String get avatarUrl {
|
||||
if (avatar.isEmpty) return '';
|
||||
if (avatar.startsWith('http')) return avatar;
|
||||
return 'https://tools.wktyl.com$avatar';
|
||||
String get avatarDisplayUrl {
|
||||
if (avatarUrl.isNotEmpty) {
|
||||
if (avatarUrl.startsWith('http')) return avatarUrl;
|
||||
return 'https://tools.wktyl.com$avatarUrl';
|
||||
}
|
||||
if (avatar.isNotEmpty) {
|
||||
if (avatar.startsWith('http')) return avatar;
|
||||
if (avatar.startsWith('data:')) return avatar;
|
||||
return 'https://tools.wktyl.com$avatar';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
@Deprecated('Use avatarDisplayUrl instead')
|
||||
String get avatarUrlCompat => avatarDisplayUrl;
|
||||
|
||||
bool get isVip => vip?.isVip ?? false;
|
||||
|
||||
bool get getIsOnline => isOnline == 1;
|
||||
|
||||
factory UserModel.fromJson(Map<String, dynamic> json) {
|
||||
return UserModel(
|
||||
id: json['id'] as int? ?? 0,
|
||||
username: json['username'] as String? ?? '',
|
||||
nickname: json['nickname'] as String? ?? '',
|
||||
avatar: json['avatar'] as String? ?? '',
|
||||
avatarUrl: json['avatar_url'] as String? ?? '',
|
||||
email: json['email'] as String? ?? '',
|
||||
mobile: json['mobile'] as String? ?? '',
|
||||
score: json['score'] as int? ?? 0,
|
||||
@@ -75,8 +105,25 @@ class UserModel {
|
||||
: null,
|
||||
verification: json['verification'] != null
|
||||
? UserVerification.fromJson(
|
||||
json['verification'] as Map<String, dynamic>)
|
||||
json['verification'] as Map<String, dynamic>,
|
||||
)
|
||||
: null,
|
||||
isOnline: json['is_online'] as int? ?? 0,
|
||||
vip: json['vip'] != null
|
||||
? UserVip.fromJson(json['vip'] as Map<String, dynamic>)
|
||||
: null,
|
||||
cloudSpace: json['cloud_space'] != null
|
||||
? UserCloudSpace.fromJson(json['cloud_space'] as Map<String, dynamic>)
|
||||
: null,
|
||||
devices: json['devices'] != null
|
||||
? (json['devices'] as List<dynamic>)
|
||||
.map((e) => UserDevice.fromJson(e as Map<String, dynamic>))
|
||||
.toList()
|
||||
: [],
|
||||
extra: json['extra'] != null
|
||||
? UserExtra.fromJson(json['extra'] as Map<String, dynamic>)
|
||||
: null,
|
||||
profileSlug: json['profile_slug'] as String? ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -85,6 +132,7 @@ class UserModel {
|
||||
String? username,
|
||||
String? nickname,
|
||||
String? avatar,
|
||||
String? avatarUrl,
|
||||
String? email,
|
||||
String? mobile,
|
||||
int? score,
|
||||
@@ -98,12 +146,19 @@ class UserModel {
|
||||
String? token,
|
||||
UserTitle? title,
|
||||
UserVerification? verification,
|
||||
int? isOnline,
|
||||
UserVip? vip,
|
||||
UserCloudSpace? cloudSpace,
|
||||
List<UserDevice>? devices,
|
||||
UserExtra? extra,
|
||||
String? profileSlug,
|
||||
}) {
|
||||
return UserModel(
|
||||
id: id ?? this.id,
|
||||
username: username ?? this.username,
|
||||
nickname: nickname ?? this.nickname,
|
||||
avatar: avatar ?? this.avatar,
|
||||
avatarUrl: avatarUrl ?? this.avatarUrl,
|
||||
email: email ?? this.email,
|
||||
mobile: mobile ?? this.mobile,
|
||||
score: score ?? this.score,
|
||||
@@ -117,6 +172,12 @@ class UserModel {
|
||||
token: token ?? this.token,
|
||||
title: title ?? this.title,
|
||||
verification: verification ?? this.verification,
|
||||
isOnline: isOnline ?? this.isOnline,
|
||||
vip: vip ?? this.vip,
|
||||
cloudSpace: cloudSpace ?? this.cloudSpace,
|
||||
devices: devices ?? this.devices,
|
||||
extra: extra ?? this.extra,
|
||||
profileSlug: profileSlug ?? this.profileSlug,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -145,10 +206,7 @@ class UserTitle {
|
||||
}
|
||||
|
||||
class UserVerification {
|
||||
const UserVerification({
|
||||
this.email = 0,
|
||||
this.mobile = 0,
|
||||
});
|
||||
const UserVerification({this.email = 0, this.mobile = 0});
|
||||
|
||||
final int email;
|
||||
final int mobile;
|
||||
@@ -163,3 +221,177 @@ class UserVerification {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class UserVip {
|
||||
const UserVip({
|
||||
this.isVip = false,
|
||||
this.startTime = 0,
|
||||
this.endTime = 0,
|
||||
this.startDate = '',
|
||||
this.endDate = '',
|
||||
});
|
||||
|
||||
final bool isVip;
|
||||
final int startTime;
|
||||
final int endTime;
|
||||
final String startDate;
|
||||
final String endDate;
|
||||
|
||||
bool get isActive => isVip && endTime > 0;
|
||||
|
||||
factory UserVip.fromJson(Map<String, dynamic> json) {
|
||||
return UserVip(
|
||||
isVip: json['is_vip'] as bool? ?? false,
|
||||
startTime: json['start_time'] as int? ?? 0,
|
||||
endTime: json['end_time'] as int? ?? 0,
|
||||
startDate: json['start_date'] as String? ?? '',
|
||||
endDate: json['end_date'] as String? ?? '',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class UserCloudSpace {
|
||||
const UserCloudSpace({
|
||||
this.total = 0,
|
||||
this.used = 0,
|
||||
this.free = 0,
|
||||
this.totalHuman = '',
|
||||
this.usedHuman = '',
|
||||
this.usagePercent = 0.0,
|
||||
});
|
||||
|
||||
final int total;
|
||||
final int used;
|
||||
final int free;
|
||||
final String totalHuman;
|
||||
final String usedHuman;
|
||||
final double usagePercent;
|
||||
|
||||
factory UserCloudSpace.fromJson(Map<String, dynamic> json) {
|
||||
return UserCloudSpace(
|
||||
total: json['total'] as int? ?? 0,
|
||||
used: json['used'] as int? ?? 0,
|
||||
free: json['free'] as int? ?? 0,
|
||||
totalHuman: json['total_human'] as String? ?? '',
|
||||
usedHuman: json['used_human'] as String? ?? '',
|
||||
usagePercent: (json['usage_percent'] as num?)?.toDouble() ?? 0.0,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class UserDevice {
|
||||
const UserDevice({
|
||||
this.id = 0,
|
||||
this.deviceName = '',
|
||||
this.deviceModel = '',
|
||||
this.platform = '',
|
||||
this.appName = '',
|
||||
this.ip = '',
|
||||
this.ipCity = '',
|
||||
this.ipRange = '',
|
||||
this.lastActiveTime = 0,
|
||||
this.isOnline = 0,
|
||||
this.createtime = 0,
|
||||
this.lastActiveText = '',
|
||||
this.createtimeText = '',
|
||||
});
|
||||
|
||||
final int id;
|
||||
final String deviceName;
|
||||
final String deviceModel;
|
||||
final String platform;
|
||||
final String appName;
|
||||
final String ip;
|
||||
final String ipCity;
|
||||
final String ipRange;
|
||||
final int lastActiveTime;
|
||||
final int isOnline;
|
||||
final int createtime;
|
||||
final String lastActiveText;
|
||||
final String createtimeText;
|
||||
|
||||
bool get getIsOnline => isOnline == 1;
|
||||
|
||||
bool get hasIpCity => ipCity.isNotEmpty;
|
||||
|
||||
bool get hasIpRange => ipRange.isNotEmpty;
|
||||
|
||||
String get displayLocation => hasIpCity ? '📍 $ipCity' : '';
|
||||
|
||||
factory UserDevice.fromJson(Map<String, dynamic> json) {
|
||||
return UserDevice(
|
||||
id: json['id'] as int? ?? 0,
|
||||
deviceName: json['device_name'] as String? ?? '',
|
||||
deviceModel: json['device_model'] as String? ?? '',
|
||||
platform: json['platform'] as String? ?? '',
|
||||
appName: json['app_name'] as String? ?? '',
|
||||
ip: json['ip'] as String? ?? '',
|
||||
ipCity: json['ip_city'] as String? ?? '',
|
||||
ipRange: json['ip_range'] as String? ?? '',
|
||||
lastActiveTime: json['last_active_time'] as int? ?? 0,
|
||||
isOnline: json['is_online'] as int? ?? 0,
|
||||
createtime: json['createtime'] as int? ?? 0,
|
||||
lastActiveText: json['last_active_text'] as String? ?? '',
|
||||
createtimeText: json['createtime_text'] as String? ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
UserDevice copyWith({
|
||||
int? id,
|
||||
String? deviceName,
|
||||
String? deviceModel,
|
||||
String? platform,
|
||||
String? appName,
|
||||
String? ip,
|
||||
String? ipCity,
|
||||
String? ipRange,
|
||||
int? lastActiveTime,
|
||||
int? isOnline,
|
||||
int? createtime,
|
||||
String? lastActiveText,
|
||||
String? createtimeText,
|
||||
}) {
|
||||
return UserDevice(
|
||||
id: id ?? this.id,
|
||||
deviceName: deviceName ?? this.deviceName,
|
||||
deviceModel: deviceModel ?? this.deviceModel,
|
||||
platform: platform ?? this.platform,
|
||||
appName: appName ?? this.appName,
|
||||
ip: ip ?? this.ip,
|
||||
ipCity: ipCity ?? this.ipCity,
|
||||
ipRange: ipRange ?? this.ipRange,
|
||||
lastActiveTime: lastActiveTime ?? this.lastActiveTime,
|
||||
isOnline: isOnline ?? this.isOnline,
|
||||
createtime: createtime ?? this.createtime,
|
||||
lastActiveText: lastActiveText ?? this.lastActiveText,
|
||||
createtimeText: createtimeText ?? this.createtimeText,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class UserExtra {
|
||||
const UserExtra({
|
||||
this.money = '0.00',
|
||||
this.noteLimit = 50,
|
||||
this.verification,
|
||||
this.lastSigninDate = '',
|
||||
});
|
||||
|
||||
final String money;
|
||||
final int noteLimit;
|
||||
final UserVerification? verification;
|
||||
final String lastSigninDate;
|
||||
|
||||
factory UserExtra.fromJson(Map<String, dynamic> json) {
|
||||
return UserExtra(
|
||||
money: json['money']?.toString() ?? '0.00',
|
||||
noteLimit: json['note_limit'] as int? ?? 50,
|
||||
verification: json['verification'] != null
|
||||
? UserVerification.fromJson(
|
||||
json['verification'] as Map<String, dynamic>,
|
||||
)
|
||||
: null,
|
||||
lastSigninDate: json['last_signin_date'] as String? ?? '',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user