Kaynağa Gözat

实现获取今日概况、今日代办、今日患者接口。

PC\19500 3 hafta önce
ebeveyn
işleme
a10bc2ff19

+ 11 - 0
lib/core/constants/api_constants.dart

@@ -53,6 +53,17 @@ class ApiConstants {
   /// Application JSON
   static const String applicationJson = 'application/json';
 
+  // ==================== 首页(工作台)相关 ====================
+
+  /// 今日概况
+  static const String getTodayOverview = 'api/his-clinic/work-bench/today-overview';
+
+  /// 今日代办
+  static const String getTodayWait = 'api/his-clinic/work-bench/today-wait';
+
+  /// 今日患者
+  static const String getTodayPatient = 'api/his-clinic/work-bench/today-patient';
+
   // ==================== 超时配置 ====================
   
   /// 连接超时时间(秒)

+ 29 - 0
lib/core/network/dio_client.dart

@@ -6,6 +6,8 @@ import 'package:sino_med_cloud/core/network/interceptors/log_interceptor.dart';
 import 'package:sino_med_cloud/core/utils/logger.dart';
 import 'package:sino_med_cloud/base/common_response.dart';
 
+import '../../base/list_response.dart';
+
 /// Dio 客户端 - 统一网络请求管理
 class DioClient {
   // 使用一个内部方法来创建和配置 Dio 实例
@@ -86,6 +88,33 @@ class DioClient {
     }
   }
 
+  static Future<BaseListResponse<T>> getList<T>(
+      String path, {
+        required T Function(Object? json) fromJsonT,
+        Map<String, dynamic>? queryParameters,
+        Options? options,
+        CancelToken? cancelToken,
+        ProgressCallback? onReceiveProgress,
+      }) async {
+    try {
+      final response = await dio.get(
+        path,
+        queryParameters: queryParameters,
+        options: options,
+        cancelToken: cancelToken,
+        onReceiveProgress: onReceiveProgress,
+      );
+
+      return BaseListResponse<T>.fromJson(
+        response.data as Map<String, dynamic>,
+        fromJsonT,
+      );
+    } on DioException catch (e) {
+      // 错误已由 ErrorInterceptor 处理,直接抛出
+      rethrow;
+    }
+  }
+
   // ==================== POST 请求 ====================
 
   /// POST 请求

+ 45 - 0
lib/features/HomePage/data/today_overview_model.dart

@@ -0,0 +1,45 @@
+import 'package:json_annotation/json_annotation.dart';
+
+part 'today_overview_model.g.dart';
+
+/// 今日概况模型
+@JsonSerializable()
+class TodayOverviewModel {
+  @JsonKey(name: 'today_arrived_total')
+  final int? todayArrivedTotal; // 预约到诊人数
+  @JsonKey(name: 'today_appointment_total')
+  final int todayAppointmentTotal; // 今日预约人数
+  @JsonKey(name: 'today_registration_total')
+  final int? todayRegistrationTotal; // 今日挂号人数
+  @JsonKey(name: 'today_visit_total')
+  final int? todayVisitTotal; // 今日就诊人数
+  @JsonKey(name: 'today_new_patient_total')
+  final int? todayNewPatientTotal; // 今日新增患者
+  @JsonKey(name: 'today_revenue_total')
+  final int? todayRevenueTotal; // 今日收入
+  @JsonKey(name: 'today_average_order_price')
+  final int? todayAverageOrderPrice; // 今日客单价
+  @JsonKey(name: 'inventory_warning_count')
+  final int? inventoryWarningCount; // 库存预警品种数量
+  @JsonKey(name: 'validity_warning_count')
+  final int? validityWarningCount; // 效期预警品种数量
+
+  TodayOverviewModel({
+    this.todayArrivedTotal,
+    required this.todayAppointmentTotal,
+    this.todayRegistrationTotal,
+    this.todayVisitTotal,
+    this.todayNewPatientTotal,
+    this.todayRevenueTotal,
+    this.todayAverageOrderPrice,
+    this.inventoryWarningCount,
+    this.validityWarningCount
+  });
+
+  /// 从 JSON 创建 TodayOverviewModel
+  factory TodayOverviewModel.fromJson(Map<String, dynamic> json) =>
+      _$TodayOverviewModelFromJson(json);
+
+  /// 转换为 JSON
+  Map<String, dynamic> toJson() => _$TodayOverviewModelToJson(this);
+}

+ 34 - 0
lib/features/HomePage/data/today_overview_model.g.dart

@@ -0,0 +1,34 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'today_overview_model.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+TodayOverviewModel _$TodayOverviewModelFromJson(
+  Map<String, dynamic> json,
+) => TodayOverviewModel(
+  todayArrivedTotal: (json['today_arrived_total'] as num?)?.toInt(),
+  todayAppointmentTotal: (json['today_appointment_total'] as num).toInt(),
+  todayRegistrationTotal: (json['today_registration_total'] as num?)?.toInt(),
+  todayVisitTotal: (json['today_visit_total'] as num?)?.toInt(),
+  todayNewPatientTotal: (json['today_new_patient_total'] as num?)?.toInt(),
+  todayRevenueTotal: (json['today_revenue_total'] as num?)?.toInt(),
+  todayAverageOrderPrice: (json['today_average_order_price'] as num?)?.toInt(),
+  inventoryWarningCount: (json['inventory_warning_count'] as num?)?.toInt(),
+  validityWarningCount: (json['validity_warning_count'] as num?)?.toInt(),
+);
+
+Map<String, dynamic> _$TodayOverviewModelToJson(TodayOverviewModel instance) =>
+    <String, dynamic>{
+      'today_arrived_total': instance.todayArrivedTotal,
+      'today_appointment_total': instance.todayAppointmentTotal,
+      'today_registration_total': instance.todayRegistrationTotal,
+      'today_visit_total': instance.todayVisitTotal,
+      'today_new_patient_total': instance.todayNewPatientTotal,
+      'today_revenue_total': instance.todayRevenueTotal,
+      'today_average_order_price': instance.todayAverageOrderPrice,
+      'inventory_warning_count': instance.inventoryWarningCount,
+      'validity_warning_count': instance.validityWarningCount,
+    };

