Browse Source

访客的模块

liukai 2 months ago
parent
commit
c2344a65d8

+ 1 - 1
packages/cpt_main/lib/modules/feedback/create/feedback_create_view_model.dart

@@ -93,7 +93,7 @@ class FeedbackCreateViewModel extends _$FeedbackCreateViewModel with DioCancelab
       ToastEngine.show("Enter Your FeedBack Description");
       return;
     }
-    //执行密码登录
+    //执行请求
     final result = await _mainRepository.postFeedback(
       categoryId: state.selectedOption?.id,
       title: title,

+ 1 - 3
packages/cpt_main/lib/modules/visitor/active/visitor_active.dart

@@ -20,10 +20,8 @@ class VisitorActiveScreen extends HookConsumerWidget {
 
     useEffect(() {
       // 组件挂载时执行 - 执行接口请求
-      Future.microtask(() => viewModel.fetchAppliedStaffList());
+      Future.microtask(() => viewModel.fetchList());
       return () {
-        // 组件卸载时执行
-        Log.d("VisitorActiveScreen 组件卸载时执行");
       };
     }, []);
 

+ 3 - 2
packages/cpt_main/lib/modules/visitor/active/visitor_active_state.dart

@@ -1,3 +1,4 @@
+import 'package:domain/entity/visitor_page_entity.dart';
 import 'package:widgets/load_state_layout.dart';
 
 class VisitorActiveState {
@@ -6,7 +7,7 @@ class VisitorActiveState {
   LoadState loadingState;
   String? errorMessage;
 
-  List<String> datas; //页面列表数据
+  List<VisitorPageList> datas; //页面列表数据
 
   // ===================================  Begin  ↓  ===================================
 
@@ -20,7 +21,7 @@ class VisitorActiveState {
     LoadState? loadingState,
     String? errorMessage,
     bool? needShowPlaceholder,
-    List<String>? datas,
+    List<VisitorPageList>? datas,
   }) {
     return VisitorActiveState(
       errorMessage: errorMessage ?? this.errorMessage,

+ 51 - 74
packages/cpt_main/lib/modules/visitor/active/visitor_active_view_model.dart

@@ -1,3 +1,6 @@
+import 'package:domain/entity/visitor_page_entity.dart';
+import 'package:domain/repository/main_repository.dart';
+import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 import 'package:shared/utils/log_utils.dart';
 import 'package:widgets/load_state_layout.dart';
@@ -8,21 +11,23 @@ import 'visitor_active_state.dart';
 part 'visitor_active_view_model.g.dart';
 
 @riverpod
-class VisitorActiveViewModel extends _$VisitorActiveViewModel {
+class VisitorActiveViewModel extends _$VisitorActiveViewModel with DioCancelableMixin {
+  late final MainRepository _mainRepository;
   var _curPage = 1; //请求参数当前的页面
   var _needShowPlaceholder = true; //是否展示LoadingView
 
   // Refresh 控制器
   final EasyRefreshController refreshController = EasyRefreshController(
-    controlFinishRefresh: true,  //允许刷新
-    controlFinishLoad: true,   //允许加载
+    controlFinishRefresh: true, //允许刷新
+    controlFinishLoad: true, //允许加载
   );
 
   @override
   VisitorActiveState build() {
+    _mainRepository = ref.read(mainRepositoryProvider);
     final state = VisitorActiveState(datas: []);
     //初始化默认调用接口
-    Log.d("VisitorActiveViewModel 执行build");
+    registerCancellation();
     return state;
   }
 
@@ -34,100 +39,72 @@ class VisitorActiveViewModel extends _$VisitorActiveViewModel {
   // Refresh 刷新事件
   Future onRefresh() async {
     _curPage = 1;
-    fetchAppliedStaffList();
+    fetchList();
   }
 
   // Refresh 加载事件
   Future loadMore() async {
     _curPage++;
-    fetchAppliedStaffList();
+    fetchList();
   }
 
   // 重试请求
   Future retryRequest() async {
     _curPage = 1;
     _needShowPlaceholder = true;
-    fetchAppliedStaffList();
+    fetchList();
   }
 
   /// 获取服务器数据
-  Future fetchAppliedStaffList() async {
+  Future fetchList() async {
     if (_needShowPlaceholder) {
       changeLoadingState(LoadState.State_Loading, null);
     }
 
-    // 获取 Applied 列表
-    // var listResult = await _jobRepository.fetchJobAppliedList(
-    //   state.jobId,
-    //   state.selectedStatusId,
-    //   state.keyword,
-    //   curPage: _curPage,
-    //   cancelToken: cancelToken,
-    // );
-    //
-    // // 处理数据
-    // if (listResult.isSuccess) {
-    //   handleList(listResult.data?.rows);
-    // } else {
-    //   errorMessage = listResult.errorMsg;
-    //   changeLoadingState(LoadState.State_Error);
-    // }
+    // 获取列表
+    var listResult = await _mainRepository.fetchVisitorList(
+      type: "active",
+      curPage: _curPage,
+      cancelToken: cancelToken,
+    );
 
-
-    await Future.delayed(const Duration(milliseconds: 1500));
-
-    final List<String> list = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"];
-
-    if (_curPage == 1) {
-      //刷新的方式
-      state = state.copyWith(datas: list);
-      refreshController.finishRefresh();
-
-      //更新展示的状态
-      changeLoadingState(LoadState.State_Success, null);
+    // 处理数据
+    if (listResult.isSuccess) {
+      handleList(listResult.data?.list);
     } else {
-      //加载更多
-      final allList = state.datas;
-      allList.addAll(list);
-      state.datas.addAll(list);
-
-      refreshController.finishLoad();
-
-      state = state.copyWith(datas: allList);
+      changeLoadingState(LoadState.State_Error, listResult.errorMsg);
     }
 
     // 最后赋值
     _needShowPlaceholder = false;
   }
 
-// 处理数据与展示的逻辑
-// void handleList(List<JobAppliedListSGRows>? list) {
-//   if (list != null && list.isNotEmpty) {
-//     //有数据,判断是刷新还是加载更多的数据
-//     if (_curPage == 1) {
-//       //刷新的方式
-//       state.datas.clear();
-//       state.datas.addAll(list);
-//       refreshController.finishRefresh();
-//
-//       //更新展示的状态
-//       changeLoadingState(LoadState.State_Success);
-//     } else {
-//       //加载更多
-//       state.datas.addAll(list);
-//       refreshController.finishLoad();
-//       update();
-//     }
-//   } else {
-//     if (_curPage == 1) {
-//       //展示无数据的布局
-//       state.datas.clear();
-//       changeLoadingState(LoadState.State_Empty);
-//       refreshController.finishRefresh();
-//     } else {
-//       //展示加载完成,没有更多数据了
-//       refreshController.finishLoad(IndicatorResult.noMore);
-//     }
-//   }
-// }
+  // 处理数据与展示的逻辑
+  void handleList(List<VisitorPageList>? list) {
+    if (list != null && list.isNotEmpty) {
+      //有数据,判断是刷新还是加载更多的数据
+      if (_curPage == 1) {
+        //刷新的方式
+        state = state.copyWith(datas: list);
+        refreshController.finishRefresh();
+
+        //更新展示的状态
+        changeLoadingState(LoadState.State_Success, null);
+      } else {
+        //加载更多
+        state.datas.addAll(List<VisitorPageList>.from(state.datas)..addAll(list));
+        refreshController.finishLoad();
+      }
+    } else {
+      if (_curPage == 1) {
+        //展示无数据的布局
+        state = state.copyWith(datas: []);
+        changeLoadingState(LoadState.State_Empty, null);
+        refreshController.finishRefresh();
+      } else {
+        //展示加载完成,没有更多数据了
+        refreshController.finishLoad(IndicatorResult.noMore);
+      }
+    }
+  }
 }

+ 0 - 3
packages/cpt_main/lib/modules/visitor/history/visitor_history.dart

@@ -2,7 +2,6 @@ import 'package:auto_route/auto_route.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
-import 'package:shared/utils/log_utils.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/load_state_layout.dart';
 import 'package:widgets/widget_export.dart';
@@ -21,8 +20,6 @@ class VisitorHistoryScreen extends HookConsumerWidget {
       // 组件挂载时执行 - 执行接口请求
       Future.microtask(() => viewModel.fetchList());
       return () {
-        // 组件卸载时执行
-        Log.d("VisitorHistoryScreen 组件卸载时执行");
       };
     }, []);
 

+ 3 - 2
packages/cpt_main/lib/modules/visitor/history/visitor_history_state.dart

@@ -1,3 +1,4 @@
+import 'package:domain/entity/visitor_page_entity.dart';
 import 'package:widgets/load_state_layout.dart';
 
 class VisitorHistoryState {
@@ -6,7 +7,7 @@ class VisitorHistoryState {
   LoadState loadingState;
   String? errorMessage;
 
-  List<String> datas; //页面列表数据
+  List<VisitorPageList> datas; //页面列表数据
 
   // ===================================  Begin  ↓  ===================================
 
@@ -20,7 +21,7 @@ class VisitorHistoryState {
     LoadState? loadingState,
     String? errorMessage,
     bool? needShowPlaceholder,
-    List<String>? datas,
+    List<VisitorPageList>? datas,
   }) {
     return VisitorHistoryState(
       errorMessage: errorMessage ?? this.errorMessage,

+ 47 - 70
packages/cpt_main/lib/modules/visitor/history/visitor_history_view_model.dart

@@ -1,3 +1,6 @@
+import 'package:domain/entity/visitor_page_entity.dart';
+import 'package:domain/repository/main_repository.dart';
+import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 import 'package:shared/utils/log_utils.dart';
 import 'package:widgets/load_state_layout.dart';
@@ -8,21 +11,23 @@ import 'visitor_history_state.dart';
 part 'visitor_history_view_model.g.dart';
 
 @riverpod
-class VisitorHistoryViewModel extends _$VisitorHistoryViewModel {
+class VisitorHistoryViewModel extends _$VisitorHistoryViewModel with DioCancelableMixin {
+  late final MainRepository _mainRepository;
   var _curPage = 1; //请求参数当前的页面
   var _needShowPlaceholder = true; //是否展示LoadingView
 
   // Refresh 控制器
   final EasyRefreshController refreshController = EasyRefreshController(
-    controlFinishRefresh: true,  //允许刷新
-    controlFinishLoad: true,   //允许加载
+    controlFinishRefresh: true, //允许刷新
+    controlFinishLoad: true, //允许加载
   );
 
   @override
   VisitorHistoryState build() {
+    _mainRepository = ref.read(mainRepositoryProvider);
     final state = VisitorHistoryState(datas: []);
     //初始化默认调用接口
-    Log.d("VisitorActiveViewModel 执行build");
+    registerCancellation();
     return state;
   }
 
@@ -56,78 +61,50 @@ class VisitorHistoryViewModel extends _$VisitorHistoryViewModel {
       changeLoadingState(LoadState.State_Loading, null);
     }
 
-    // 获取 Applied 列表
-    // var listResult = await _jobRepository.fetchJobAppliedList(
-    //   state.jobId,
-    //   state.selectedStatusId,
-    //   state.keyword,
-    //   curPage: _curPage,
-    //   cancelToken: cancelToken,
-    // );
-    //
-    // // 处理数据
-    // if (listResult.isSuccess) {
-    //   handleList(listResult.data?.rows);
-    // } else {
-    //   errorMessage = listResult.errorMsg;
-    //   changeLoadingState(LoadState.State_Error);
-    // }
+    // 获取列表
+    var listResult = await _mainRepository.fetchVisitorList(
+      type: "history",
+      curPage: _curPage,
+      cancelToken: cancelToken,
+    );
 
-
-    await Future.delayed(const Duration(milliseconds: 1500));
-
-    final List<String> list = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"];
-
-    if (_curPage == 1) {
-      //刷新的方式
-      state = state.copyWith(datas: list);
-      refreshController.finishRefresh();
-
-      //更新展示的状态
-      changeLoadingState(LoadState.State_Success, null);
+    // 处理数据
+    if (listResult.isSuccess) {
+      handleList(listResult.data?.list);
     } else {
-      //加载更多
-      final allList = state.datas;
-      allList.addAll(list);
-      state.datas.addAll(list);
-
-      refreshController.finishLoad();
-
-      state = state.copyWith(datas: allList);
+      changeLoadingState(LoadState.State_Error, listResult.errorMsg);
     }
 
     // 最后赋值
     _needShowPlaceholder = false;
   }
 
-// 处理数据与展示的逻辑
-// void handleList(List<JobAppliedListSGRows>? list) {
-//   if (list != null && list.isNotEmpty) {
-//     //有数据,判断是刷新还是加载更多的数据
-//     if (_curPage == 1) {
-//       //刷新的方式
-//       state.datas.clear();
-//       state.datas.addAll(list);
-//       refreshController.finishRefresh();
-//
-//       //更新展示的状态
-//       changeLoadingState(LoadState.State_Success);
-//     } else {
-//       //加载更多
-//       state.datas.addAll(list);
-//       refreshController.finishLoad();
-//       update();
-//     }
-//   } else {
-//     if (_curPage == 1) {
-//       //展示无数据的布局
-//       state.datas.clear();
-//       changeLoadingState(LoadState.State_Empty);
-//       refreshController.finishRefresh();
-//     } else {
-//       //展示加载完成,没有更多数据了
-//       refreshController.finishLoad(IndicatorResult.noMore);
-//     }
-//   }
-// }
+  // 处理数据与展示的逻辑
+  void handleList(List<VisitorPageList>? list) {
+    if (list != null && list.isNotEmpty) {
+      //有数据,判断是刷新还是加载更多的数据
+      if (_curPage == 1) {
+        //刷新的方式
+        state = state.copyWith(datas: list);
+        refreshController.finishRefresh();
+
+        //更新展示的状态
+        changeLoadingState(LoadState.State_Success, null);
+      } else {
+        //加载更多
+        state.datas.addAll(List<VisitorPageList>.from(state.datas)..addAll(list));
+        refreshController.finishLoad();
+      }
+    } else {
+      if (_curPage == 1) {
+        //展示无数据的布局
+        state = state.copyWith(datas: []);
+        changeLoadingState(LoadState.State_Empty, null);
+        refreshController.finishRefresh();
+      } else {
+        //展示加载完成,没有更多数据了
+        refreshController.finishLoad(IndicatorResult.noMore);
+      }
+    }
+  }
 }

+ 9 - 7
packages/cpt_main/lib/modules/visitor/item_visitor.dart

@@ -1,11 +1,13 @@
 import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:domain/entity/visitor_page_entity.dart';
 import 'package:flutter/material.dart';
+import 'package:shared/utils/util.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_text_view.dart';
 
 class VisitorItem extends StatelessWidget {
   final int index;
-  final String item;
+  final VisitorPageList item;
 
   const VisitorItem({
     required this.index,
@@ -34,7 +36,7 @@ class VisitorItem extends StatelessWidget {
         children: [
           //姓名
           MyTextView(
-            "Wu Bing Bing",
+            item.name ?? "",
             fontSize: 16,
             marginTop: 19,
             marginBottom: 5,
@@ -46,14 +48,14 @@ class VisitorItem extends StatelessWidget {
           Row(
             children: [
               MyTextView(
-                "+86 12345678901",
+                item.phone ?? "",
                 fontSize: 14,
                 textColor: context.appColors.textBlack,
                 isFontRegular: true,
               ),
               const Spacer(),
               MyTextView(
-                "M12****7B",
+                Utils.maskString(item.nric ?? ""),
                 fontSize: 14,
                 textColor: context.appColors.textBlack,
                 isFontRegular: true,
@@ -65,14 +67,14 @@ class VisitorItem extends StatelessWidget {
           Row(
             children: [
               MyTextView(
-                "EFG8878",
+                item.vehicleNumber ?? "",
                 fontSize: 14,
                 textColor: context.appColors.textBlack,
                 isFontRegular: true,
               ),
               const Spacer(),
               MyTextView(
-                "Monday 13 Oct 2024",
+                item.createdAt ?? "",
                 fontSize: 14,
                 textColor: context.appColors.textBlack,
                 isFontRegular: true,
@@ -82,7 +84,7 @@ class VisitorItem extends StatelessWidget {
 
           //备注
           MyTextView(
-            "Visiting a friend's house as a guest",
+            item.note ?? "",
             fontSize: 14,
             marginTop: 6,
             textColor: context.appColors.textDarkGray,

+ 3 - 5
packages/cpt_main/lib/modules/visitor/register/visitor_register_page.dart

@@ -140,13 +140,11 @@ class VisitorRegisterPage extends HookConsumerWidget {
               ),
 
               // 通行时间
-              MyTextView(
-                S.current.access_date,
+              FormRequireText(
+                text: S.current.access_date,
                 textColor: context.appColors.textBlack,
                 fontSize: 17,
-                marginTop: 14.5,
-                isFontMedium: true,
-              ),
+              ).marginOnly(top: 14.5),
               // 选择器
               PickerContainer(
                 content: state.accessDate == null ? "" : DateTimeUtils.formatDate(state.accessDate, format: 'dd MMM yyyy'),

+ 34 - 12
packages/cpt_main/lib/modules/visitor/register/visitor_register_view_model.dart

@@ -1,8 +1,10 @@
-
 import 'package:cpt_main/modules/main/main_page.dart';
 import 'package:cs_resources/generated/l10n.dart';
+import 'package:domain/repository/main_repository.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:plugin_platform/engine/notify/notify_engine.dart';
+import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 import 'package:shared/utils/date_time_utils.dart';
 import 'package:shared/utils/log_utils.dart';
@@ -10,23 +12,26 @@ import 'package:shared/utils/util.dart';
 import 'package:widgets/picker/date_picker_util.dart';
 
 import 'visitor_register_state.dart';
+
 part 'visitor_register_view_model.g.dart';
 
 @riverpod
-class VisitorRegisterViewModel extends _$VisitorRegisterViewModel {
+class VisitorRegisterViewModel extends _$VisitorRegisterViewModel with DioCancelableMixin {
+  late final MainRepository _mainRepository;
 
   @override
-  VisitorRegisterState build(){
+  VisitorRegisterState build() {
+    _mainRepository = ref.read(mainRepositoryProvider);
     final state = VisitorRegisterState();
     initListener(state);
-    ref.onDispose(() {
+    registerCancellation(callback: () {
       onDispose(state);
     });
     return state;
   }
 
   //提交表单
-  void submitVisitorRegister() {
+  void submitVisitorRegister() async {
     state = state.copyWith(
       fullNameErrorText: null,
       phoneErrorText: null,
@@ -56,7 +61,7 @@ class VisitorRegisterViewModel extends _$VisitorRegisterViewModel {
     final nric = nricController.text;
     final plateNumber = plateNumberController.text;
     final note = noteController.text;
-    final accessDate = state.accessDate == null ?  null : DateTimeUtils.formatDate(state.accessDate!,format: 'yyyy-MM-dd');
+    final accessDate = state.accessDate == null ? null : DateTimeUtils.formatDate(state.accessDate!, format: 'yyyy-MM-dd');
 
     Log.d('当前待提交的 fullName:$fullName phone:$phone nric:$nric plateNumber:$plateNumber note:$note accessDate:$accessDate');
 
@@ -75,11 +80,29 @@ class VisitorRegisterViewModel extends _$VisitorRegisterViewModel {
       return;
     }
 
-    //执行密码登录
-    ToastEngine.show('准备执行请求 fullName:$fullName phone:$phone nric:$nric plateNumber:$plateNumber note:$note accessDate:$accessDate');
+    if (Utils.isEmpty(accessDate)) {
+      ToastEngine.show("Select Access Date");
+      return;
+    }
+
+    //执行请求
+    final result = await _mainRepository.createVisitor(
+      name: fullName,
+      phone: phone,
+      nric: nric,
+      vehicleNumber: plateNumber,
+      accessDate: accessDate,
+      note: note,
+      cancelToken: cancelToken,
+    );
 
-    //去首页
-    MainPage.startInstance();
+    if (result.isSuccess) {
+      NotifyEngine.showSuccess(S.current.successful);
+      //去首页
+      MainPage.startInstance();
+    } else {
+      ToastEngine.show(result.errorMsg ?? "UnKnow Error");
+    }
   }
 
   //选择通行时间
@@ -88,7 +111,7 @@ class VisitorRegisterViewModel extends _$VisitorRegisterViewModel {
       selectedDateTime: state.accessDate ?? DateTime.now(),
       mode: CupertinoDatePickerMode.date,
       onDateTimeChanged: (date) {
-       state = state.copyWith(accessDate: date);
+        state = state.copyWith(accessDate: date);
       },
       title: S.current.access_date,
     );
@@ -133,5 +156,4 @@ class VisitorRegisterViewModel extends _$VisitorRegisterViewModel {
 
     Log.d("VisitorRegisterViewModel 销毁 onDispose");
   }
-
 }

+ 6 - 0
packages/cs_domain/lib/constants/api_constants.dart

@@ -47,6 +47,12 @@ class ApiConstants {
   //反馈详情
   static const apiFeedbackDetail = "/api/v1/user/feedback/index/detail";
 
+  //创建访客
+  static const apiCreateVisitor = "/api/v1/user/visitor/index/apply";
+
+  //访客状态列表
+  static const apiVisitorList = "/api/v1/user/visitor/index";
+
   // =========================== Profile ↓=========================================
 
   //用户Me页面详情

+ 49 - 0
packages/cs_domain/lib/entity/visitor_page_entity.dart

@@ -0,0 +1,49 @@
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/visitor_page_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/visitor_page_entity.g.dart';
+
+@JsonSerializable()
+class VisitorPageEntity {
+	int count = 0;
+	int page =0 ;
+	int limit=0;
+	@JSONField(name: "count_page")
+	int countPage=0;
+	List<VisitorPageList> list = [];
+
+	VisitorPageEntity();
+
+	factory VisitorPageEntity.fromJson(Map<String, dynamic> json) => $VisitorPageEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $VisitorPageEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}
+
+@JsonSerializable()
+class VisitorPageList {
+	String? id;
+	String? name;
+	String? phone;
+	String? nric;
+	@JSONField(name: "vehicle_number")
+	String? vehicleNumber;
+	@JSONField(name: "created_at")
+	String? createdAt;
+	String? note;
+
+	VisitorPageList();
+
+	factory VisitorPageList.fromJson(Map<String, dynamic> json) => $VisitorPageListFromJson(json);
+
+	Map<String, dynamic> toJson() => $VisitorPageListToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

+ 9 - 0
packages/cs_domain/lib/generated/json/base/json_convert_content.dart

@@ -35,6 +35,7 @@ import 'package:domain/entity/property_news_entity.dart';
 import 'package:domain/entity/property_sale_rent_entity.dart';
 import 'package:domain/entity/server_time.dart';
 import 'package:domain/entity/user_me_entity.dart';
+import 'package:domain/entity/visitor_page_entity.dart';
 
 JsonConvert jsonConvert = JsonConvert();
 
@@ -362,6 +363,12 @@ class JsonConvert {
     if (<UserMeInformation>[] is M) {
       return data.map<UserMeInformation>((Map<String, dynamic> e) => UserMeInformation.fromJson(e)).toList() as M;
     }
+    if (<VisitorPageEntity>[] is M) {
+      return data.map<VisitorPageEntity>((Map<String, dynamic> e) => VisitorPageEntity.fromJson(e)).toList() as M;
+    }
+    if (<VisitorPageList>[] is M) {
+      return data.map<VisitorPageList>((Map<String, dynamic> e) => VisitorPageList.fromJson(e)).toList() as M;
+    }
 
     debugPrint("$M not found");
 
@@ -447,6 +454,8 @@ class JsonConvertClassCollection {
     (UserMeEstatesAccountsUnit).toString(): UserMeEstatesAccountsUnit.fromJson,
     (UserMeDefaultUnit).toString(): UserMeDefaultUnit.fromJson,
     (UserMeInformation).toString(): UserMeInformation.fromJson,
+    (VisitorPageEntity).toString(): VisitorPageEntity.fromJson,
+    (VisitorPageList).toString(): VisitorPageList.fromJson,
   };
 
   bool containsKey(String type) {

+ 121 - 0
packages/cs_domain/lib/generated/json/visitor_page_entity.g.dart

@@ -0,0 +1,121 @@
+import 'package:domain/generated/json/base/json_convert_content.dart';
+import 'package:domain/entity/visitor_page_entity.dart';
+
+VisitorPageEntity $VisitorPageEntityFromJson(Map<String, dynamic> json) {
+  final VisitorPageEntity visitorPageEntity = VisitorPageEntity();
+  final int? count = jsonConvert.convert<int>(json['count']);
+  if (count != null) {
+    visitorPageEntity.count = count;
+  }
+  final int? page = jsonConvert.convert<int>(json['page']);
+  if (page != null) {
+    visitorPageEntity.page = page;
+  }
+  final int? limit = jsonConvert.convert<int>(json['limit']);
+  if (limit != null) {
+    visitorPageEntity.limit = limit;
+  }
+  final int? countPage = jsonConvert.convert<int>(json['count_page']);
+  if (countPage != null) {
+    visitorPageEntity.countPage = countPage;
+  }
+  final List<VisitorPageList>? list = (json['list'] as List<dynamic>?)?.map(
+          (e) => jsonConvert.convert<VisitorPageList>(e) as VisitorPageList).toList();
+  if (list != null) {
+    visitorPageEntity.list = list;
+  }
+  return visitorPageEntity;
+}
+
+Map<String, dynamic> $VisitorPageEntityToJson(VisitorPageEntity entity) {
+  final Map<String, dynamic> data = <String, dynamic>{};
+  data['count'] = entity.count;
+  data['page'] = entity.page;
+  data['limit'] = entity.limit;
+  data['count_page'] = entity.countPage;
+  data['list'] = entity.list.map((v) => v.toJson()).toList();
+  return data;
+}
+
+extension VisitorPageEntityExtension on VisitorPageEntity {
+  VisitorPageEntity copyWith({
+    int? count,
+    int? page,
+    int? limit,
+    int? countPage,
+    List<VisitorPageList>? list,
+  }) {
+    return VisitorPageEntity()
+      ..count = count ?? this.count
+      ..page = page ?? this.page
+      ..limit = limit ?? this.limit
+      ..countPage = countPage ?? this.countPage
+      ..list = list ?? this.list;
+  }
+}
+
+VisitorPageList $VisitorPageListFromJson(Map<String, dynamic> json) {
+  final VisitorPageList visitorPageList = VisitorPageList();
+  final String? id = jsonConvert.convert<String>(json['id']);
+  if (id != null) {
+    visitorPageList.id = id;
+  }
+  final String? name = jsonConvert.convert<String>(json['name']);
+  if (name != null) {
+    visitorPageList.name = name;
+  }
+  final String? phone = jsonConvert.convert<String>(json['phone']);
+  if (phone != null) {
+    visitorPageList.phone = phone;
+  }
+  final String? nric = jsonConvert.convert<String>(json['nric']);
+  if (nric != null) {
+    visitorPageList.nric = nric;
+  }
+  final String? vehicleNumber = jsonConvert.convert<String>(json['vehicle_number']);
+  if (vehicleNumber != null) {
+    visitorPageList.vehicleNumber = vehicleNumber;
+  }
+  final String? createdAt = jsonConvert.convert<String>(json['created_at']);
+  if (createdAt != null) {
+    visitorPageList.createdAt = createdAt;
+  }
+  final String? note = jsonConvert.convert<String>(json['note']);
+  if (note != null) {
+    visitorPageList.note = note;
+  }
+  return visitorPageList;
+}
+
+Map<String, dynamic> $VisitorPageListToJson(VisitorPageList entity) {
+  final Map<String, dynamic> data = <String, dynamic>{};
+  data['id'] = entity.id;
+  data['name'] = entity.name;
+  data['phone'] = entity.phone;
+  data['nric'] = entity.nric;
+  data['vehicle_number'] = entity.vehicleNumber;
+  data['created_at'] = entity.createdAt;
+  data['note'] = entity.note;
+  return data;
+}
+
+extension VisitorPageListExtension on VisitorPageList {
+  VisitorPageList copyWith({
+    String? id,
+    String? name,
+    String? phone,
+    String? nric,
+    String? vehicleNumber,
+    String? createdAt,
+    String? note,
+  }) {
+    return VisitorPageList()
+      ..id = id ?? this.id
+      ..name = name ?? this.name
+      ..phone = phone ?? this.phone
+      ..nric = nric ?? this.nric
+      ..vehicleNumber = vehicleNumber ?? this.vehicleNumber
+      ..createdAt = createdAt ?? this.createdAt
+      ..note = note ?? this.note;
+  }
+}

+ 68 - 1
packages/cs_domain/lib/repository/main_repository.dart

@@ -1,9 +1,11 @@
 import 'package:domain/entity/feedback_detail_entity.dart';
+import 'package:domain/entity/visitor_page_entity.dart';
 import 'package:plugin_platform/platform_export.dart';
 import 'package:plugin_platform/http/dio_engine.dart';
 import 'package:plugin_platform/http/http_result.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 import 'package:shared/utils/log_utils.dart';
+import 'package:shared/utils/util.dart';
 
 import '../constants/api_constants.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
@@ -129,7 +131,7 @@ class MainRepository {
     CancelToken? cancelToken,
   }) async {
     Map<String, String> params = {};
-    params['id'] = id??"";
+    params['id'] = id ?? "";
 
     final result = await dioEngine.requestNetResult(
       ApiConstants.apiFeedbackDetail,
@@ -147,4 +149,69 @@ class MainRepository {
     }
     return result.convert();
   }
+
+  /// 创建访客的信息
+  Future<HttpResult> createVisitor({
+    required String? name,
+    required String? phone,
+    required String? nric,
+    required String? vehicleNumber,
+    required String? accessDate,
+    required String? note,
+    CancelToken? cancelToken,
+  }) async {
+    Map<String, String> params = {};
+    params['name'] = name ?? "";
+    params['phone'] = phone ?? "";
+    params['nric'] = nric ?? "";
+    params['access_date'] = accessDate ?? "";
+
+    if (Utils.isNotEmpty(vehicleNumber)) {
+      params['vehicle_number'] = vehicleNumber!;
+    }
+    if (Utils.isNotEmpty(note)) {
+      params['note'] = note!;
+    }
+
+    final result = await dioEngine.requestNetResult(
+      ApiConstants.apiCreateVisitor,
+      params: params,
+      method: HttpMethod.POST,
+      isShowLoadingDialog: true,
+      networkDebounce: true,
+      cancelToken: cancelToken,
+    );
+
+    if (result.isSuccess) {
+      return result.convert();
+    }
+    return result.convert();
+  }
+
+  /// 已创建的访客列表
+  Future<HttpResult<VisitorPageEntity>> fetchVisitorList({
+    required String type,
+    required int curPage,
+    CancelToken? cancelToken,
+  }) async {
+    Map<String, String> params = {};
+    params['type'] = type;
+    params['page'] = curPage.toString();
+    params['limit'] = "10";
+
+    final result = await dioEngine.requestNetResult(
+      ApiConstants.apiVisitorList,
+      params: params,
+      method: HttpMethod.GET,
+      cancelToken: cancelToken,
+    );
+
+    if (result.isSuccess) {
+      final json = result.getDataJson();
+      var data = VisitorPageEntity.fromJson(json!);
+      return result.convert<VisitorPageEntity>(data: data);
+    }
+    return result.convert();
+  }
+
 }

+ 21 - 0
packages/cs_shared/lib/utils/util.dart

@@ -188,4 +188,25 @@ class Utils {
 
     return null; // 未找到宽高
   }
+
+  /// 将字符串的前三位和后两位显示,中间用 * 替代。
+  static String maskString(String input) {
+    // 检查字符串长度
+    if (input.length <= 5) {
+      // 如果字符串长度小于等于5,直接返回原字符串
+      return input;
+    }
+
+    // 获取前三位和后两位
+    String start = input.substring(0, 3);
+    String end = input.substring(input.length - 2);
+
+    // 计算中间需要的 * 的数量
+    int asterisksCount = input.length - 5; // 计算需要的 * 的数量
+    String asterisks = '*' * asterisksCount; // 创建 * 字符串
+
+    // 拼接成新的字符串
+    return '$start$asterisks$end';
+  }
+
 }