510 lines
14 KiB
Dart
510 lines
14 KiB
Dart
import 'dart:async';
|
|
import 'dart:convert';
|
|
import 'package:http/http.dart' as http;
|
|
import 'package:lamiter/Class/Diagnosis/diagnosis.dart';
|
|
import 'package:lamiter/Class/Form/constitution_form.dart';
|
|
import 'package:lamiter/Class/Form/posture_issue_form.dart';
|
|
import 'package:lamiter/Class/Result/constitution_result.dart';
|
|
import 'package:lamiter/Class/Result/posture_issue_result.dart';
|
|
import 'package:lamiter/Class/User/client.dart';
|
|
|
|
class API {
|
|
final app_server_ip = 'http://139.227.101.187:7723';
|
|
// 'http://127.0.0.1:3000';
|
|
final constitution_model_ip = 'http://211.22.135.143:7600';
|
|
final posture_issue_model_ip = 'http://211.22.135.143:8202';
|
|
|
|
Future<Map<String, dynamic>> _GET(String uri) async {
|
|
try {
|
|
final response = await http.get(
|
|
Uri.parse(uri),
|
|
headers: <String, String>{
|
|
'Content-Type': 'application/json; charset=UTF-8',
|
|
},
|
|
);
|
|
return jsonDecode(response.body) as Map<String, dynamic>;
|
|
} catch (e) {
|
|
/*伺服器異常*/
|
|
print(e.toString());
|
|
}
|
|
return {'errorMessage': '無法連線伺服器。請稍後重試,或聯繫開發人員。'};
|
|
}
|
|
|
|
Future<Map<String, dynamic>> _POST(String uri, Object? body) async {
|
|
try {
|
|
final response = await http.post(
|
|
Uri.parse(uri),
|
|
headers: <String, String>{
|
|
'Content-Type': 'application/json; charset=UTF-8',
|
|
},
|
|
body: body,
|
|
);
|
|
return jsonDecode(response.body) as Map<String, dynamic>;
|
|
} catch (e) {
|
|
/*伺服器異常*/
|
|
print(e.toString());
|
|
}
|
|
return {'errorMessage': '無法連線伺服器。請稍後重試,或聯繫開發人員。'};
|
|
}
|
|
|
|
// 獲取封面照
|
|
Future<Map<String, dynamic>> get_lamiter_image() async {
|
|
return await _GET(
|
|
'$app_server_ip/get_lamiter_image',
|
|
);
|
|
}
|
|
|
|
// 獲取logo
|
|
Future<Map<String, dynamic>> get_lamiter_logo() async {
|
|
return await _GET(
|
|
'$app_server_ip/get_lamiter_logo',
|
|
);
|
|
}
|
|
|
|
// 最大可新增客戶數量
|
|
Future<Map<String, dynamic>> get_client_max_number(
|
|
String managerId,
|
|
) async {
|
|
return await _POST(
|
|
'$app_server_ip/get_client_max_number',
|
|
jsonEncode(<String, String?>{
|
|
'managerId': managerId,
|
|
}),
|
|
);
|
|
}
|
|
|
|
// 登入
|
|
Future<Map<String, dynamic>> login(
|
|
String account,
|
|
String password,
|
|
) async {
|
|
return await _POST(
|
|
'$app_server_ip/login',
|
|
jsonEncode(<String, String?>{
|
|
'account': account,
|
|
'password': password,
|
|
}),
|
|
);
|
|
}
|
|
|
|
// 取得所有客戶(按照最近更新時間排列)
|
|
Future<Map<String, dynamic>> get_clients(String managerId) async {
|
|
return await _POST(
|
|
'$app_server_ip/get_clients',
|
|
jsonEncode(<String, String?>{
|
|
'managerId': managerId,
|
|
}),
|
|
);
|
|
}
|
|
|
|
// 取得客戶(用於即時更新用戶主頁)
|
|
Future<Map<String, dynamic>> get_client(String clientId) async {
|
|
return await _POST(
|
|
'$app_server_ip/get_client',
|
|
jsonEncode(<String, String?>{
|
|
'clientId': clientId,
|
|
}),
|
|
);
|
|
}
|
|
|
|
// 新增客戶
|
|
Future<Map<String, dynamic>> create_client(
|
|
String managerId,
|
|
Client client,
|
|
) async {
|
|
return await _POST(
|
|
'$app_server_ip/create_client',
|
|
jsonEncode(<String, dynamic>{
|
|
'managerId': managerId,
|
|
'clientJson': client.toJson(),
|
|
}),
|
|
);
|
|
}
|
|
|
|
// 刪除客戶
|
|
Future<Map<String, dynamic>> delete_client(
|
|
String managerId,
|
|
String clientId,
|
|
) async {
|
|
return await _POST(
|
|
'$app_server_ip/delete_client',
|
|
jsonEncode(<String, String?>{
|
|
'managerId': managerId,
|
|
'clientId': clientId,
|
|
}),
|
|
);
|
|
}
|
|
|
|
// 更新客戶
|
|
Future<Map<String, dynamic>> update_client(
|
|
String managerId,
|
|
Client client,
|
|
) async {
|
|
return await _POST(
|
|
'$app_server_ip/update_client',
|
|
jsonEncode(<String, dynamic>{
|
|
'managerId': managerId,
|
|
'clientJson': client.toJson(),
|
|
}),
|
|
);
|
|
}
|
|
|
|
// 新增診斷
|
|
Future<Map<String, dynamic>> create_diagnosis(Diagnosis diagnosis) async {
|
|
return await _POST(
|
|
'$app_server_ip/create_diagnosis',
|
|
jsonEncode(<String, dynamic>{
|
|
'diagnosisJson': diagnosis.toJson(),
|
|
}),
|
|
);
|
|
}
|
|
|
|
// 取得診斷
|
|
Future<Map<String, dynamic>> get_diagnoses(String clientId) async {
|
|
return await _POST(
|
|
'$app_server_ip/get_diagnoses',
|
|
jsonEncode(<String, String?>{'clientId': clientId}),
|
|
);
|
|
}
|
|
|
|
// 創建客戶表格
|
|
Future<Map<String, dynamic>> get_create_client_form() async {
|
|
return await _GET('$app_server_ip/get_create_client_form');
|
|
}
|
|
|
|
// 診斷問卷
|
|
Future<Map<String, dynamic>> get_health_index_form() async {
|
|
return await _GET('$app_server_ip/get_health_index_form');
|
|
}
|
|
|
|
Future<Map<String, dynamic>> get_physical_index_form() async {
|
|
return await _GET('$app_server_ip/get_physical_index_form');
|
|
}
|
|
|
|
Future<Map<String, dynamic>> get_urban_disease_form() async {
|
|
return await _GET('$app_server_ip/get_urban_disease_form');
|
|
}
|
|
|
|
Future<Map<String, dynamic>> get_stress_index_form() async {
|
|
return await _GET('$app_server_ip/get_stress_index_form');
|
|
}
|
|
|
|
Future<Map<String, dynamic>> get_sleep_well_index_form() async {
|
|
return await _GET('$app_server_ip/get_sleep_well_index_form');
|
|
}
|
|
|
|
Future<Map<String, dynamic>> get_constitution_form() async {
|
|
return await _GET('$app_server_ip/get_constitution_form');
|
|
}
|
|
|
|
Future<Map<String, dynamic>> get_zong_fu_index_form() async {
|
|
return await _GET('$app_server_ip/get_zong_fu_index_form');
|
|
}
|
|
|
|
Future<Map<String, dynamic>> get_posture_issue_form() async {
|
|
return await _GET('$app_server_ip/get_posture_issue_form');
|
|
}
|
|
|
|
// 體質
|
|
Future<Map<String, dynamic>> get_constitutions() async {
|
|
return await _GET('$app_server_ip/get_constitutions');
|
|
}
|
|
|
|
// Future<Map<String, dynamic>> get_constitution(String constitutionId) async {
|
|
// return await _POST(
|
|
// '$app_server_ip/get_constitution',
|
|
// jsonEncode(<String, String?>{
|
|
// 'constitutionId': constitutionId,
|
|
// }),
|
|
// );
|
|
// }
|
|
|
|
// 臟腑
|
|
Future<Map<String, dynamic>> get_zong_fu_organs() async {
|
|
return await _GET('$app_server_ip/get_zong_fu_organs');
|
|
}
|
|
|
|
// 體態
|
|
Future<Map<String, dynamic>> get_posture_issues() async {
|
|
return await _GET('$app_server_ip/get_posture_issues');
|
|
}
|
|
|
|
// 體態症狀
|
|
Future<Map<String, dynamic>> get_symptoms() async {
|
|
return await _GET('$app_server_ip/get_symptoms');
|
|
}
|
|
|
|
// 都會疾病
|
|
Future<Map<String, dynamic>> get_urban_diseases() async {
|
|
return await _GET('$app_server_ip/get_urban_diseases');
|
|
}
|
|
|
|
Future<Map<String, dynamic>> get_urban_disease_image(
|
|
String urbanDiseaseId,
|
|
) async {
|
|
return await _POST(
|
|
'$app_server_ip/get_urban_disease_image',
|
|
jsonEncode(<String, String?>{
|
|
'urbanDiseaseId': urbanDiseaseId,
|
|
}),
|
|
);
|
|
}
|
|
|
|
Future<Map<String, dynamic>> get_urban_disease_zh_image(
|
|
String urbanDiseaseId,
|
|
) async {
|
|
return await _POST(
|
|
'$app_server_ip/get_urban_disease_zh_image',
|
|
jsonEncode(<String, String?>{
|
|
'urbanDiseaseId': urbanDiseaseId,
|
|
}),
|
|
);
|
|
}
|
|
|
|
// 經絡穴位系統
|
|
Future<Map<String, dynamic>> get_constitution_meridian_network(
|
|
String constitutionId,
|
|
List<String> zongFuOrgansIds,
|
|
) async {
|
|
return await _POST(
|
|
'$app_server_ip/get_constitution_meridian_network',
|
|
jsonEncode(<String, dynamic>{
|
|
'constitutionId': constitutionId,
|
|
'zongFuOrgansIds': zongFuOrgansIds,
|
|
}),
|
|
);
|
|
}
|
|
|
|
Future<Map<String, dynamic>> get_body_parts(
|
|
List<String> postureIssuesIds,
|
|
) async {
|
|
return await _POST(
|
|
'$app_server_ip/get_body_parts',
|
|
jsonEncode(<String, dynamic>{
|
|
'postureIssuesIds': postureIssuesIds,
|
|
}),
|
|
);
|
|
}
|
|
|
|
Future<Map<String, dynamic>> get_body_issues(
|
|
List<String> bodyIssuesIds,
|
|
) async {
|
|
return await _POST(
|
|
'$app_server_ip/get_body_issues',
|
|
jsonEncode(<String, dynamic>{
|
|
'bodyIssuesIds': bodyIssuesIds,
|
|
}),
|
|
);
|
|
}
|
|
|
|
Future<Map<String, dynamic>> get_acupoint(String acupointId) async {
|
|
return await _POST(
|
|
'$app_server_ip/get_acupoint',
|
|
jsonEncode(<String, dynamic>{
|
|
'acupointId': acupointId,
|
|
}),
|
|
);
|
|
}
|
|
|
|
Future<Map<String, dynamic>> get_acupoint_image(String acupointId) async {
|
|
return await _POST(
|
|
'$app_server_ip/get_acupoint_image',
|
|
jsonEncode(<String, dynamic>{
|
|
'acupointId': acupointId,
|
|
}),
|
|
);
|
|
}
|
|
|
|
Future<Map<String, dynamic>> get_meridian(String meridianId) async {
|
|
return await _POST(
|
|
'$app_server_ip/get_meridian',
|
|
jsonEncode(<String, dynamic>{
|
|
'meridianId': meridianId,
|
|
}),
|
|
);
|
|
}
|
|
|
|
Future<Map<String, dynamic>> get_meridian_image(String meridianId) async {
|
|
return await _POST(
|
|
'$app_server_ip/get_meridian_image',
|
|
jsonEncode(<String, dynamic>{
|
|
'meridianId': meridianId,
|
|
}),
|
|
);
|
|
}
|
|
|
|
// 節氣食譜
|
|
Future<Map<String, dynamic>> get_seasonal_recipe(
|
|
String constitutionId,
|
|
String season,
|
|
) async {
|
|
return await _POST(
|
|
'$app_server_ip/get_seasonal_recipe',
|
|
jsonEncode(<String, dynamic>{
|
|
'constitutionId': constitutionId,
|
|
'season': season,
|
|
}),
|
|
);
|
|
}
|
|
|
|
// 院所鏈接
|
|
Future<Map<String, dynamic>> get_medical_facilities(String managerId) async {
|
|
return await _POST(
|
|
'$app_server_ip/get_medical_facilities',
|
|
jsonEncode(<String, dynamic>{'managerId': managerId}),
|
|
);
|
|
}
|
|
|
|
// 配對產品
|
|
Future<Map<String, dynamic>> get_products(String managerId) async {
|
|
return await _POST(
|
|
'$app_server_ip/get_products',
|
|
jsonEncode(<String, dynamic>{'managerId': managerId}),
|
|
);
|
|
}
|
|
|
|
Future<Map<String, dynamic>> get_treatments(String managerId) async {
|
|
return await _POST(
|
|
'$app_server_ip/get_treatments',
|
|
jsonEncode(<String, dynamic>{'managerId': managerId}),
|
|
);
|
|
}
|
|
|
|
Future<Map<String, dynamic>> get_courses(String managerId) async {
|
|
return await _POST(
|
|
'$app_server_ip/get_courses',
|
|
jsonEncode(<String, dynamic>{'managerId': managerId}),
|
|
);
|
|
}
|
|
|
|
Future<Map<String, dynamic>> create_usage_time(
|
|
String managerId, DateTime startTime, DateTime endTime) async {
|
|
return await _POST(
|
|
'$app_server_ip/create_usage_time',
|
|
jsonEncode(<String, dynamic>{
|
|
'managerId': managerId,
|
|
'usageTimeJson': {
|
|
'startTime': startTime.toUtc().toIso8601String(),
|
|
'endTime': endTime.toUtc().toIso8601String(),
|
|
}
|
|
}),
|
|
);
|
|
}
|
|
|
|
// 體質體態模型
|
|
Future<ConstitutionResult?> constitution_analysis(
|
|
ConstitutionForm form) async {
|
|
if (form.tongueImage == null) return null;
|
|
String? image_id = await _submit_image(
|
|
'$constitution_model_ip/api/Tongue_Analysis',
|
|
form.tongueImage,
|
|
);
|
|
if (image_id == null) return null;
|
|
final result = await _analysis(
|
|
'$constitution_model_ip/api/Tongue_Analysis_Result',
|
|
jsonEncode(<String, String>{
|
|
'image_id': image_id,
|
|
}));
|
|
if (result == null) return null;
|
|
return ConstitutionResult.fromJson(result);
|
|
}
|
|
|
|
Future<PostureIssueResult?> posture_issue_analysis(
|
|
PostureIssueForm form) async {
|
|
// TODO API需要可以確認現在圖片的分析狀態
|
|
if (form.frontViewImage == null && form.sideViewImage == null) return null;
|
|
String? front_view_image_id, side_view_image_id;
|
|
if (form.frontViewImage != null) {
|
|
front_view_image_id = await _submit_image(
|
|
'$posture_issue_model_ip/api/Posture_Analysis_Front_View',
|
|
form.frontViewImage,
|
|
);
|
|
}
|
|
if (form.sideViewImage != null) {
|
|
side_view_image_id = await _submit_image(
|
|
'$posture_issue_model_ip/api/Posture_Analysis_Side_View',
|
|
form.sideViewImage,
|
|
);
|
|
}
|
|
if (front_view_image_id == null && side_view_image_id == null) return null;
|
|
if (front_view_image_id != null) {
|
|
final frontViewResult = await _analysis(
|
|
'$posture_issue_model_ip/api/Posture_Analysis_Result',
|
|
jsonEncode(<String, String?>{
|
|
'front_view_image_id': front_view_image_id,
|
|
'side_view_image_id': null
|
|
}));
|
|
if (frontViewResult == null) return null;
|
|
}
|
|
if (side_view_image_id != null) {
|
|
final sideViewResult = await _analysis(
|
|
'$posture_issue_model_ip/api/Posture_Analysis_Result',
|
|
jsonEncode(<String, String?>{
|
|
'front_view_image_id': null,
|
|
'side_view_image_id': side_view_image_id
|
|
}));
|
|
if (sideViewResult == null) return null;
|
|
}
|
|
final result = await _analysis(
|
|
'$posture_issue_model_ip/api/Posture_Analysis_Result',
|
|
jsonEncode(<String, String?>{
|
|
'front_view_image_id': front_view_image_id,
|
|
'side_view_image_id': side_view_image_id
|
|
}));
|
|
if (result == null) return null;
|
|
return PostureIssueResult.fromJson(result);
|
|
}
|
|
|
|
Future<String?> _submit_image(String uri, String? img64) async {
|
|
final response = await http.post(
|
|
Uri.parse(uri),
|
|
headers: <String, String>{
|
|
'Content-Type': 'application/json; charset=UTF-8',
|
|
},
|
|
body: jsonEncode(<String, String?>{
|
|
'image': img64,
|
|
}),
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
return jsonDecode(response.body)['image_id'];
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
Future<dynamic> _analysis(String uri, Object body) async {
|
|
dynamic result;
|
|
|
|
Timer? _timer;
|
|
final completer = Completer<void>();
|
|
_timer = Timer.periodic(const Duration(seconds: 1), (timer) async {
|
|
final response = await http.post(
|
|
Uri.parse(uri),
|
|
headers: <String, String>{
|
|
'Content-Type': 'application/json; charset=UTF-8',
|
|
},
|
|
body: body,
|
|
);
|
|
if (response.statusCode == 200) {
|
|
if (jsonDecode(response.body).isEmpty) {
|
|
result = null; // 圖片還沒分析完成
|
|
} else {
|
|
result = jsonDecode(response.body) as Map<String, dynamic>;
|
|
}
|
|
} else {
|
|
result = null; // 伺服器異常
|
|
}
|
|
|
|
if (timer.tick >= 10 || result != null) {
|
|
_timer!.cancel();
|
|
try {
|
|
completer.complete();
|
|
} catch (e) {}
|
|
}
|
|
});
|
|
await completer.future;
|
|
return result;
|
|
}
|
|
}
|