+ 75 - 0
lib/features/HomePage/data/today_patient_model.dart

@@ -0,0 +1,75 @@
+import 'package:json_annotation/json_annotation.dart';
+
+part 'today_patient_model.g.dart';
+
+/// 今日患者模型
+@JsonSerializable()
+class TodayPatientModel {
+  @JsonKey(name: 'appointment_uuid')
+  final String appointmentUUID; // 门诊uuid
+  final String gender; // 0:未知 1:男 2:女
+  @JsonKey(name: 'serial_number')
+  final String serialNumber; // 预约时间段对应的序号
+  final int action; // 1:预约 2:挂号 3:加号
+  @JsonKey(name: 'patient_name')
+  final String patientName; // 患者名称
+  @JsonKey(name: 'patient_phone')
+  final String? patientPhone; // 患者手机号
+  @JsonKey(name: 'doctor_name')
+  final String? doctorName; // 医生名称
+  @JsonKey(name: 'his_dept_name')
+  final String? hisDeptName; // 医生科室
+  @JsonKey(name: 'day_part')
+  final String dayPart; // 挂号一天,上午:morning 下午:afternoon  晚上:evening
+  @JsonKey(name: 'appointment_status')
+  final int appointmentStatus; // 挂号状态
+  @JsonKey(name: 'institution_patient_uuid')
+  final String? institutionPatientUUID; // 机构患者uuid
+  @JsonKey(name: 'see_doctor_time')
+  final String? seeDoctorTime; // 就诊时间
+  @JsonKey(name: 'created_time')
+  final String createdTime; // 创建时间
+  @JsonKey(name: 'status_weight')
+  // 10:待诊 20:待收费 30:待发药 40:已诊 50:已收费 60:已发药 70:已退药 80:已退费 90:已退珍
+  final int statusWeight;
+  @JsonKey(name: 'payment_receipt_uuid')
+  final String paymentReceiptUUID; // 收费和药房的uuid
+  @JsonKey(name: 'payment_receipt_status')
+  final int paymentReceiptStatus; // 收费状态
+  @JsonKey(name: 'prescribes_receipt_status')
+  final int? prescribesReceiptStatus; // 发药状态
+  @JsonKey(name: 'is_retail')
+  final bool isRetail; // 是否零售
+  @JsonKey(name: 'temporary_reception_status')
+  // 1:非临时接诊 2:临时接诊 3:临时接诊-已诊
+  final String temporaryReceptionStatus;
+
+  TodayPatientModel({
+    required this.appointmentUUID,
+    required this.gender,
+    required this.serialNumber,
+    required this.action,
+    required this.patientName,
+    this.patientPhone,
+    this.doctorName,
+    this.hisDeptName,
+    required this.dayPart,
+    required this.appointmentStatus,
+    this.institutionPatientUUID,
+    this.seeDoctorTime,
+    required this.createdTime,
+    required this.statusWeight,
+    required this.paymentReceiptUUID,
+    required this.paymentReceiptStatus,
+    this.prescribesReceiptStatus,
+    required this.isRetail,
+    required this.temporaryReceptionStatus,
+  });
+
+  /// 从 JSON 创建 TodayPatientModel
+  factory TodayPatientModel.fromJson(Map<String, dynamic> json) =>
+      _$TodayPatientModelFromJson(json);
+
+  /// 转换为 JSON
+  Map<String, dynamic> toJson() => _$TodayPatientModelToJson(this);
+}

