初始化

This commit is contained in:
wyf
2026-01-20 21:30:10 +08:00
commit c54f76cd0c
34 changed files with 5262 additions and 0 deletions

View File

@@ -0,0 +1,63 @@
class CommonVariables {
static bool isNetWorkOn = false;
static String supabaseUrl = "https://zhmht.swes.com.cn:3443";
// 企业微信客服拉起的url地址
// static String wxKfUrl = "https://work.weixin.qq.com/kfid/kfcab6a07e8aac68945";
static String wxKfUrl = "https://work.weixin.qq.com/kfid/kfc7d2337b9c07b1269";
// 企业微信ID
// static String wxCorpId = "wwc17348c75dbde1dc";
static String wxCorpId = "ww51feda6026280cd0";
//ICP备案号
static String ICPRightCode = "皖ICP备2024068219号-1A";
//公司名称
static String enterpriseName = "合肥眠花糖家具有限责任公司";
//备案时间
static String ICPTime = "2019-2029";
static String shoph5Url = "https://zhmht.swes.com.cn:1443";
static Map<String, Function(dynamic)> callMap = {};
static const String weather_apiKey =
'40e23445cf0a29561af2b5b7d506a38b'; // 替换为你的 API 密钥
static String shareText = "您的朋友邀请您使用《智慧眠花糖》APP请复制后面链接在浏览器中打开 " +
shoph5Url +
"/#/pages/download/download";
//容器圆角
static double filter_selector_border_radius = 50;
static double slider_container_border_radius = 10;
static double dialog_selector_border_radius = 6;
//列表数据(X秒内为刚刚数据)
static int recent_data_time = 60 * 5;
//表格间距
static int form_padding_small = 1;
static int form_padding_medium = 5;
static int form_padding_large = 8;
//内容容器最小高度百分比
static double text_height_small_percent = 0.036; //注释
static double text_height_medium_percent = 0.037; //正文
static double text_height_large_percent = 0.046; //标题/搜索栏
static double text_height_more_large_percent = 0.074; //菜单
static double icon_height_medium_percent = 0.014; //icon
static int default_page = 1;
static int default_limit_max = 999999;
static int default_limit = 10;
//下拉最大高度
static double dropdown_max_height = 200;
//详情弹窗左边字段显示宽度百分比
static double dialog_attribute_width_percent = 0.15;
static String default_gender = "1";
static bool default_vibrate = true;
static int default_weight = 65;
static int default_age = 30;
static String default_phone = "18612345678";
static int default_height = 170;
static String default_username = "眠眠";
}

9
bin/const/Constants.dart Normal file
View File

@@ -0,0 +1,9 @@
class Constants {
static const int port = 9200;
static const String serviceName = "vsbs_room";
static int default_page = 1;
static int default_limit_max = 999999;
static int default_limit = 10;
}

View File

@@ -0,0 +1,4 @@
class HttpStatusCode {
static const int ok = 200; // 请求成功,服务器已返回请求的数据。
static const int internalServerError = 500; // 服务器内部错误。
}

View File

@@ -0,0 +1,10 @@
class MessageConstants {
// 成功提示
static const String DELETE_ERROR = "删除失败,请联系管理员";
static const String UPDATE_ERROR = "更新失败,请联系管理员";
static const String ADD_ERROR = "添加失败,请联系管理员";
static const String ADD_SUCCESS = "添加成功";
static const String UPDATE_SUCCESS = "更新成功";
static const String DELETE_SUCCESS = "删除成功";
}

View File

@@ -0,0 +1,13 @@
enum MessageType {
instant_alarm("1", "实时体征消息"), // 实时体征消息
check_in("2", "入住消息"), // 入住消息
service("3", "服务消息"), // 服务消息
system("4", "系统消息"); // 系统消息
// 枚举的值
final String code; // 整数值
final String description; // 字符串描述
// 构造函数
const MessageType(this.code, this.description);
}

View File

@@ -0,0 +1,4 @@
class ResponseJsonCode {
static const int success = 200; // 操作成功
static const int fail = 400; // 操作失败
}

View File

@@ -0,0 +1,12 @@
enum RuzhuMessageType {
reservation("1", "预约消息"), // 预约消息
check_in("2", "入住消息"), // 入住消息
check_out("3", "退住消息"); // 退住消息
// 枚举的值
final String code; // 整数值
final String description; // 字符串描述
// 构造函数
const RuzhuMessageType(this.code, this.description);
}

