chore: 批量代码优化与功能迭代更新

本次提交包含大量代码优化、功能新增与服务端配置更新:
1. 修复分析报告统计数据,调整CMake策略设置
2. 优化APP权限配置、编辑器与聊天界面组件
3. 更新依赖库版本与pubspec配置
4. 新增文件传输服务端、信令服务器相关配置与脚本
5. 完善用户注销功能与数据库迁移脚本
6. 优化多处动画效果、代码风格与日志输出
7. 新增多种调试与部署脚本,修复已知BUG
This commit is contained in:
Developer
2026-05-12 06:28:04 +08:00
parent 72f64f9ca9
commit 283950ea07
245 changed files with 50255 additions and 6160 deletions

View File

@@ -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? ?? '',
);
}
}