+ 54 - 0
lib/features/HomePage/data/today_patient_model.g.dart

@@ -0,0 +1,54 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'today_patient_model.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+TodayPatientModel _$TodayPatientModelFromJson(Map<String, dynamic> json) =>
+    TodayPatientModel(
+      appointmentUUID: json['appointment_uuid'] as String,
+      gender: json['gender'] as String,
+      serialNumber: json['serial_number'] as String,
+      action: (json['action'] as num).toInt(),
+      patientName: json['patient_name'] as String,
+      patientPhone: json['patient_phone'] as String?,
+      doctorName: json['doctor_name'] as String?,
+      hisDeptName: json['his_dept_name'] as String?,
+      dayPart: json['day_part'] as String,
+      appointmentStatus: (json['appointment_status'] as num).toInt(),
+      institutionPatientUUID: json['institution_patient_uuid'] as String?,
+      seeDoctorTime: json['see_doctor_time'] as String?,
+      createdTime: json['created_time'] as String,
+      statusWeight: (json['status_weight'] as num).toInt(),
+      paymentReceiptUUID: json['payment_receipt_uuid'] as String,
+      paymentReceiptStatus: (json['payment_receipt_status'] as num).toInt(),
+      prescribesReceiptStatus: (json['prescribes_receipt_status'] as num?)
+          ?.toInt(),
+      isRetail: json['is_retail'] as bool,
+      temporaryReceptionStatus: json['temporary_reception_status'] as String,
+    );
+
+Map<String, dynamic> _$TodayPatientModelToJson(TodayPatientModel instance) =>
+    <String, dynamic>{
+      'appointment_uuid': instance.appointmentUUID,
+      'gender': instance.gender,
+      'serial_number': instance.serialNumber,
+      'action': instance.action,
+      'patient_name': instance.patientName,
+      'patient_phone': instance.patientPhone,
+      'doctor_name': instance.doctorName,
+      'his_dept_name': instance.hisDeptName,
+      'day_part': instance.dayPart,
+      'appointment_status': instance.appointmentStatus,
+      'institution_patient_uuid': instance.institutionPatientUUID,
+      'see_doctor_time': instance.seeDoctorTime,
+      'created_time': instance.createdTime,
+      'status_weight': instance.statusWeight,
+      'payment_receipt_uuid': instance.paymentReceiptUUID,
+      'payment_receipt_status': instance.paymentReceiptStatus,
+      'prescribes_receipt_status': instance.prescribesReceiptStatus,
+      'is_retail': instance.isRetail,
+      'temporary_reception_status': instance.temporaryReceptionStatus,
+    };

+ 28 - 0
lib/features/HomePage/data/today_wait_model.dart

@@ -0,0 +1,28 @@
+import 'package:json_annotation/json_annotation.dart';
+
+part 'today_wait_model.g.dart';
+
+/// 今日待办模型
+@JsonSerializable()
+class TodayWaitModel {
+  @JsonKey(name: 'today_wait_charged')
+  final int? todayWaitCharged; // 收费
+  @JsonKey(name: 'today_wait_medicine')
+  final int? todayWaitMedicine; // 发药
+  @JsonKey(name: 'today_wait_outpatient')
+  final int? todayWaitOutpatient; // 门诊
+
+  TodayWaitModel({
+    this.todayWaitCharged,
+    this.todayWaitMedicine,
+    this.todayWaitOutpatient
+  });
+
+  /// 从 JSON 创建 TodayWaitModel
+  factory TodayWaitModel.fromJson(Map<String, dynamic> json) =>
+      _$TodayWaitModelFromJson(json);
+
+  /// 转换为 JSON
+  Map<String, dynamic> toJson() => _$TodayWaitModelToJson(this);
+
+}

+ 21 - 0
lib/features/HomePage/data/today_wait_model.g.dart