View File

@@ -0,0 +1,38 @@
class ServiceConstant {
//基础地址
// static const String baseHost = "vsbs.he-info.cn";
// static const String baseHost = "vsbst-api.he-info.cn";
static const String baseHost = "vsbs-test.he-info.cn";
static const String apibaseHost = "songxia.he-info.com";
//服务地址
static String service_address = "https://$apibaseHost";
static String web_service_address = "http://$baseHost";
static String app_server_service = "/wx/app/bizreport/app"; //服务名称
//服务名称及api
//房间类型
//房间
static const String room_service = "/vsbs_room";
static const String room_list = "/room/roomList"; //房间列表
static const String disease_range_data = "/statistics/disease";
//日志
static String logService = "$web_service_address/vsbs_log";
//websocket网关
static const String webSocketService = "wss://$baseHost/vsbs_ws_gateway/ws";
//数据中心
static String dataCenterService = "$service_address/vsbs_data_center";
static const String sleepReportData = "/api/sleep/data/list"; //睡眠报告数据
//机构数据
static String agency_service = "$service_address/vsbs_agency"; //机构服务
static const String agency_list = "/agency/allAgencyList"; //获取机构列表
//用户中心
static String userCenterService = "$service_address/vsbs_user_center";
//添加报警
static const String addMessage = "/api/message/info";
static const String message_service = "/vsbs_message_center";
static const String message_list = "/api/message/info"; //查询消息
set serviceAddress(String host) {
service_address = host;
}
}

View File

