feat: 完成智能电网电工端 Flutter 应用初始化

创建完整的 Flutter 项目结构,包含 Android 和 iOS 平台配置、核心网络层、路由、状态管理及业务模块(订单、收益、认证),适配原 uni-app 项目功能逻辑
This commit is contained in:
andyesfly committed 2026-10-06 11:54:10 +08:00
commit 56830e94ec
108 files changed
+9272

No files matched your search

+58
View File
@@ -0,0 +1,58 @@
import '../../../core/network/api_client.dart';
import '../../../core/network/api_response.dart';
import 'auth_models.dart';
/// 认证与个人资料接口,对应后端 `/api/worker-app/auth/*` 与 `/profile`。
class AuthApi {
AuthApi(this._client);
final ApiClient _client;
Future<ApiResponse<LoginResult>> login({
required String phone,
required String password,
}) => _client.post<LoginResult>(
'/worker-app/auth/login',
body: {'phone': phone, 'password': password},
parse: (d) => LoginResult.fromJson((d as Map).cast<String, dynamic>()),
needAuth: false,
);
Future<ApiResponse<WorkerInfo>> register({
required String workerName,
required String phone,
required String password,
String? idCard,
String? workerTitle,
}) => _client.post<WorkerInfo>(
'/worker-app/auth/register',
body: {
'workerName': workerName,
'phone': phone,
'password': password,
if (idCard != null && idCard.isNotEmpty) 'idCard': idCard,
if (workerTitle != null && workerTitle.isNotEmpty) 'workerTitle': workerTitle,
},
parse: (d) => WorkerInfo.fromJson((d as Map).cast<String, dynamic>()),
needAuth: false,
);
Future<ApiResponse<WorkerProfile>> profile() => _client.get<WorkerProfile>(
'/worker-app/profile',
parse: (d) => WorkerProfile.fromJson((d as Map).cast<String, dynamic>()),
);
Future<ApiResponse<WorkerInfo>> updateProfile({
String? workerName,
String? idCard,
String? workerTitle,
}) => _client.put<WorkerInfo>(
'/worker-app/profile',
body: {
'workerName': ?workerName,
'idCard': ?idCard,
'workerTitle': ?workerTitle,
},
parse: (d) => WorkerInfo.fromJson((d as Map).cast<String, dynamic>()),
);
}
+151
View File
@@ -0,0 +1,151 @@
import '../../../core/utils/id_util.dart';
/// 电工基础信息,对应后端 `WorkerAppService.basicInfo()`。
class WorkerInfo {
const WorkerInfo({
required this.id,
required this.workerName,
required this.phone,
required this.workerTitle,
required this.auditStatus,
required this.status,
required this.rating,
required this.completedCount,
});
final int id;
final String workerName;
final String phone;
final String workerTitle;
/// 审核状态:0 待审核 / 1 已通过 / 2 已驳回
final int auditStatus;
/// 在职状态:0 离职 / 1 在职
final int status;
final double rating;
final int completedCount;
String get displayName => workerName.isNotEmpty ? workerName : phone;
/// 头像占位文字:取显示名首个字符(按 Unicode 码点截取,兼容中文)。
String get avatarText =>
displayName.isEmpty ? '电' : String.fromCharCode(displayName.runes.first);
bool get isApproved => auditStatus == 1;
String get auditStatusText => switch (auditStatus) {
0 => '待审核',
1 => '已通过',
2 => '已驳回',
_ => '未知',
};
factory WorkerInfo.fromJson(Map<String, dynamic> json) => WorkerInfo(
id: toIntOr(json['id'], 0),
workerName: json['workerName'] as String? ?? '',
phone: json['phone'] as String? ?? '',
workerTitle: json['workerTitle'] as String? ?? '',
auditStatus: toIntOr(json['auditStatus'], 0),
status: toIntOr(json['status'], 0),
rating: toDoubleOr(json['rating'], 5),
completedCount: toIntOr(json['completedCount'], 0),
);
Map<String, dynamic> toJson() => {
'id': id,
'workerName': workerName,
'phone': phone,
'workerTitle': workerTitle,
'auditStatus': auditStatus,
'status': status,
'rating': rating,
'completedCount': completedCount,
};
}
/// 登录返回体。
class LoginResult {
const LoginResult({required this.token, required this.workerInfo});
final String token;
final WorkerInfo workerInfo;
factory LoginResult.fromJson(Map<String, dynamic> json) => LoginResult(
token: json['token'] as String? ?? '',
workerInfo: WorkerInfo.fromJson(
(json['workerInfo'] as Map?)?.cast<String, dynamic>() ?? const {},
),
);
}
/// 电工资质证照,对应 `worker_cert` 表。
class CertInfo {
const CertInfo({
required this.id,
required this.certType,
required this.certNo,
required this.issueAuthority,
required this.issueDate,
required this.expireDate,
required this.certImageUrl,
required this.status,
});
final int id;
final String certType;
final String certNo;
final String issueAuthority;
final String issueDate;
final String expireDate;
final String certImageUrl;
/// 有效期状态:0 正常 / 1 即将到期 / 2 已过期
final int status;
factory CertInfo.fromJson(Map<String, dynamic> json) => CertInfo(
id: toIntOr(json['id'], 0),
certType: json['certType'] as String? ?? '',
certNo: json['certNo'] as String? ?? '',
issueAuthority: json['issueAuthority'] as String? ?? '',
issueDate: json['issueDate'] as String? ?? '',
expireDate: json['expireDate'] as String? ?? '',
certImageUrl: json['certImageUrl'] as String? ?? '',
status: toIntOr(json['status'], 0),
);
}
/// 个人资料,对应 `GET /api/worker-app/profile`。
class WorkerProfile {
const WorkerProfile({
required this.basic,
required this.idCard,
required this.auditRemark,
required this.certStatus,
required this.certs,
});
final WorkerInfo basic;
final String idCard;
final String auditRemark;
/// 资质汇总状态:none / valid / expiring / expired
final String certStatus;
final List<CertInfo> certs;
/// 「我的」页证书区取首张证书展示(源页面只展示一张「电工职业资格证」)。
CertInfo? get primaryCert => certs.isEmpty ? null : certs.first;
factory WorkerProfile.fromJson(Map<String, dynamic> json) => WorkerProfile(
basic: WorkerInfo.fromJson(json),
idCard: json['idCard'] as String? ?? '',
auditRemark: json['auditRemark'] as String? ?? '',
certStatus: json['certStatus'] as String? ?? 'none',
certs:
(json['certs'] as List?)
?.map((e) => CertInfo.fromJson((e as Map).cast<String, dynamic>()))
.toList() ??
const [],
);
}