@@ -0,0 +1,21 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'today_wait_model.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+TodayWaitModel _$TodayWaitModelFromJson(Map<String, dynamic> json) =>
+    TodayWaitModel(
+      todayWaitCharged: (json['today_wait_charged'] as num?)?.toInt(),
+      todayWaitMedicine: (json['today_wait_medicine'] as num?)?.toInt(),
+      todayWaitOutpatient: (json['today_wait_outpatient'] as num?)?.toInt(),
+    );
+
+Map<String, dynamic> _$TodayWaitModelToJson(TodayWaitModel instance) =>
+    <String, dynamic>{
+      'today_wait_charged': instance.todayWaitCharged,
+      'today_wait_medicine': instance.todayWaitMedicine,
+      'today_wait_outpatient': instance.todayWaitOutpatient,
+    };

+ 95 - 0
lib/features/HomePage/domain/work_bench_service.dart

@@ -1,4 +1,99 @@
+import 'package:path/path.dart' as path;
+import 'package:sino_med_cloud/core/utils/logger.dart';
+
+import '../../../core/constants/api_constants.dart';
+import '../../../core/network/dio_client.dart';
+import '../data/today_overview_model.dart';
+import '../data/today_patient_model.dart';
+import '../data/today_wait_model.dart';
 
 class WorkBenchService {
 
+  // 获取今日概况数据
+  static Future<TodayOverviewModel> getTodayOverview() async {
+    try {
+     final response = await DioClient.get<Map<String, dynamic>>(
+        path.join(ApiConstants.baseUrl, ApiConstants.getTodayOverview),
+        fromJsonT: (json) => json as Map<String, dynamic>,
+      );
+     if (response.success && response.code == 20000) {
+       AppLogger.d('获取今日概况成功: ${response.data}');
+       final jsonData = response.data!;
+       // 解析为 TodayOverviewModel
+       final todayOverviewModel = TodayOverviewModel.fromJson(jsonData);
+       return todayOverviewModel;
+     } else {
+       final errorMsg = response.msg ?? '获取今日概况失败';
+       AppLogger.d('获取今日概况失败: $errorMsg');
+       throw Exception(errorMsg);
+     }
+    } catch (e) {
+      AppLogger.e('获取今日概况错误', e);
+      rethrow;
+    }
+  }
+
+  // 获取今日代办数据
+  static Future<TodayWaitModel> getTodayWait() async {
+    try {
+      final response = await DioClient.get<Map<String, dynamic>>(
+        path.join(ApiConstants.baseUrl, ApiConstants.getTodayWait),
+        fromJsonT: (json) => json as Map<String, dynamic>,
+      );
+      if (response.success && response.code == 20000) {
+        AppLogger.d('获取今日代办成功: ${response.data}');
+        final jsonData = response.data!;
+        // 解析为 TodayOverviewModel
+        final todayOverviewModel = TodayWaitModel.fromJson(jsonData);
+        return todayOverviewModel;
+      } else {
+        final errorMsg = response.msg ?? '获取今日代办失败';
+        AppLogger.d('获取今日代办失败: $errorMsg');
+        throw Exception(errorMsg);
+      }
+    } catch (e) {
+      AppLogger.e('获取今日代办错误', e);
+      rethrow;
+    }
+  }
+
+  // 获取今日患者数据
+  static Future<List<TodayPatientModel>> getTodayPatient({
+    required int limit,
+    required int offset,
+    String? search,
+    String? nameOrMobile
+  }) async {
+    try {
+      // 构建查询参数
+      final queryParameters = <String, dynamic>{
+        'limit': limit,
+        'offset': offset,
+      };
+      if (search != null && search.isNotEmpty) {
+        queryParameters['search'] = search;
+      }
+      if (nameOrMobile != null && nameOrMobile.isNotEmpty) {
+        queryParameters['name_or_mobile'] = nameOrMobile;
+      }
+      
+      final response = await DioClient.getList<TodayPatientModel>(
+        path.join(ApiConstants.baseUrl, ApiConstants.getTodayPatient),
+        fromJsonT: (json) => TodayPatientModel.fromJson(json as Map<String, dynamic>),
+        queryParameters: queryParameters,
+      );
+      
+      if (response.success && response.code == 20000) {
+        AppLogger.d('获取今日患者成功,共 ${response.data.count} 条,返回 ${response.data.results.length} 条');
+        return response.data.results;
+      } else {
+        final errorMsg = response.msg ?? '获取今日患者失败';
+        AppLogger.d('获取今日患者失败: $errorMsg');
+        throw Exception(errorMsg);
+      }
+    } catch (e) {
+      AppLogger.e('获取今日患者错误', e);
+      rethrow;
+    }
+  }
 }