@@ -0,0 +1,241 @@
import 'dart:convert';
import 'package:EasyDartModule/EasyDartModule.dart';
import 'package:EasyDartModule/base/webserver/WebServer.dart';
import '../const/HttpStatusCode.dart';
import '../const/MessageConstants.dart';
import '../const/ResponseJsonCode.dart';
import '../model/ApiResponse.dart';
import '../service/AreaService.dart';
part 'AreaController.route.dart';
@RequestMapping(path: "/report")
class AreaController {
final AreaService areaService = AreaService();
set callHandler(handler) => _callHandler = handler;
Map<HttpMethod, List<List>> get routeMap => routes;
AreaController();
// 获取实时数据
@RequestMapping(path: "/getInstantData", method: HttpMethod.GET,auth: false)
Future<Response> getInstantData(
Request request, Map<String, dynamic> jwt) async {
ApiResponse<List> apiResponse = ApiResponse();
try {
var queryParameters = request.requestedUri.queryParameters;
String? mac = queryParameters['mac'];
String? openId = queryParameters['openId'];
if (mac == null || mac.isEmpty) {
apiResponse.code = ResponseJsonCode.fail;
apiResponse.message = "查询失败设备mac不能为空";
return Response(
HttpStatusCode.ok,
body: apiResponse.serialize(),
);
}
if (openId == null || openId.isEmpty) {
apiResponse.code = ResponseJsonCode.fail;
apiResponse.message = "查询失败设备openId不能为空";
return Response(
HttpStatusCode.ok,
body: apiResponse.serialize(),
);
}
Map result = await areaService.getInstantData(mac,openId);
if (result['flag'] == 1) {
// 成功
// apiResponse.code = ResponseJsonCode.success;
// apiResponse.message = result['msg'] ?? "查询成功";
// apiResponse.data = result['data'];
apiResponse.code = ResponseJsonCode.success;
apiResponse.message = result['msg'] ?? "查询成功";
// 2. 将 result['data'] 包装成 List<Map<String, dynamic>>
if (result['data'] != null) {
// result['data'] 是一个 Map包装成 List
Map<String, dynamic> dataMap =
Map<String, dynamic>.from(result['data']);
// 可以在这里添加一些额外字段(可选)
dataMap['responseTime'] = DateTime.now().millisecondsSinceEpoch;
// 将单个 Map 放入 List 中
apiResponse.data = [dataMap];
} else {
apiResponse.data = [];
}
} else {
// 失败
apiResponse.code = ResponseJsonCode.fail;
apiResponse.message = result['msg'] ?? "查询失败";
apiResponse.data = null;
}
return Response(
HttpStatusCode.ok,
body: apiResponse.serialize(),
);
} catch (e) {
apiResponse.code = ResponseJsonCode.fail;
apiResponse.message = "查询失败: $e";
return Response(
HttpStatusCode.internalServerError,
body: apiResponse.serialize(),
);
}
}
// 开始体验设备
@RequestMapping(path: "/start", method: HttpMethod.POST,auth: false)
Future<Response> start(Request request) async {
ApiResponse<String> apiResponse = ApiResponse();
try {
var data = jsonDecode(await request.readAsString());
if (data == null || data.isEmpty || data['mac'] == null) {
apiResponse.code = ResponseJsonCode.fail;
apiResponse.message = "请求失败设备mac不能为空";
return Response(
HttpStatusCode.ok,
body: apiResponse.serialize(),
);
}
if (data == null || data.isEmpty || data['openId'] == null) {
apiResponse.code = ResponseJsonCode.fail;
apiResponse.message = "请求失败设备openId不能为空";
return Response(
HttpStatusCode.ok,
body: apiResponse.serialize(),
);
}
Map result = await areaService.startKuaijian(data);
if (result['flag'] == 1) {
apiResponse.code = ResponseJsonCode.success;
apiResponse.message = result['msg'] ?? MessageConstants.ADD_SUCCESS;
} else {
apiResponse.code = ResponseJsonCode.fail;
apiResponse.message = result['msg'] ?? "操作失败";
}
return Response(
HttpStatusCode.ok,
body: apiResponse.serialize(),
);
} catch (e) {
apiResponse.code = ResponseJsonCode.fail;
apiResponse.message = "添加失败: $e";
return Response(
HttpStatusCode.internalServerError,
body: apiResponse.serialize(),
);
}
}
// 结束体验设备
@RequestMapping(path: "/end", method: HttpMethod.POST,auth: false)
Future<Response> end(Request request) async {
ApiResponse<String> apiResponse = ApiResponse();
try {
var data = jsonDecode(await request.readAsString());
if (data == null || data.isEmpty || data['mac'] == null) {
apiResponse.code = ResponseJsonCode.fail;
apiResponse.message = "请求失败设备mac不能为空";
return Response(
HttpStatusCode.ok,
body: apiResponse.serialize(),
);
}
if (data == null || data.isEmpty || data['openId'] == null) {
apiResponse.code = ResponseJsonCode.fail;
apiResponse.message = "请求失败设备openId不能为空";
return Response(
HttpStatusCode.ok,
body: apiResponse.serialize(),
);
}
Map result = await areaService.endKuaijian(data);
if (result['flag'] == 1) {
apiResponse.code = ResponseJsonCode.success;
apiResponse.message = result['msg'] ?? MessageConstants.ADD_SUCCESS;
} else {
apiResponse.code = ResponseJsonCode.fail;
apiResponse.message = result['msg'] ?? "操作失败";
}
return Response(
HttpStatusCode.ok,
body: apiResponse.serialize(),
);
} catch (e) {
apiResponse.code = ResponseJsonCode.fail;
apiResponse.message = "添加失败: $e";
return Response(
HttpStatusCode.internalServerError,
body: apiResponse.serialize(),
);
}
}
// // 更新区域
// @RequestMapping(path: "/updateArea", method: HttpMethod.PUT)
// Future<Response> updateArea(Request request) async {
// ApiResponse<String> apiResponse = ApiResponse();
// try {
// var data = jsonDecode(await request.readAsString());
// var areaId = data['_id'];
// var updatedArea = Area.fromJson(data);
// if (updatedArea.id == null || updatedArea.id!.isEmpty) {
// apiResponse.code = ResponseJsonCode.fail;
// apiResponse.message = "区域ID不能为空";
// String serializedJson = apiResponse.serialize();
// return Response(HttpStatusCode.ok, body: serializedJson);
// }
// var result = await areaService.updateArea(areaId, updatedArea);
// apiResponse.code = 1;
// apiResponse.message = result;
// String serializedJson = apiResponse.serialize();
// return Response(200, body: serializedJson); // 发送成功响应
// } catch (e) {
// apiResponse.code = -1;
// apiResponse.message = "更新失败: $e"; // 包含异常信息
// String serializedJson = apiResponse.serialize();
// return Response(500, body: serializedJson); // 发送失败响应
// }
// }
// 删除区域
// @RequestMapping(path: "/deleteArea", method: HttpMethod.DELETE)
// Future<Response> deleteArea(Request request) async {
// ApiResponse<String> apiResponse = ApiResponse();
// try {
// var data = jsonDecode(await request.readAsString());
// var areaId = data['areaId'];
// var result = await areaService.deleteArea(areaId);
// apiResponse.code = 1;
// if (result.isEmpty) {
// apiResponse.code = ResponseJsonCode.success;
// apiResponse.message = MessageConstants.DELETE_SUCCESS;
// String serializedJson = apiResponse.serialize();
// return Response(HttpStatusCode.ok, body: serializedJson); // 发送成功响应
// }
// apiResponse.code = ResponseJsonCode.fail;
// apiResponse.message = result;
// String serializedJson = apiResponse.serialize();
// return Response(HttpStatusCode.ok, body: serializedJson);
// } catch (e) {
// apiResponse.code = -1;
// apiResponse.message = "删除失败: $e"; // 包含异常信息
// String serializedJson = apiResponse.serialize();
// return Response(500, body: serializedJson); // 发送失败响应
// }
// }
}

