初始化
This commit is contained in:
63
bin/const/CommonVariables.dart
Normal file
63
bin/const/CommonVariables.dart
Normal 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
9
bin/const/Constants.dart
Normal 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;
|
||||
|
||||
}
|
||||
4
bin/const/HttpStatusCode.dart
Normal file
4
bin/const/HttpStatusCode.dart
Normal file
@@ -0,0 +1,4 @@
|
||||
class HttpStatusCode {
|
||||
static const int ok = 200; // 请求成功,服务器已返回请求的数据。
|
||||
static const int internalServerError = 500; // 服务器内部错误。
|
||||
}
|
||||
10
bin/const/MessageConstants.dart
Normal file
10
bin/const/MessageConstants.dart
Normal 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 = "删除成功";
|
||||
}
|
||||
13
bin/const/MessageType.dart
Normal file
13
bin/const/MessageType.dart
Normal 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);
|
||||
}
|
||||
4
bin/const/ResponseJsonCode.dart
Normal file
4
bin/const/ResponseJsonCode.dart
Normal file
@@ -0,0 +1,4 @@
|
||||
class ResponseJsonCode {
|
||||
static const int success = 200; // 操作成功
|
||||
static const int fail = 400; // 操作失败
|
||||
}
|
||||
12
bin/const/RuzhuMessageType.dart
Normal file
12
bin/const/RuzhuMessageType.dart
Normal 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);
|
||||
}
|
||||
38
bin/const/ServiceConstant.dart
Normal file
38
bin/const/ServiceConstant.dart
Normal 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;
|
||||
}
|
||||
}
|
||||
241
bin/controller/AreaController.dart
Normal file
241
bin/controller/AreaController.dart
Normal 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); // 发送失败响应
|
||||
// }
|
||||
// }
|
||||
}
|
||||
24
bin/controller/AreaController.route.dart
Normal file
24
bin/controller/AreaController.route.dart
Normal 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]
|
||||
],
|
||||
};
|
||||
80
bin/enum/ReportStatus.dart
Normal file
80
bin/enum/ReportStatus.dart
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
17
bin/handler/MqttHandler.dart
Normal file
17
bin/handler/MqttHandler.dart
Normal 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
82
bin/main.dart
Normal 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");
|
||||
}
|
||||
}
|
||||
66
bin/model/ApiResponse.dart
Normal file
66
bin/model/ApiResponse.dart
Normal 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();
|
||||
}
|
||||
}
|
||||
40
bin/model/ApiResponse.g.dart
Normal file
40
bin/model/ApiResponse.g.dart
Normal 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
37
bin/model/Area.dart
Normal 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
40
bin/model/Area.g.dart
Normal 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,
|
||||
};
|
||||
18
bin/model/WebSocketMessage.dart
Normal file
18
bin/model/WebSocketMessage.dart
Normal 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);
|
||||
}
|
||||
25
bin/model/WebSocketMessage.g.dart
Normal file
25
bin/model/WebSocketMessage.g.dart
Normal 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,
|
||||
};
|
||||
29
bin/model/api_response.dart
Normal file
29
bin/model/api_response.dart
Normal 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 原始响应对象
|
||||
);
|
||||
}
|
||||
}
|
||||
19
bin/model/app_uri_status.dart
Normal file
19
bin/model/app_uri_status.dart
Normal 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;
|
||||
}
|
||||
1606
bin/service/AreaService copy.dart
Normal file
1606
bin/service/AreaService copy.dart
Normal file
File diff suppressed because it is too large
Load Diff
1717
bin/service/AreaService.dart
Normal file
1717
bin/service/AreaService.dart
Normal file
File diff suppressed because it is too large
Load Diff
95
bin/util/MyUtils.dart
Normal file
95
bin/util/MyUtils.dart
Normal 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;
|
||||
}
|
||||
}
|
||||
102
bin/util/requestWithLog.dart
Normal file
102
bin/util/requestWithLog.dart
Normal 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';
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user