View File

@@ -0,0 +1,24 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// **************************************************************************
// RouteGenerator
// **************************************************************************
part of 'AreaController.dart';
late var _callHandler;
final Map<HttpMethod, List<List>> routes = {
HttpMethod.GET: [
[
"/report/getInstantData",
HttpResponseType.JSON,
_callHandler.getInstantData,
2,
false
]
],
HttpMethod.POST: [
["/report/start", HttpResponseType.JSON, _callHandler.start, 1, false],
["/report/end", HttpResponseType.JSON, _callHandler.end, 1, false]
],
};

View File

@@ -0,0 +1,80 @@
/// 报告状态枚举
enum ReportStatus {
experienceing, // 0 - 体验中 ok
generating, // 1 - 生成报告中 ok
appNormalClose, // 2 - APP正常关闭 ok
appAbnormalClose, // 3 - APP异常关闭 ok 可以捕获到的异常
appActiveClose, // 4 - APP主动关闭 ok
reportExceptionClose,// 5 - 报告生成异常关闭 ok
completed, // 9 - 完成
//网络断掉了怎么办todo websocket心跳 弹窗提示 微信视频结束之后要将微信标志重置 监听网络状态
//网络 蓝牙 视频播放 设备连接
//todo 监听网络状态 失败了停止播放视频
//todo 监听蓝牙状态 断掉就停止播放视频并且发送异常关闭
//todo 重新打开app
}
/// 扩展方法,提供数字映射和文本描述
extension ReportStatusExtension on ReportStatus {
/// 获取对应的数字状态值
int get value {
switch (this) {
case ReportStatus.experienceing:
return 0;
case ReportStatus.generating:
return 1;
case ReportStatus.appNormalClose:
return 2;
case ReportStatus.appAbnormalClose:
return 3;
case ReportStatus.appActiveClose:
return 4;
case ReportStatus.reportExceptionClose:
return 5;
case ReportStatus.completed:
return 9;
}
}
/// 获取文本描述
String get label {
switch (this) {
case ReportStatus.experienceing:
return "体验中";
case ReportStatus.generating:
return "生成报告中";
case ReportStatus.appNormalClose:
return "APP正常关闭";
case ReportStatus.appAbnormalClose:
return "APP异常关闭";
case ReportStatus.appActiveClose:
return "APP主动关闭";
case ReportStatus.reportExceptionClose:
return "报告生成异常关闭";
case ReportStatus.completed:
return "完成";
}
}
/// 根据数字获取枚举
static ReportStatus fromValue(int value) {
switch (value) {
case 0:
return ReportStatus.experienceing;
case 1:
return ReportStatus.generating;
case 2:
return ReportStatus.appNormalClose;
case 3:
return ReportStatus.appAbnormalClose;
case 4:
return ReportStatus.appActiveClose;
case 5:
return ReportStatus.reportExceptionClose;
case 9:
return ReportStatus.completed;
default:
throw Exception("未知报告状态: $value");
}
}
}

View File

@@ -0,0 +1,17 @@
class MqttHandler {
// 报警处理 单独线程 todo
void message(String topic, String msg) {
// print("topic: $topic, msg:$msg");
try {
// statisticsService.saveDeviceStatus(msg);
// alarmRuleService.judgeInstantAlarm(msg);
} catch (e) {
// print(e);
}
//遍历路径获取匹配的topic 进行websocket数据转发
// _topicPathHandler.forwardMessageByTopic(topic, msg);
}
}

82
bin/main.dart Normal file
View File

@@ -0,0 +1,82 @@
import 'dart:convert';
import 'dart:io';
import 'package:EasyDartModule/EasyDartModule.dart';
import 'package:EasyDartModule/base/logger/Logger.dart';
import 'package:EasyDartModule/base/redis/redis.dart';
import 'package:EasyDartModule/base/websocket/WebSocket.dart';
import './controller/AreaController.dart';
import 'const/ServiceConstant.dart';
import './const/CommonVariables.dart';
void main(List<String> args) async {
initEasyDartModule();
}
Future<void> initEasyDartModule() async {
try {
String? web = Platform.environment["web_port"] ?? "9200";
List<String> redis =
(Platform.environment["redis"] ?? "127.0.0.1:6379").split(":");
if (redis.length == 1) {
redis.add("6379");
}
EasyDartModule.init(
loggerConfig: LoggerConfig(
host: ServiceConstant.logService, serviceName: "快检报告服务"),
redisConfig: RedisConfig(host: redis[0], port: int.parse(redis[1])),
webSocketConfig:
WebSocketConfig(ServiceConstant.webSocketService, (data) {
// 接收到服务消息
var json = jsonDecode(data);
// ef.log("[websokcet]:${json}");
EasyDartModule.logger.info("[websokcet数据]:${json}");
if (json['wsId'] != null) {
// ef.kvRoot.websocketId = json['wsId'];
}
if (json['code'] != null && json['code'] != 200) {
EasyDartModule.logger
.error("[websokcet数据]:websocket连接失败--》" + json['msg']);
}
if (json["path"] != null) {
var call = CommonVariables.callMap[json["path"]];
if (call != null) {
try {
if (json['path'] != "/smartbed/connect") {
call(json["data"]);
} else {
call(json);
}
} catch (e) {
print(e);
}
} else {
print("未找到当前路径: ${json["path"]} 回调函数");
EasyDartModule.logger.error("未找到当前路径: ${json["path"]} 回调函数");
}
}
// print(data);
}, onOpen: () {
// 连接建立完毕
// EasyDartModule.websocket
// .sendData(jsonEncode({"path": "/aa/bb", "type": 1}));
print("object");
}));
while (!EasyDartModule.redis.isConnected()) {
await Future.delayed(Duration(seconds: 1));
}
// EasyDartModule.webServer.addHandler(StatisticsController());
EasyDartModule.webServer.addHandler(AreaController());
EasyDartModule.webServer.start(
int.parse(web),
);
} catch (e) {
print(e);
EasyDartModule.logger.error("websocket连接失败--》:$e");
}
}

View File

@@ -0,0 +1,66 @@
import 'dart:convert';
import 'package:json_annotation/json_annotation.dart';
import 'package:fixnum/fixnum.dart'; // 用于处理 Int64 类型
part 'ApiResponse.g.dart';
@JsonSerializable(genericArgumentFactories: true)
class ApiResponse<T> {
int? code;
int? total;
T? data;
String? message;
ApiResponse();
// JSON 反序列化
factory ApiResponse.fromJson(
Map<String, dynamic> json,
T Function(Object? json) fromJsonT,
) =>
_$ApiResponseFromJson(json, fromJsonT);
// JSON 序列化
Map<String, dynamic> toJson(Object? Function(T value) toJsonT) =>
_$ApiResponseToJson(this, toJsonT);
// 添加自定义的 toJson 序列化方法,确保能正确序列化泛型数据
String serialize() {
// 手动处理 data 中的 Int64 转换为 int
var serializedData = _serializeData(data);
return jsonEncode({
'code': code,
'total': total,
'data': serializedData,
'message': message,
});
}
// 递归处理 data 中的每个项,转换 Int64 为 int
dynamic _serializeData(dynamic data) {
if (data is List) {
// 处理 List 中的 Int64 类型
return data.map((e) => _serializeData(e)).toList();
} else if (data is Map) {
// 处理 Map 中的 Int64 类型
var map = Map<String, dynamic>.from(data);
map.forEach((key, value) {
if (value is Int64) {
map[key] = value.toInt();
} else {
map[key] = _serializeData(value);
}
});
return map;
} else if (data is Int64) {
// 如果是 Int64 类型,转换为 int
return data.toInt();
}
return data;
}
@override
String toString() {
return serialize();
}
}

View File

@@ -0,0 +1,40 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'ApiResponse.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
ApiResponse<T> _$ApiResponseFromJson<T>(
Map<String, dynamic> json,
T Function(Object? json) fromJsonT,
) =>
ApiResponse<T>()
..code = (json['code'] as num?)?.toInt()
..total = (json['total'] as num?)?.toInt()
..data = _$nullableGenericFromJson(json['data'], fromJsonT)
..message = json['message'] as String?;
Map<String, dynamic> _$ApiResponseToJson<T>(
ApiResponse<T> instance,
Object? Function(T value) toJsonT,
) =>
<String, dynamic>{
'code': instance.code,
'total': instance.total,
'data': _$nullableGenericToJson(instance.data, toJsonT),
'message': instance.message,
};
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);

37
bin/model/Area.dart Normal file
View File

@@ -0,0 +1,37 @@
import 'package:json_annotation/json_annotation.dart';
part 'Area.g.dart';
@JsonSerializable()
class Area {
@JsonKey(name: '_id')
String? id; // 区域id
String? area_name; // 区域名称
String? area_desc; // 区域描述
int? created_at; // 创建时间(毫秒)
int? updated_at; // 更新时间(毫秒)
String? created_by_id; // 创建人ID
String? created_by_name; // 创建人名称
String? updated_by_id; // 更新人ID
String? updated_by_name; // 更新人名称
String? oid; // 机构ID
int? deleted; // 是否删除
String? points; // 坐标点集合
String? tid; // 所属机构
int? level; // 权限等级
Area();
static Area fromJson(Map<String, dynamic> json) => _$AreaFromJson(json);
Map<String, dynamic> toJson() => _$AreaToJson(this);
// 使用查询参数填充 Area 对象
static Area fromQueryParameters(Map<String, String> queryParameters, Map<String, dynamic> jwt) {
var json = <String, dynamic>{};
queryParameters.forEach((key, value) {
json[key] = value;
});
json['tid'] = jwt['tid'];
json['level'] = jwt['level'];
return Area.fromJson(json);
}
}

40
bin/model/Area.g.dart Normal file
View File

@@ -0,0 +1,40 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'Area.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
Area _$AreaFromJson(Map<String, dynamic> json) => Area()
..id = json['_id'] as String?
..area_name = json['area_name'] as String?
..area_desc = json['area_desc'] as String?
..created_at = (json['created_at'] as num?)?.toInt()
..updated_at = (json['updated_at'] as num?)?.toInt()
..created_by_id = json['created_by_id'] as String?
..created_by_name = json['created_by_name'] as String?
..updated_by_id = json['updated_by_id'] as String?
..updated_by_name = json['updated_by_name'] as String?
..oid = json['oid'] as String?
..deleted = (json['deleted'] as num?)?.toInt()
..points = json['points'] as String?
..tid = json['tid'] as String?
..level = (json['level'] as num?)?.toInt();
Map<String, dynamic> _$AreaToJson(Area instance) => <String, dynamic>{
'_id': instance.id,
'area_name': instance.area_name,
'area_desc': instance.area_desc,
'created_at': instance.created_at,
'updated_at': instance.updated_at,
'created_by_id': instance.created_by_id,
'created_by_name': instance.created_by_name,
'updated_by_id': instance.updated_by_id,
'updated_by_name': instance.updated_by_name,
'oid': instance.oid,
'deleted': instance.deleted,
'points': instance.points,
'tid': instance.tid,
'level': instance.level,
};

View File

@@ -0,0 +1,18 @@
import 'package:json_annotation/json_annotation.dart';
part 'WebSocketMessage.g.dart';
@JsonSerializable()
class WebSocketMessage {
String path;
int? type;
dynamic data;
String? to;
String? mac;
WebSocketMessage({required this.path, this.type, this.data, this.to,this.mac});
static WebSocketMessage fromJson(Map<String, dynamic> json) =>
_$WebSocketMessageFromJson(json);
Map<String, dynamic> toJson() => _$WebSocketMessageToJson(this);
}

View File

@@ -0,0 +1,25 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'WebSocketMessage.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
WebSocketMessage _$WebSocketMessageFromJson(Map<String, dynamic> json) =>
WebSocketMessage(
path: json['path'] as String,
type: (json['type'] as num?)?.toInt(),
data: json['data'],
to: json['to'] as String?,
mac: json['mac'] as String?,
);
Map<String, dynamic> _$WebSocketMessageToJson(WebSocketMessage instance) =>
<String, dynamic>{
'path': instance.path,
'type': instance.type,
'data': instance.data,
'to': instance.to,
'mac': instance.mac,
};

View File

@@ -0,0 +1,29 @@
class ApiResponse<T> {
int? code;
T? data;
String? msg;
int? total;
dynamic rawResponse; // 原始 Dio 响应对象
ApiResponse({
required this.code,
this.data,
this.msg,
this.total,
this.rawResponse,
});
factory ApiResponse.fromJson(
Map<String, dynamic> json,
T Function(Object?) fromJsonT, {
dynamic rawResponse,
}) {
return ApiResponse<T>(
code: json['code'] as int?,
data: json['data'] != null ? fromJsonT(json['data']) : null,
msg: json['msg'] as String?,
total: json['total'] as int?,
rawResponse: rawResponse, // 保留 Dio 原始响应对象
);
}
}

View File

@@ -0,0 +1,19 @@
// lib/http_status_codes.dart
class HttpStatusCodes {
// Success codes
static const int ok = 200;
static const int created = 201;
static const int accepted = 202;
// Client error codes
static const int badRequest = 400;
static const int unauthorized = 401;//401 参数错误
static const int forbidden = 403;//403 禁止,多条数据,不允许修改
static const int notFound = 404;//404 没有报告
// Server error codes
static const int internalServerError = 500;//500 内部异常
static const int notImplemented = 501;
static const int serviceUnavailable = 503;
}

File diff suppressed because it is too large Load Diff

1717
bin/service/AreaService.dart Normal file

File diff suppressed because it is too large Load Diff

95
bin/util/MyUtils.dart Normal file
View File

@@ -0,0 +1,95 @@
import '../model/api_response.dart';
import '../model/app_uri_status.dart';
class MyUtils {
static ApiResponse formatResponse(
ApiResponse res,
String successMsg,
String errorMsg,
) {
if (res.code == HttpStatusCodes.ok) {
// 成功但 msg 为空时填默认成功提示
if (res.msg == null || res.msg!.isEmpty) {
res.msg = successMsg;
}
} else {
// 失败且 msg 为空时填默认失败提示
if (res.msg == null || res.msg!.isEmpty) {
res.msg = errorMsg;
}
}
return res;
}
// 获取最近24小时的开始时间的毫秒数
static int getStartOfLast24HoursMilliseconds() {
DateTime now = DateTime.now();
DateTime startOfLast24Hours = now.subtract(Duration(hours: 24));
return startOfLast24Hours.millisecondsSinceEpoch;
}
// 获取当前时间的毫秒数作为最近24小时的结束时间
static int getEndOfLast24HoursMilliseconds() {
DateTime now = DateTime.now();
return now.millisecondsSinceEpoch;
}
static int getStartRangeFromNDaysAgoToNextDay(int n) {
DateTime now = DateTime.now();
DateTime start = DateTime(now.year, now.month, now.day - n - 1, 18, 0, 0);
DateTime end = start.add(Duration(hours: 24));
return start.millisecondsSinceEpoch;
}
static int getEndRangeFromNDaysAgoToNextDay(int n) {
DateTime now = DateTime.now();
DateTime start = DateTime(now.year, now.month, now.day - n - 1, 18, 0, 0);
DateTime end = start.add(Duration(hours: 24));
return end.millisecondsSinceEpoch;
}
// 获取当天前一天的下午18:00的时间戳
static int getYesterday18Milliseconds() {
DateTime now = DateTime.now();
DateTime yesterday18 = DateTime(now.year, now.month, now.day - 1, 18, 0, 0);
return yesterday18.millisecondsSinceEpoch;
}
// 获取当天17:00的时间戳
static int getToday17Milliseconds() {
DateTime now = DateTime.now();
DateTime today17 = DateTime(now.year, now.month, now.day, 17, 0, 0);
return today17.millisecondsSinceEpoch;
}
// 获取前一天的开始时间戳前一天的00:00:00
static int getStartOfYesterdayMilliseconds() {
DateTime now = DateTime.now();
DateTime startOfYesterday =
DateTime(now.year, now.month, now.day - 1, 0, 0, 0);
return startOfYesterday.millisecondsSinceEpoch;
}
// 获取前一天的结束时间戳前一天的23:59:59
static int getEndOfYesterdayMilliseconds() {
DateTime now = DateTime.now();
DateTime endOfYesterday =
DateTime(now.year, now.month, now.day - 1, 23, 59, 59);
return endOfYesterday.millisecondsSinceEpoch;
}
// 获取前一天的开始时间戳前一天的00:00:00
static int getStartOfCurrentMilliseconds() {
DateTime now = DateTime.now();
DateTime startOfYesterday = DateTime(now.year, now.month, now.day, 0, 0, 0);
return startOfYesterday.millisecondsSinceEpoch;
}
// 获取前一天的结束时间戳前一天的23:59:59
static int getEndOfCurrentMilliseconds() {
DateTime now = DateTime.now();
DateTime endOfYesterday =
DateTime(now.year, now.month, now.day, 23, 59, 59);
return endOfYesterday.millisecondsSinceEpoch;
}
}

View File

@@ -0,0 +1,102 @@
import 'dart:convert';
import 'package:EasyDartModule/EasyDartModule.dart';
import '../model/api_response.dart';
import '../model/app_uri_status.dart';
import '../util/MyUtils.dart';
Future<ApiResponse> requestWithLog({
required String logTitle,
required MyHttpMethod method,
required String queryUrl,
Map<String, dynamic>? data,
String successMsg = "操作成功",
String errorMsg = "操作失败",
void Function(ApiResponse res)? onSuccess,
void Function(ApiResponse res)? onFailure,
}) async {
EasyDartModule.logger.info(logTitle);
ApiResponse apiResponse = ApiResponse(code: -1, msg: "请求失败");
try {
String? language = "";
if (language != null && language.isNotEmpty) {
if (queryUrl.contains("?")) {
queryUrl += "&lang=$language";
} else {
queryUrl += "?lang=$language";
}
}
successMsg = successMsg;
errorMsg = errorMsg;
var response;
switch (method) {
case MyHttpMethod.get:
response = await EasyDartModule.dio.get(queryUrl);
break;
case MyHttpMethod.post:
response = data != null
? await EasyDartModule.dio.post(queryUrl, data: jsonEncode(data))
: await EasyDartModule.dio.post(queryUrl);
break;
case MyHttpMethod.put:
response = data != null
? await EasyDartModule.dio.put(queryUrl, data: jsonEncode(data))
: await EasyDartModule.dio.put(queryUrl);
break;
case MyHttpMethod.delete:
response = data != null
? await EasyDartModule.dio.delete(queryUrl, data: jsonEncode(data))
: await EasyDartModule.dio.delete(queryUrl);
break;
}
if (response != null) {
final responseData =
response.data is String ? jsonDecode(response.data) : response.data;
apiResponse = ApiResponse.fromJson(responseData, (object) => object,
rawResponse: response);
if (apiResponse.code == HttpStatusCodes.ok || apiResponse.code == 20000) {
MyUtils.formatResponse(apiResponse, successMsg, errorMsg);
onSuccess?.call(apiResponse);
} else {
print("[网络请求失败:$response]");
apiResponse.msg = responseData['msg'] ?? errorMsg;
onFailure?.call(apiResponse);
}
return apiResponse;
} else {
apiResponse = ApiResponse(code: -1, msg: "失败");
onFailure?.call(apiResponse);
return apiResponse;
}
} catch (e) {
print("[网络请求异常:$e]");
EasyDartModule.logger.error("$logTitle 失败->$e");
onFailure?.call(apiResponse);
return apiResponse;
}
}
enum MyHttpMethod { get, post, put, delete }
extension HttpMethodExtension on MyHttpMethod {
String get name {
switch (this) {
case MyHttpMethod.get:
return 'GET';
case MyHttpMethod.post:
return 'POST';
case MyHttpMethod.put:
return 'PUT';
case MyHttpMethod.delete:
return 'DELETE';
}
}
}