|
|
@ -188,11 +188,17 @@
|
||||||
30C4C01D2FDBF557009215C1 /* RemoveMemberViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C4C01C2FDBF557009215C1 /* RemoveMemberViewModel.swift */; };
|
30C4C01D2FDBF557009215C1 /* RemoveMemberViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C4C01C2FDBF557009215C1 /* RemoveMemberViewModel.swift */; };
|
||||||
30C4C0202FDC0EC5009215C1 /* GroupInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C4C01F2FDC0EC5009215C1 /* GroupInfoView.swift */; };
|
30C4C0202FDC0EC5009215C1 /* GroupInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C4C01F2FDC0EC5009215C1 /* GroupInfoView.swift */; };
|
||||||
30C4C0222FDC0ED3009215C1 /* GroupInfoVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C4C0212FDC0ED3009215C1 /* GroupInfoVC.swift */; };
|
30C4C0222FDC0ED3009215C1 /* GroupInfoVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C4C0212FDC0ED3009215C1 /* GroupInfoVC.swift */; };
|
||||||
|
30CCDE4E2FE26CEA00F5214A /* PayResultPopVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30CCDE4D2FE26CEA00F5214A /* PayResultPopVC.swift */; };
|
||||||
|
30CCDE512FE2785D00F5214A /* SignInVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30CCDE502FE2785D00F5214A /* SignInVC.swift */; };
|
||||||
|
30CCDE532FE2786600F5214A /* SignInView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30CCDE522FE2786600F5214A /* SignInView.swift */; };
|
||||||
|
30CCDE552FE2903100F5214A /* SignInModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30CCDE542FE2903100F5214A /* SignInModel.swift */; };
|
||||||
30D87CDB2FDFA9EE00E958FD /* MQTTService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D87CDA2FDFA9EE00E958FD /* MQTTService.swift */; };
|
30D87CDB2FDFA9EE00E958FD /* MQTTService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D87CDA2FDFA9EE00E958FD /* MQTTService.swift */; };
|
||||||
30D87CDD2FDFF07500E958FD /* InteractionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D87CDC2FDFF07500E958FD /* InteractionView.swift */; };
|
30D87CDD2FDFF07500E958FD /* InteractionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D87CDC2FDFF07500E958FD /* InteractionView.swift */; };
|
||||||
30D87CDF2FDFF1A100E958FD /* QuickMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D87CDE2FDFF1A100E958FD /* QuickMessageView.swift */; };
|
30D87CDF2FDFF1A100E958FD /* QuickMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D87CDE2FDFF1A100E958FD /* QuickMessageView.swift */; };
|
||||||
30D87D042FE1336300E958FD /* NavigationVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D87D012FE1336300E958FD /* NavigationVC.swift */; };
|
30D87D042FE1336300E958FD /* NavigationVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D87D012FE1336300E958FD /* NavigationVC.swift */; };
|
||||||
30D87D052FE1336300E958FD /* NavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D87D022FE1336300E958FD /* NavigationView.swift */; };
|
30D87D052FE1336300E958FD /* NavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D87D022FE1336300E958FD /* NavigationView.swift */; };
|
||||||
|
30D891F52FE22E0600E958FD /* OrderAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D891F42FE22E0600E958FD /* OrderAPI.swift */; };
|
||||||
|
30D891F72FE22E6E00E958FD /* OrderService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D891F62FE22E6E00E958FD /* OrderService.swift */; };
|
||||||
30DC18522FD009CD0041DCD1 /* VipExpenseModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30DC18512FD009CD0041DCD1 /* VipExpenseModel.swift */; };
|
30DC18522FD009CD0041DCD1 /* VipExpenseModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30DC18512FD009CD0041DCD1 /* VipExpenseModel.swift */; };
|
||||||
30DC18542FD00C4A0041DCD1 /* VipRechargeVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30DC18532FD00C4A0041DCD1 /* VipRechargeVM.swift */; };
|
30DC18542FD00C4A0041DCD1 /* VipRechargeVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30DC18532FD00C4A0041DCD1 /* VipRechargeVM.swift */; };
|
||||||
30DC185A2FD11E7A0041DCD1 /* WebOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30DC18562FD11E7A0041DCD1 /* WebOperations.swift */; };
|
30DC185A2FD11E7A0041DCD1 /* WebOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30DC18562FD11E7A0041DCD1 /* WebOperations.swift */; };
|
||||||
|
|
@ -425,11 +431,17 @@
|
||||||
30C4C01C2FDBF557009215C1 /* RemoveMemberViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoveMemberViewModel.swift; sourceTree = "<group>"; };
|
30C4C01C2FDBF557009215C1 /* RemoveMemberViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoveMemberViewModel.swift; sourceTree = "<group>"; };
|
||||||
30C4C01F2FDC0EC5009215C1 /* GroupInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupInfoView.swift; sourceTree = "<group>"; };
|
30C4C01F2FDC0EC5009215C1 /* GroupInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupInfoView.swift; sourceTree = "<group>"; };
|
||||||
30C4C0212FDC0ED3009215C1 /* GroupInfoVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupInfoVC.swift; sourceTree = "<group>"; };
|
30C4C0212FDC0ED3009215C1 /* GroupInfoVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupInfoVC.swift; sourceTree = "<group>"; };
|
||||||
|
30CCDE4D2FE26CEA00F5214A /* PayResultPopVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayResultPopVC.swift; sourceTree = "<group>"; };
|
||||||
|
30CCDE502FE2785D00F5214A /* SignInVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInVC.swift; sourceTree = "<group>"; };
|
||||||
|
30CCDE522FE2786600F5214A /* SignInView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInView.swift; sourceTree = "<group>"; };
|
||||||
|
30CCDE542FE2903100F5214A /* SignInModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInModel.swift; sourceTree = "<group>"; };
|
||||||
30D87CDA2FDFA9EE00E958FD /* MQTTService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MQTTService.swift; sourceTree = "<group>"; };
|
30D87CDA2FDFA9EE00E958FD /* MQTTService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MQTTService.swift; sourceTree = "<group>"; };
|
||||||
30D87CDC2FDFF07500E958FD /* InteractionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InteractionView.swift; sourceTree = "<group>"; };
|
30D87CDC2FDFF07500E958FD /* InteractionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InteractionView.swift; sourceTree = "<group>"; };
|
||||||
30D87CDE2FDFF1A100E958FD /* QuickMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickMessageView.swift; sourceTree = "<group>"; };
|
30D87CDE2FDFF1A100E958FD /* QuickMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickMessageView.swift; sourceTree = "<group>"; };
|
||||||
30D87D012FE1336300E958FD /* NavigationVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationVC.swift; sourceTree = "<group>"; };
|
30D87D012FE1336300E958FD /* NavigationVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationVC.swift; sourceTree = "<group>"; };
|
||||||
30D87D022FE1336300E958FD /* NavigationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationView.swift; sourceTree = "<group>"; };
|
30D87D022FE1336300E958FD /* NavigationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationView.swift; sourceTree = "<group>"; };
|
||||||
|
30D891F42FE22E0600E958FD /* OrderAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderAPI.swift; sourceTree = "<group>"; };
|
||||||
|
30D891F62FE22E6E00E958FD /* OrderService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderService.swift; sourceTree = "<group>"; };
|
||||||
30DC18512FD009CD0041DCD1 /* VipExpenseModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VipExpenseModel.swift; sourceTree = "<group>"; };
|
30DC18512FD009CD0041DCD1 /* VipExpenseModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VipExpenseModel.swift; sourceTree = "<group>"; };
|
||||||
30DC18532FD00C4A0041DCD1 /* VipRechargeVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VipRechargeVM.swift; sourceTree = "<group>"; };
|
30DC18532FD00C4A0041DCD1 /* VipRechargeVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VipRechargeVM.swift; sourceTree = "<group>"; };
|
||||||
30DC18552FD11E7A0041DCD1 /* NavigationTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationTitleView.swift; sourceTree = "<group>"; };
|
30DC18552FD11E7A0041DCD1 /* NavigationTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationTitleView.swift; sourceTree = "<group>"; };
|
||||||
|
|
@ -479,15 +491,11 @@
|
||||||
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
||||||
3070777D2FD2A214004C37CC /* lotties */ = {
|
3070777D2FD2A214004C37CC /* lotties */ = {
|
||||||
isa = PBXFileSystemSynchronizedRootGroup;
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
exceptions = (
|
|
||||||
);
|
|
||||||
path = lotties;
|
path = lotties;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
30D87CEF2FDFF52100E958FD /* TTGTagCollectionView */ = {
|
30D87CEF2FDFF52100E958FD /* TTGTagCollectionView */ = {
|
||||||
isa = PBXFileSystemSynchronizedRootGroup;
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
exceptions = (
|
|
||||||
);
|
|
||||||
path = TTGTagCollectionView;
|
path = TTGTagCollectionView;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
|
@ -526,6 +534,7 @@
|
||||||
305A74CE2FCA8C7000227D26 /* SystemAPI.swift */,
|
305A74CE2FCA8C7000227D26 /* SystemAPI.swift */,
|
||||||
305A74CF2FCA8C7000227D26 /* UserAPI.swift */,
|
305A74CF2FCA8C7000227D26 /* UserAPI.swift */,
|
||||||
30BAB8502FCD331C00C33B5C /* GroupAPI.swift */,
|
30BAB8502FCD331C00C33B5C /* GroupAPI.swift */,
|
||||||
|
30D891F42FE22E0600E958FD /* OrderAPI.swift */,
|
||||||
);
|
);
|
||||||
path = API;
|
path = API;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -866,6 +875,7 @@
|
||||||
30A7A9102FCAEE3D00105780 /* GroupListPopView.swift */,
|
30A7A9102FCAEE3D00105780 /* GroupListPopView.swift */,
|
||||||
30D87CDE2FDFF1A100E958FD /* QuickMessageView.swift */,
|
30D87CDE2FDFF1A100E958FD /* QuickMessageView.swift */,
|
||||||
30D87CDC2FDFF07500E958FD /* InteractionView.swift */,
|
30D87CDC2FDFF07500E958FD /* InteractionView.swift */,
|
||||||
|
30CCDE4F2FE2782700F5214A /* SignIn */,
|
||||||
);
|
);
|
||||||
path = Home;
|
path = Home;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -892,10 +902,10 @@
|
||||||
305A76352FCA8C7000227D26 /* Map */ = {
|
305A76352FCA8C7000227D26 /* Map */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
30D87D032FE1336300E958FD /* Navigation */,
|
|
||||||
305A76322FCA8C7000227D26 /* CircleMember.swift */,
|
305A76322FCA8C7000227D26 /* CircleMember.swift */,
|
||||||
305A76332FCA8C7000227D26 /* MemberAnnotation.swift */,
|
305A76332FCA8C7000227D26 /* MemberAnnotation.swift */,
|
||||||
305A76342FCA8C7000227D26 /* MemberAnnotationView.swift */,
|
305A76342FCA8C7000227D26 /* MemberAnnotationView.swift */,
|
||||||
|
30D87D032FE1336300E958FD /* Navigation */,
|
||||||
);
|
);
|
||||||
path = Map;
|
path = Map;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -939,6 +949,7 @@
|
||||||
305A763B2FCA8C7000227D26 /* SystemService.swift */,
|
305A763B2FCA8C7000227D26 /* SystemService.swift */,
|
||||||
305A763C2FCA8C7000227D26 /* UserService.swift */,
|
305A763C2FCA8C7000227D26 /* UserService.swift */,
|
||||||
30BAB8522FCD337C00C33B5C /* GroupService.swift */,
|
30BAB8522FCD337C00C33B5C /* GroupService.swift */,
|
||||||
|
30D891F62FE22E6E00E958FD /* OrderService.swift */,
|
||||||
);
|
);
|
||||||
path = Service;
|
path = Service;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -1034,6 +1045,7 @@
|
||||||
305A76692FCA8C7000227D26 /* Pop */ = {
|
305A76692FCA8C7000227D26 /* Pop */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
30CCDE4D2FE26CEA00F5214A /* PayResultPopVC.swift */,
|
||||||
30EFF3BA2FD90D7600EB35D4 /* ConfirmPopVC.swift */,
|
30EFF3BA2FD90D7600EB35D4 /* ConfirmPopVC.swift */,
|
||||||
305A76642FCA8C7000227D26 /* DLAlertPopVC.swift */,
|
305A76642FCA8C7000227D26 /* DLAlertPopVC.swift */,
|
||||||
305A76652FCA8C7000227D26 /* DLCustomPopVC.swift */,
|
305A76652FCA8C7000227D26 /* DLCustomPopVC.swift */,
|
||||||
|
|
@ -1190,6 +1202,16 @@
|
||||||
path = GroupInfo;
|
path = GroupInfo;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
30CCDE4F2FE2782700F5214A /* SignIn */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
30CCDE502FE2785D00F5214A /* SignInVC.swift */,
|
||||||
|
30CCDE522FE2786600F5214A /* SignInView.swift */,
|
||||||
|
30CCDE542FE2903100F5214A /* SignInModel.swift */,
|
||||||
|
);
|
||||||
|
path = SignIn;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
30D87CD52FDF9F1900E958FD /* MQTT */ = {
|
30D87CD52FDF9F1900E958FD /* MQTT */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
|
@ -1445,10 +1467,14 @@
|
||||||
inputFileListPaths = (
|
inputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-QuickLocation/Pods-QuickLocation-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-QuickLocation/Pods-QuickLocation-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
);
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
name = "[CP] Embed Pods Frameworks";
|
name = "[CP] Embed Pods Frameworks";
|
||||||
outputFileListPaths = (
|
outputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-QuickLocation/Pods-QuickLocation-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-QuickLocation/Pods-QuickLocation-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
);
|
);
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-QuickLocation/Pods-QuickLocation-frameworks.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-QuickLocation/Pods-QuickLocation-frameworks.sh\"\n";
|
||||||
|
|
@ -1462,10 +1488,14 @@
|
||||||
inputFileListPaths = (
|
inputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-QuickLocation/Pods-QuickLocation-resources-${CONFIGURATION}-input-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-QuickLocation/Pods-QuickLocation-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
);
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
name = "[CP] Copy Pods Resources";
|
name = "[CP] Copy Pods Resources";
|
||||||
outputFileListPaths = (
|
outputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-QuickLocation/Pods-QuickLocation-resources-${CONFIGURATION}-output-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-QuickLocation/Pods-QuickLocation-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
);
|
);
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-QuickLocation/Pods-QuickLocation-resources.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-QuickLocation/Pods-QuickLocation-resources.sh\"\n";
|
||||||
|
|
@ -1579,6 +1609,7 @@
|
||||||
305A76C92FCA8C7000227D26 /* ApiManager.swift in Sources */,
|
305A76C92FCA8C7000227D26 /* ApiManager.swift in Sources */,
|
||||||
305A76CA2FCA8C7000227D26 /* AppSettings.swift in Sources */,
|
305A76CA2FCA8C7000227D26 /* AppSettings.swift in Sources */,
|
||||||
305A76CB2FCA8C7000227D26 /* Authorize.swift in Sources */,
|
305A76CB2FCA8C7000227D26 /* Authorize.swift in Sources */,
|
||||||
|
30CCDE552FE2903100F5214A /* SignInModel.swift in Sources */,
|
||||||
305A76CC2FCA8C7000227D26 /* FileTools.swift in Sources */,
|
305A76CC2FCA8C7000227D26 /* FileTools.swift in Sources */,
|
||||||
305A76CD2FCA8C7000227D26 /* Permission.swift in Sources */,
|
305A76CD2FCA8C7000227D26 /* Permission.swift in Sources */,
|
||||||
305A76CE2FCA8C7000227D26 /* RouterManager.swift in Sources */,
|
305A76CE2FCA8C7000227D26 /* RouterManager.swift in Sources */,
|
||||||
|
|
@ -1614,6 +1645,7 @@
|
||||||
30EFF3CF2FDA669800EB35D4 /* MyProfileVC.swift in Sources */,
|
30EFF3CF2FDA669800EB35D4 /* MyProfileVC.swift in Sources */,
|
||||||
30EFF3E52FDAA93400EB35D4 /* PrivacyPolicyVC.swift in Sources */,
|
30EFF3E52FDAA93400EB35D4 /* PrivacyPolicyVC.swift in Sources */,
|
||||||
305A76E22FCA8C7000227D26 /* GroupViewModel.swift in Sources */,
|
305A76E22FCA8C7000227D26 /* GroupViewModel.swift in Sources */,
|
||||||
|
30CCDE4E2FE26CEA00F5214A /* PayResultPopVC.swift in Sources */,
|
||||||
305A76E32FCA8C7000227D26 /* GroupMemberView.swift in Sources */,
|
305A76E32FCA8C7000227D26 /* GroupMemberView.swift in Sources */,
|
||||||
30BAB84F2FCD2FED00C33B5C /* InviteJoinVC.swift in Sources */,
|
30BAB84F2FCD2FED00C33B5C /* InviteJoinVC.swift in Sources */,
|
||||||
305A76E42FCA8C7000227D26 /* HomeView.swift in Sources */,
|
305A76E42FCA8C7000227D26 /* HomeView.swift in Sources */,
|
||||||
|
|
@ -1674,20 +1706,24 @@
|
||||||
305A77072FCA8C7000227D26 /* Helper.swift in Sources */,
|
305A77072FCA8C7000227D26 /* Helper.swift in Sources */,
|
||||||
305A77082FCA8C7000227D26 /* PageCollectionViewFlowLayout.swift in Sources */,
|
305A77082FCA8C7000227D26 /* PageCollectionViewFlowLayout.swift in Sources */,
|
||||||
3062E8C42FCFC90F00CEF511 /* CreateGroupVipPopView.swift in Sources */,
|
3062E8C42FCFC90F00CEF511 /* CreateGroupVipPopView.swift in Sources */,
|
||||||
|
30CCDE512FE2785D00F5214A /* SignInVC.swift in Sources */,
|
||||||
305A77092FCA8C7000227D26 /* PageContentView.swift in Sources */,
|
305A77092FCA8C7000227D26 /* PageContentView.swift in Sources */,
|
||||||
305A770A2FCA8C7000227D26 /* PageStyle.swift in Sources */,
|
305A770A2FCA8C7000227D26 /* PageStyle.swift in Sources */,
|
||||||
305A770B2FCA8C7000227D26 /* PageTitleView.swift in Sources */,
|
305A770B2FCA8C7000227D26 /* PageTitleView.swift in Sources */,
|
||||||
305A770C2FCA8C7000227D26 /* PageView.swift in Sources */,
|
305A770C2FCA8C7000227D26 /* PageView.swift in Sources */,
|
||||||
305A770D2FCA8C7000227D26 /* PageViewManager.swift in Sources */,
|
305A770D2FCA8C7000227D26 /* PageViewManager.swift in Sources */,
|
||||||
|
30D891F52FE22E0600E958FD /* OrderAPI.swift in Sources */,
|
||||||
307073EA2FD2715A004C37CC /* GroupChatViewModel.swift in Sources */,
|
307073EA2FD2715A004C37CC /* GroupChatViewModel.swift in Sources */,
|
||||||
305A770E2FCA8C7000227D26 /* DLAlertPopVC.swift in Sources */,
|
305A770E2FCA8C7000227D26 /* DLAlertPopVC.swift in Sources */,
|
||||||
305A770F2FCA8C7000227D26 /* DLCustomPopVC.swift in Sources */,
|
305A770F2FCA8C7000227D26 /* DLCustomPopVC.swift in Sources */,
|
||||||
30EFF29B2FD668C900EB35D4 /* VoiceRecordView.swift in Sources */,
|
30EFF29B2FD668C900EB35D4 /* VoiceRecordView.swift in Sources */,
|
||||||
|
30CCDE532FE2786600F5214A /* SignInView.swift in Sources */,
|
||||||
305A77102FCA8C7000227D26 /* DLSheetPopVC.swift in Sources */,
|
305A77102FCA8C7000227D26 /* DLSheetPopVC.swift in Sources */,
|
||||||
30EFF3D32FDA69F400EB35D4 /* AvatarIconListView.swift in Sources */,
|
30EFF3D32FDA69F400EB35D4 /* AvatarIconListView.swift in Sources */,
|
||||||
30EFF3B72FD8F86200EB35D4 /* ReviewMemberListVM.swift in Sources */,
|
30EFF3B72FD8F86200EB35D4 /* ReviewMemberListVM.swift in Sources */,
|
||||||
305A77112FCA8C7000227D26 /* DLViewTransition.m in Sources */,
|
305A77112FCA8C7000227D26 /* DLViewTransition.m in Sources */,
|
||||||
3062E8BA2FCEAC6500CEF511 /* CreateGroupView.swift in Sources */,
|
3062E8BA2FCEAC6500CEF511 /* CreateGroupView.swift in Sources */,
|
||||||
|
30D891F72FE22E6E00E958FD /* OrderService.swift in Sources */,
|
||||||
305A77192FCA8C7000227D26 /* CollectionHFlowLayout.swift in Sources */,
|
305A77192FCA8C7000227D26 /* CollectionHFlowLayout.swift in Sources */,
|
||||||
305A771A2FCA8C7000227D26 /* JJPageControl.swift in Sources */,
|
305A771A2FCA8C7000227D26 /* JJPageControl.swift in Sources */,
|
||||||
305A771B2FCA8C7000227D26 /* ReusableView.swift in Sources */,
|
305A771B2FCA8C7000227D26 /* ReusableView.swift in Sources */,
|
||||||
|
|
@ -1730,7 +1766,7 @@
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_TEAM = 7LP48T8ZJE;
|
DEVELOPMENT_TEAM = XSJJKSY9FB;
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = "$(inherited)";
|
ENABLE_USER_SCRIPT_SANDBOXING = "$(inherited)";
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = QuickLocation/Info.plist;
|
INFOPLIST_FILE = QuickLocation/Info.plist;
|
||||||
|
|
@ -1779,7 +1815,7 @@
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_TEAM = 7LP48T8ZJE;
|
DEVELOPMENT_TEAM = XSJJKSY9FB;
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = "$(inherited)";
|
ENABLE_USER_SCRIPT_SANDBOXING = "$(inherited)";
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = QuickLocation/Info.plist;
|
INFOPLIST_FILE = QuickLocation/Info.plist;
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,22 @@
|
||||||
uuid = "AE547311-A826-480F-B1ED-BD6B815729FA"
|
uuid = "AE547311-A826-480F-B1ED-BD6B815729FA"
|
||||||
type = "0"
|
type = "0"
|
||||||
version = "2.0">
|
version = "2.0">
|
||||||
|
<Breakpoints>
|
||||||
|
<BreakpointProxy
|
||||||
|
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||||
|
<BreakpointContent
|
||||||
|
uuid = "AA447600-D860-4876-A728-F18CC2D566FC"
|
||||||
|
shouldBeEnabled = "Yes"
|
||||||
|
ignoreCount = "0"
|
||||||
|
continueAfterRunningActions = "No"
|
||||||
|
filePath = "QuickLocation/AppDelegate.swift"
|
||||||
|
startingColumnNumber = "9223372036854775807"
|
||||||
|
endingColumnNumber = "9223372036854775807"
|
||||||
|
startingLineNumber = "70"
|
||||||
|
endingLineNumber = "70"
|
||||||
|
landmarkName = "application(_:open:options:)"
|
||||||
|
landmarkType = "7">
|
||||||
|
</BreakpointContent>
|
||||||
|
</BreakpointProxy>
|
||||||
|
</Breakpoints>
|
||||||
</Bucket>
|
</Bucket>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
//
|
||||||
|
// OrderAPI.swift
|
||||||
|
// QuickLocation
|
||||||
|
//
|
||||||
|
// Created by 八条 on 2026/6/17.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Moya
|
||||||
|
import SwiftyUserDefaults
|
||||||
|
internal import Alamofire
|
||||||
|
|
||||||
|
/// 订单API
|
||||||
|
enum OrderAPI {
|
||||||
|
/// 充值内容
|
||||||
|
/// - Parameters:
|
||||||
|
/// - type: 类型 member
|
||||||
|
case rechargeInfo(type: String)
|
||||||
|
|
||||||
|
/// 支付参数
|
||||||
|
/// - Parameters:
|
||||||
|
/// - goodsId: 商品ID
|
||||||
|
/// - payType: alipay、weixin
|
||||||
|
/// - source: center
|
||||||
|
/// - extra: 额外参数
|
||||||
|
case orderPayParams(goodsId: String, payType: String, source: String, extra: [String:Any]=[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
extension OrderAPI: MultiTargetProtocol {
|
||||||
|
|
||||||
|
var path: String {
|
||||||
|
switch self {
|
||||||
|
case .rechargeInfo:
|
||||||
|
return "api/order/goods"
|
||||||
|
case .orderPayParams:
|
||||||
|
return "api/order"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var method: Moya.Method {
|
||||||
|
switch self {
|
||||||
|
case .rechargeInfo:
|
||||||
|
return .get
|
||||||
|
default:
|
||||||
|
return .post
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var task: Moya.Task {
|
||||||
|
switch self {
|
||||||
|
case let .rechargeInfo(type):
|
||||||
|
var params = Parameters()
|
||||||
|
params["type"] = type
|
||||||
|
return .requestParameters(parameters: params, encoding: URLEncoding())
|
||||||
|
|
||||||
|
case let .orderPayParams(goodsId, payType, source, extra):
|
||||||
|
var params = Parameters()
|
||||||
|
params["goods_id"] = goodsId
|
||||||
|
params["pay_type"] = payType
|
||||||
|
params["source"] = source
|
||||||
|
params["pay_source"] = "app"
|
||||||
|
params["extra"] = extra
|
||||||
|
return .requestParameters(parameters: params, encoding: JSONEncoding())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -18,11 +18,6 @@ enum SystemAPI {
|
||||||
/// - phone: 手机号
|
/// - phone: 手机号
|
||||||
case sendCode(phone: String)
|
case sendCode(phone: String)
|
||||||
|
|
||||||
/// 充值内容
|
|
||||||
/// - Parameters:
|
|
||||||
/// - type: 类型 member
|
|
||||||
case rechargeInfo(type: String)
|
|
||||||
|
|
||||||
/// 微信客服
|
/// 微信客服
|
||||||
case wechatService
|
case wechatService
|
||||||
}
|
}
|
||||||
|
|
@ -35,8 +30,6 @@ extension SystemAPI: MultiTargetProtocol {
|
||||||
return "api/user/config"
|
return "api/user/config"
|
||||||
case .sendCode:
|
case .sendCode:
|
||||||
return "api/user/sms/code"
|
return "api/user/sms/code"
|
||||||
case .rechargeInfo:
|
|
||||||
return "api/order/goods"
|
|
||||||
case .wechatService:
|
case .wechatService:
|
||||||
return "api/weixin/service"
|
return "api/weixin/service"
|
||||||
}
|
}
|
||||||
|
|
@ -44,7 +37,7 @@ extension SystemAPI: MultiTargetProtocol {
|
||||||
|
|
||||||
var method: Moya.Method {
|
var method: Moya.Method {
|
||||||
switch self {
|
switch self {
|
||||||
case .userConfig, .rechargeInfo, .wechatService:
|
case .userConfig, .wechatService:
|
||||||
return .get
|
return .get
|
||||||
case .sendCode:
|
case .sendCode:
|
||||||
return .post
|
return .post
|
||||||
|
|
@ -61,11 +54,6 @@ extension SystemAPI: MultiTargetProtocol {
|
||||||
params["phone"] = phone
|
params["phone"] = phone
|
||||||
return .requestParameters(parameters: params, encoding: JSONEncoding())
|
return .requestParameters(parameters: params, encoding: JSONEncoding())
|
||||||
|
|
||||||
case let .rechargeInfo(type):
|
|
||||||
var params = Parameters()
|
|
||||||
params["type"] = type
|
|
||||||
return .requestParameters(parameters: params, encoding: URLEncoding())
|
|
||||||
|
|
||||||
case .wechatService:
|
case .wechatService:
|
||||||
return .requestParameters(parameters: parameters, encoding: URLEncoding())
|
return .requestParameters(parameters: parameters, encoding: URLEncoding())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,9 @@ enum UserAPI {
|
||||||
/// 用户IM Token
|
/// 用户IM Token
|
||||||
case imToken
|
case imToken
|
||||||
|
|
||||||
|
/// 签到信息
|
||||||
|
case signInInfo
|
||||||
|
|
||||||
/// 更换手机号
|
/// 更换手机号
|
||||||
case changePhone(timestamp: String, phone: String, code: String)
|
case changePhone(timestamp: String, phone: String, code: String)
|
||||||
|
|
||||||
|
|
@ -62,6 +65,8 @@ extension UserAPI: MultiTargetProtocol {
|
||||||
return "api/user"
|
return "api/user"
|
||||||
case .imToken:
|
case .imToken:
|
||||||
return "mapi/openim/user/token/get"
|
return "mapi/openim/user/token/get"
|
||||||
|
case .signInInfo:
|
||||||
|
return "mapi/user/signin"
|
||||||
case .changePhone:
|
case .changePhone:
|
||||||
return "api/user"
|
return "api/user"
|
||||||
case .setHeadPic:
|
case .setHeadPic:
|
||||||
|
|
@ -81,7 +86,7 @@ extension UserAPI: MultiTargetProtocol {
|
||||||
|
|
||||||
var method: Moya.Method {
|
var method: Moya.Method {
|
||||||
switch self {
|
switch self {
|
||||||
case .userInfo:
|
case .userInfo, .signInInfo:
|
||||||
return .get
|
return .get
|
||||||
case .changePhone, .setGender:
|
case .changePhone, .setGender:
|
||||||
return .put
|
return .put
|
||||||
|
|
@ -110,6 +115,9 @@ extension UserAPI: MultiTargetProtocol {
|
||||||
params["force"] = true
|
params["force"] = true
|
||||||
return .requestParameters(parameters: params, encoding: JSONEncoding())
|
return .requestParameters(parameters: params, encoding: JSONEncoding())
|
||||||
|
|
||||||
|
case .signInInfo:
|
||||||
|
return .requestParameters(parameters: Parameters(), encoding: URLEncoding())
|
||||||
|
|
||||||
case let .changePhone(timestamp, phone, code):
|
case let .changePhone(timestamp, phone, code):
|
||||||
var params = Parameters()
|
var params = Parameters()
|
||||||
params["phone_timestamp"] = timestamp
|
params["phone_timestamp"] = timestamp
|
||||||
|
|
|
||||||
|
|
@ -67,9 +67,25 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
|
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
|
||||||
|
print("📱 application open url: \(url.absoluteString) host: \(url.host ?? "")")
|
||||||
|
// 处理支付宝支付结果(不限制 host,适应新版 SDK)
|
||||||
|
if url.scheme?.hasPrefix("Alipay") == true || url.host == "safepay" {
|
||||||
|
AlipaySDK.defaultService().processOrder(withPaymentResult: url) { resultDic in
|
||||||
|
print("📱 Alipay callback: \(resultDic ?? [:])")
|
||||||
|
guard let result = resultDic,
|
||||||
|
let resultStatus = result["resultStatus"] as? String,
|
||||||
|
resultStatus != "6001" else { return }
|
||||||
|
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
else if url.host == "pay" {
|
||||||
return WXApi.handleOpen(url, delegate: self)
|
return WXApi.handleOpen(url, delegate: self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func setupLocation() {
|
func setupLocation() {
|
||||||
let manager = AuthorizeManager.manager(type: .locationWhenInUse)
|
let manager = AuthorizeManager.manager(type: .locationWhenInUse)
|
||||||
if manager?.authorizeStatus() != .authorized {
|
if manager?.authorizeStatus() != .authorized {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Group 1545@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Group 1545@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Group_2075@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Group_2075@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "failure@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "failure@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "success@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "success@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
},
|
||||||
|
"properties" : {
|
||||||
|
"provides-namespace" : true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Group 2404@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Group 2404@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
QuickLocation/Assets.xcassets/SignIn/signIn_text.imageset/Group 2404@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
QuickLocation/Assets.xcassets/SignIn/signIn_text.imageset/Group 2404@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Group_2400@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Group_2400@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "today_signin@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "today_signin@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
QuickLocation/Assets.xcassets/SignIn/today_text.imageset/today_signin@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
QuickLocation/Assets.xcassets/SignIn/today_text.imageset/today_signin@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 19 KiB |
|
|
@ -1,22 +0,0 @@
|
||||||
{
|
|
||||||
"images": [
|
|
||||||
{
|
|
||||||
"idiom": "universal",
|
|
||||||
"scale": "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "map_avatar_1@2x.png",
|
|
||||||
"idiom": "universal",
|
|
||||||
"scale": "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "map_avatar_1@3x.png",
|
|
||||||
"idiom": "universal",
|
|
||||||
"scale": "3x"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"info": {
|
|
||||||
"author": "xcode",
|
|
||||||
"version": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 765 B |
|
Before Width: | Height: | Size: 8.1 KiB |
|
|
@ -1,22 +0,0 @@
|
||||||
{
|
|
||||||
"images": [
|
|
||||||
{
|
|
||||||
"idiom": "universal",
|
|
||||||
"scale": "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "map_avatar_2@2x.png",
|
|
||||||
"idiom": "universal",
|
|
||||||
"scale": "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "map_avatar_2@3x.png",
|
|
||||||
"idiom": "universal",
|
|
||||||
"scale": "3x"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"info": {
|
|
||||||
"author": "xcode",
|
|
||||||
"version": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 761 B |
|
Before Width: | Height: | Size: 8.1 KiB |
|
|
@ -1,22 +0,0 @@
|
||||||
{
|
|
||||||
"images": [
|
|
||||||
{
|
|
||||||
"idiom": "universal",
|
|
||||||
"scale": "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "map_avatar_3@2x.png",
|
|
||||||
"idiom": "universal",
|
|
||||||
"scale": "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "map_avatar_3@3x.png",
|
|
||||||
"idiom": "universal",
|
|
||||||
"scale": "3x"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"info": {
|
|
||||||
"author": "xcode",
|
|
||||||
"version": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 773 B |
|
Before Width: | Height: | Size: 8.8 KiB |
|
|
@ -1,22 +0,0 @@
|
||||||
{
|
|
||||||
"images": [
|
|
||||||
{
|
|
||||||
"idiom": "universal",
|
|
||||||
"scale": "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "map_avatar_4@2x.png",
|
|
||||||
"idiom": "universal",
|
|
||||||
"scale": "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "map_avatar_4@3x.png",
|
|
||||||
"idiom": "universal",
|
|
||||||
"scale": "3x"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"info": {
|
|
||||||
"author": "xcode",
|
|
||||||
"version": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 766 B |
|
Before Width: | Height: | Size: 8.4 KiB |
|
|
@ -1,22 +0,0 @@
|
||||||
{
|
|
||||||
"images": [
|
|
||||||
{
|
|
||||||
"idiom": "universal",
|
|
||||||
"scale": "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "map_avatar_5@2x.png",
|
|
||||||
"idiom": "universal",
|
|
||||||
"scale": "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "map_avatar_5@3x.png",
|
|
||||||
"idiom": "universal",
|
|
||||||
"scale": "3x"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"info": {
|
|
||||||
"author": "xcode",
|
|
||||||
"version": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 772 B |
|
Before Width: | Height: | Size: 8.6 KiB |
|
|
@ -28,6 +28,8 @@ extension Notification.Name {
|
||||||
static let RefreshUserConfigNotification = Notification.Name("RefreshUserConfigNotification")
|
static let RefreshUserConfigNotification = Notification.Name("RefreshUserConfigNotification")
|
||||||
/// 刷新用户圈子数据
|
/// 刷新用户圈子数据
|
||||||
static let RefreshGroupInfoNotification = Notification.Name("RefreshGroupInfoNotification")
|
static let RefreshGroupInfoNotification = Notification.Name("RefreshGroupInfoNotification")
|
||||||
|
/// 支付宝/微信支付结果回调
|
||||||
|
static let RequestOrderPayStatusNotification = Notification.Name("RequestOrderPayStatusNotification")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,16 @@
|
||||||
<dict>
|
<dict>
|
||||||
<key>CFBundleURLTypes</key>
|
<key>CFBundleURLTypes</key>
|
||||||
<array>
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Editor</string>
|
||||||
|
<key>CFBundleURLName</key>
|
||||||
|
<string>alipay</string>
|
||||||
|
<key>CFBundleURLSchemes</key>
|
||||||
|
<array>
|
||||||
|
<string>Alipay2021005185689681</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
<dict>
|
<dict>
|
||||||
<key>CFBundleTypeRole</key>
|
<key>CFBundleTypeRole</key>
|
||||||
<string>Editor</string>
|
<string>Editor</string>
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,14 @@ struct MqttLocation: Codable {
|
||||||
let points: [Points]
|
let points: [Points]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 签到上报数据
|
||||||
|
struct MqttSignIn: Codable {
|
||||||
|
let topic: String?
|
||||||
|
let latitude: Double
|
||||||
|
let longitude: Double
|
||||||
|
let address: String
|
||||||
|
}
|
||||||
|
|
||||||
/// MQTT 收到的位置消息(接收解析用)
|
/// MQTT 收到的位置消息(接收解析用)
|
||||||
struct MqttIncomingMessage: Decodable {
|
struct MqttIncomingMessage: Decodable {
|
||||||
let type: String?
|
let type: String?
|
||||||
|
|
@ -55,6 +63,8 @@ struct MqttIncomingMessage: Decodable {
|
||||||
struct MqttIncomingData: Decodable {
|
struct MqttIncomingData: Decodable {
|
||||||
let points: [Points]?
|
let points: [Points]?
|
||||||
let battery: String?
|
let battery: String?
|
||||||
|
let index: Int?
|
||||||
|
let group_key: String?
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - MQTTService
|
// MARK: - MQTTService
|
||||||
|
|
@ -98,11 +108,24 @@ final class MQTTService: NSObject {
|
||||||
let mqtt = CocoaMQTT5(clientID: clientID, host: host, port: port)
|
let mqtt = CocoaMQTT5(clientID: clientID, host: host, port: port)
|
||||||
mqtt.username = userName
|
mqtt.username = userName
|
||||||
mqtt.password = password
|
mqtt.password = password
|
||||||
mqtt.keepAlive = 60
|
mqtt.cleanSession = true
|
||||||
|
mqtt.keepAlive = 30
|
||||||
mqtt.autoReconnect = true
|
mqtt.autoReconnect = true
|
||||||
mqtt.autoReconnectTimeInterval = 5
|
mqtt.autoReconnectTimeInterval = 5
|
||||||
mqtt.delegate = self
|
mqtt.delegate = self
|
||||||
mqtt.logLevel = .warning
|
mqtt.logLevel = .warning
|
||||||
|
// MQTT 5 连接属性(对应 Android 端配置)
|
||||||
|
let connProps = MqttConnectProperties()
|
||||||
|
connProps.sessionExpiryInterval = 30
|
||||||
|
connProps.receiveMaximum = 10
|
||||||
|
connProps.maximumPacketSize = 10240
|
||||||
|
connProps.topicAliasMaximum = 0
|
||||||
|
mqtt.connectProperties = connProps
|
||||||
|
// Will 消息
|
||||||
|
let will = CocoaMQTT5Message(topic: "willtopic", payload: [])
|
||||||
|
will.qos = .qos1
|
||||||
|
will.retained = false
|
||||||
|
mqtt.willMessage = will
|
||||||
|
|
||||||
self.mqtt = mqtt
|
self.mqtt = mqtt
|
||||||
_ = mqtt.connect()
|
_ = mqtt.connect()
|
||||||
|
|
@ -129,6 +152,9 @@ final class MQTTService: NSObject {
|
||||||
/// - callback: 可选,该 topic 的专用回调,收到消息时优先于此回调
|
/// - callback: 可选,该 topic 的专用回调,收到消息时优先于此回调
|
||||||
func subscribe(topic: String, qos: CocoaMQTTQoS = .qos1, callback: ((CocoaMQTT5Message) -> Void)? = nil) {
|
func subscribe(topic: String, qos: CocoaMQTTQoS = .qos1, callback: ((CocoaMQTT5Message) -> Void)? = nil) {
|
||||||
let subscription = MqttSubscription(topic: topic, qos: qos)
|
let subscription = MqttSubscription(topic: topic, qos: qos)
|
||||||
|
subscription.noLocal = true
|
||||||
|
subscription.retainAsPublished = true
|
||||||
|
subscription.retainHandling = .none
|
||||||
mqtt?.subscribe([subscription])
|
mqtt?.subscribe([subscription])
|
||||||
if let cb = callback {
|
if let cb = callback {
|
||||||
topicCallbacks[topic] = cb
|
topicCallbacks[topic] = cb
|
||||||
|
|
@ -199,6 +225,22 @@ final class MQTTService: NSObject {
|
||||||
|
|
||||||
publish(topic: "\(topic)\(AppContextManager.shared.userId)", message: payload.toJsonString())
|
publish(topic: "\(topic)\(AppContextManager.shared.userId)", message: payload.toJsonString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - 签到
|
||||||
|
func reportSignIn(lat: Double, lon: Double, addr: String) {
|
||||||
|
let signIn = MqttSignIn(topic: nil, latitude: lat, longitude: lon, address: addr)
|
||||||
|
guard let jsonData = try? JSONEncoder().encode(signIn),
|
||||||
|
let dataDict = try? JSONSerialization.jsonObject(with: jsonData) as? [String: Any]
|
||||||
|
else { return }
|
||||||
|
|
||||||
|
let payload: [String: Any] = [
|
||||||
|
"type": MqttType.signIn.rawValue,
|
||||||
|
"data": dataDict,
|
||||||
|
"extra": "",
|
||||||
|
"sort": ""
|
||||||
|
]
|
||||||
|
publish(topic: "\(topic)\(AppContextManager.shared.userId)", message: payload.toJsonString())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - CocoaMQTT5Delegate
|
// MARK: - CocoaMQTT5Delegate
|
||||||
|
|
@ -207,6 +249,8 @@ extension MQTTService: CocoaMQTT5Delegate {
|
||||||
func mqtt5(_ mqtt5: CocoaMQTT5, didConnectAck ack: CocoaMQTTCONNACKReasonCode, connAckData: MqttDecodeConnAck?) {
|
func mqtt5(_ mqtt5: CocoaMQTT5, didConnectAck ack: CocoaMQTTCONNACKReasonCode, connAckData: MqttDecodeConnAck?) {
|
||||||
isConnected = true
|
isConnected = true
|
||||||
print("MQTT5 connected: \(ack)")
|
print("MQTT5 connected: \(ack)")
|
||||||
|
// 订阅基础 topic,接收 signIn/join/leave 等非位置消息
|
||||||
|
subscribe(topic: topic)
|
||||||
onConnected?()
|
onConnected?()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,4 +25,7 @@
|
||||||
// 微信
|
// 微信
|
||||||
#import <WechatOpenSDK/WXApi.h>
|
#import <WechatOpenSDK/WXApi.h>
|
||||||
|
|
||||||
|
// 支付宝
|
||||||
|
#import <AlipaySDK/AlipaySDK.h>
|
||||||
|
|
||||||
#endif /* QuickLocation_Bridging_Header_h */
|
#endif /* QuickLocation_Bridging_Header_h */
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,10 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict/>
|
<dict>
|
||||||
|
<key>com.apple.developer.associated-domains</key>
|
||||||
|
<array>
|
||||||
|
<string>applinks:smartdrive.zuom8.cn</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
|
||||||
|
|
@ -258,6 +258,7 @@ class GroupMemberCell: UITableViewCell {
|
||||||
.centerY(locationLab)
|
.centerY(locationLab)
|
||||||
.width(10)
|
.width(10)
|
||||||
.height(10)
|
.height(10)
|
||||||
|
.right(80, relation: .greaterThanOrEqual)
|
||||||
|
|
||||||
tagView.layoutChain
|
tagView.layoutChain
|
||||||
.leftToRightOfView(nameLab, offset: 4)
|
.leftToRightOfView(nameLab, offset: 4)
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,7 @@ class HomeView: UIView {
|
||||||
groupView.addSubview(groupNameLab)
|
groupView.addSubview(groupNameLab)
|
||||||
groupView.addSubview(groupArrowIconView)
|
groupView.addSubview(groupArrowIconView)
|
||||||
addSubview(messageView)
|
addSubview(messageView)
|
||||||
|
addSubview(messageStackView)
|
||||||
addSubview(toolsView)
|
addSubview(toolsView)
|
||||||
addSubview(searchLottieView)
|
addSubview(searchLottieView)
|
||||||
addSubview(locationView)
|
addSubview(locationView)
|
||||||
|
|
@ -167,6 +168,10 @@ class HomeView: UIView {
|
||||||
.width(36)
|
.width(36)
|
||||||
.height(36)
|
.height(36)
|
||||||
|
|
||||||
|
messageStackView.layoutChain
|
||||||
|
.topToBottomOfView(messageView, offset: 23)
|
||||||
|
.edgesHorzontal(15)
|
||||||
|
|
||||||
toolsView.layoutChain
|
toolsView.layoutChain
|
||||||
.left(23)
|
.left(23)
|
||||||
.centerY()
|
.centerY()
|
||||||
|
|
@ -441,6 +446,50 @@ class HomeView: UIView {
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
lazy var messageStackView: UIStackView = {
|
||||||
|
let view = UIStackView(arrangedSubviews: [noticeView, messageBubbleView])
|
||||||
|
view.axis = .vertical
|
||||||
|
view.alignment = .leading
|
||||||
|
view.spacing = 15
|
||||||
|
view.backgroundColor = .clear
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
// MARK: - 公告
|
||||||
|
lazy var noticeView: UIView = {
|
||||||
|
let view = UIView()
|
||||||
|
view.isHidden = true
|
||||||
|
|
||||||
|
view.layoutChain
|
||||||
|
.height(22)
|
||||||
|
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
// MARK: - 消息气泡
|
||||||
|
lazy var messageBubbleView: UIView = {
|
||||||
|
let view = UIView()
|
||||||
|
view.backgroundColor = .white.withAlphaComponent(0.8)
|
||||||
|
view.cornerRadius = 10
|
||||||
|
view.isHidden = true
|
||||||
|
|
||||||
|
view.addSubview(messageLab)
|
||||||
|
messageLab.layoutChain
|
||||||
|
.edges(all: 12)
|
||||||
|
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var messageLab: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.font = .systemFont(ofSize: 12, weight: .medium)
|
||||||
|
label.textColor = .clear
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
// MARK: - 表情展示
|
||||||
|
|
||||||
|
|
||||||
// MARK: - 侧边工具栏
|
// MARK: - 侧边工具栏
|
||||||
lazy var toolsView: UIStackView = {
|
lazy var toolsView: UIStackView = {
|
||||||
let view = UIStackView(arrangedSubviews: [bubbleView, signInView, sosView])
|
let view = UIStackView(arrangedSubviews: [bubbleView, signInView, sosView])
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,14 @@ class HomeViewController: BaseViewController {
|
||||||
// MARK: - Actions
|
// MARK: - Actions
|
||||||
private func reactiveAction() {
|
private func reactiveAction() {
|
||||||
|
|
||||||
|
// 签到
|
||||||
|
rootView.signInView.rx.tapGesture.subscribe { _ in
|
||||||
|
let vc = SignInVC(currentUserCoord: self.lastLocation?.coordinate)
|
||||||
|
vc.isNeedLogin = true
|
||||||
|
AppRouter.push(vc)
|
||||||
|
}.disposed(by: disposeBag)
|
||||||
|
|
||||||
|
// 顶部圈子
|
||||||
rootView.groupView.rx.tapGesture.subscribe { _ in
|
rootView.groupView.rx.tapGesture.subscribe { _ in
|
||||||
guard let groupModel = self.viewModel.groupModel else { return }
|
guard let groupModel = self.viewModel.groupModel else { return }
|
||||||
let groupViewFrame = self.view.convert(self.rootView.groupView.frame, from: self.rootView)
|
let groupViewFrame = self.view.convert(self.rootView.groupView.frame, from: self.rootView)
|
||||||
|
|
@ -151,14 +159,17 @@ class HomeViewController: BaseViewController {
|
||||||
}
|
}
|
||||||
}.disposed(by: disposeBag)
|
}.disposed(by: disposeBag)
|
||||||
|
|
||||||
|
// 圈子成员列表 刷新列表
|
||||||
rootView.groupMemberView.refreshBtn.rx.tap.subscribe(onNext: { _ in
|
rootView.groupMemberView.refreshBtn.rx.tap.subscribe(onNext: { _ in
|
||||||
self.requestGroupInfo()
|
self.requestGroupInfo()
|
||||||
}).disposed(by: disposeBag)
|
}).disposed(by: disposeBag)
|
||||||
|
|
||||||
|
// 圈子成员列表 邀请加入
|
||||||
rootView.groupMemberView.inviteJoinBtn.rx.tap.subscribe(onNext: { _ in
|
rootView.groupMemberView.inviteJoinBtn.rx.tap.subscribe(onNext: { _ in
|
||||||
AppRouter.push(Route.inviteJoin, userInfo: ["groupInfo": self.viewModel.groupInfo])
|
AppRouter.push(Route.inviteJoin, userInfo: ["groupInfo": self.viewModel.groupInfo])
|
||||||
}).disposed(by: disposeBag)
|
}).disposed(by: disposeBag)
|
||||||
|
|
||||||
|
// 地图回到自己
|
||||||
rootView.locationView.rx.tapGesture.subscribe { _ in
|
rootView.locationView.rx.tapGesture.subscribe { _ in
|
||||||
if let ann = self.currentUserAnnotation {
|
if let ann = self.currentUserAnnotation {
|
||||||
self.rootView.mapView.setCenter(ann.coordinate, animated: true)
|
self.rootView.mapView.setCenter(ann.coordinate, animated: true)
|
||||||
|
|
@ -193,15 +204,6 @@ class HomeViewController: BaseViewController {
|
||||||
let vc = NavigationVC(member: member, currentUserCoord: userCoord, groupName: groupName, groupIcon: "\(iconIndex)")
|
let vc = NavigationVC(member: member, currentUserCoord: userCoord, groupName: groupName, groupIcon: "\(iconIndex)")
|
||||||
self.navigationController?.pushViewController(vc, animated: true)
|
self.navigationController?.pushViewController(vc, animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MQTT 接收
|
|
||||||
MQTTService.shared.subscribe(topic: "smartdrive/") { message in
|
|
||||||
guard let msgStr = message.string,
|
|
||||||
let data = msgStr.data(using: .utf8),
|
|
||||||
let msg = try? JSONDecoder().decode(MqttIncomingMessage.self, from: data)
|
|
||||||
else { return }
|
|
||||||
print("📩 收到消息 -> 主题:\(message.topic),内容:\(msg)")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func bindViewModel() {
|
private func bindViewModel() {
|
||||||
|
|
@ -438,19 +440,23 @@ extension HomeViewController {
|
||||||
subscribedMemberIds = newIds
|
subscribedMemberIds = newIds
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 处理成员位置更新(从 topic 提取 userId,更新地图标注)
|
/// 处理 MQTT 消息(按 type 分发)
|
||||||
private func handleMemberLocation(topic: String, payload: String?) {
|
private func handleMemberLocation(topic: String, payload: String?) {
|
||||||
|
print("📩 收到消息 -> 主题:\(topic),内容:\(payload)")
|
||||||
guard let payload = payload,
|
guard let payload = payload,
|
||||||
let data = payload.data(using: .utf8),
|
let data = payload.data(using: .utf8),
|
||||||
let msg = try? JSONDecoder().decode(MqttIncomingMessage.self, from: data),
|
let msg = try? JSONDecoder().decode(MqttIncomingMessage.self, from: data)
|
||||||
let firstPoint = msg.data?.points?.first
|
|
||||||
else { return }
|
else { return }
|
||||||
print("📩 收到消息 -> 主题:\(topic),内容:\(msg)")
|
|
||||||
let userId = topic.replacingOccurrences(of: "smartdrive/", with: "")
|
let userId = topic.replacingOccurrences(of: "smartdrive/", with: "")
|
||||||
|
|
||||||
|
switch msg.type {
|
||||||
|
case "track":
|
||||||
|
guard let firstPoint = msg.data?.points?.first else { return }
|
||||||
let coord = CLLocationCoordinate2D(latitude: firstPoint.lat, longitude: firstPoint.lon)
|
let coord = CLLocationCoordinate2D(latitude: firstPoint.lat, longitude: firstPoint.lon)
|
||||||
guard CLLocationCoordinate2DIsValid(coord) else { return }
|
guard CLLocationCoordinate2DIsValid(coord) else { return }
|
||||||
|
|
||||||
// 根据 time 字段判断在线状态(毫秒时间戳)
|
// 根据 time 字段判断在线状态
|
||||||
let nowMs = Date().timeIntervalSince1970 * 1000
|
let nowMs = Date().timeIntervalSince1970 * 1000
|
||||||
let msgTimeMs = Double(firstPoint.time)
|
let msgTimeMs = Double(firstPoint.time)
|
||||||
let diffSec = (nowMs - msgTimeMs) / 1000
|
let diffSec = (nowMs - msgTimeMs) / 1000
|
||||||
|
|
@ -475,6 +481,40 @@ extension HomeViewController {
|
||||||
self.removeAnnotation(userId: userId)
|
self.removeAnnotation(userId: userId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case "disconnect":
|
||||||
|
self.removeAnnotation(userId: userId)
|
||||||
|
viewModel.setMemberOffline(userId: userId)
|
||||||
|
updateOnlineCount()
|
||||||
|
|
||||||
|
case "emote":
|
||||||
|
guard let index = msg.data?.index else { break }
|
||||||
|
if index >= 30 { // 文字
|
||||||
|
guard let gk = msg.data?.group_key, gk.components(separatedBy: "/").count >= 2 else { break }
|
||||||
|
let parts = gk.components(separatedBy: "/")
|
||||||
|
let emoteUserId = parts[1]
|
||||||
|
let textIdx = index % 10
|
||||||
|
let texts = QuickMessageView.messageList
|
||||||
|
guard textIdx < texts.count else { break }
|
||||||
|
let nickName = self.viewModel.getUserNickName(id: emoteUserId)
|
||||||
|
let tip = nickName
|
||||||
|
let fullText = tip + "对你说:" + texts[textIdx]
|
||||||
|
let attr = NSMutableAttributedString(string: fullText)
|
||||||
|
attr.addAttribute(.font, value: UIFont.systemFont(ofSize: 12, weight: .medium), range: NSRange(location: 0, length: fullText.count))
|
||||||
|
attr.addAttribute(.foregroundColor, value: UIColor(hexStr: "#16B3FF"), range: NSRange(location: 0, length: tip.count))
|
||||||
|
attr.addAttribute(.foregroundColor, value: UIColor(hexStr: "#333333"), range: NSRange(location: tip.count, length: texts[textIdx].count))
|
||||||
|
DispatchQueue.main.async { [weak self] in
|
||||||
|
guard let self = self else { return }
|
||||||
|
self.rootView.messageLab.attributedText = attr
|
||||||
|
self.rootView.messageBubbleView.isHidden = false
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
|
||||||
|
self.rootView.messageBubbleView.isHidden = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
print("📩 未处理 type=\(msg.type ?? "")")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 更新成员在线计数显示
|
/// 更新成员在线计数显示
|
||||||
|
|
@ -520,7 +560,6 @@ extension HomeViewController {
|
||||||
}
|
}
|
||||||
let newAnn = MemberAnnotation(member: oldMember)
|
let newAnn = MemberAnnotation(member: oldMember)
|
||||||
mapView.addAnnotation(newAnn)
|
mapView.addAnnotation(newAnn)
|
||||||
print("📌 updateAnnotation userId=\(userId) coord=\(coordinate.latitude),\(coordinate.longitude)")
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,10 @@ class HomeViewModel {
|
||||||
return model.default_group_key.contains(id)
|
return model.default_group_key.contains(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getUserNickName(id: String) -> String {
|
||||||
|
memberList.first { $0.user_id == id }?.nick_name ?? ""
|
||||||
|
}
|
||||||
|
|
||||||
var memberList: [GroupMemberModel] = [] {
|
var memberList: [GroupMemberModel] = [] {
|
||||||
didSet {
|
didSet {
|
||||||
var tempList = memberList
|
var tempList = memberList
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import TagListView
|
||||||
|
|
||||||
class QuickMessageView: UIView {
|
class QuickMessageView: UIView {
|
||||||
|
|
||||||
private let list: [String] = [
|
static let messageList: [String] = [
|
||||||
"爱你哦!", "预计到达时间?", "发生什么情况?", "注意安全", "在路上", "给我打电话",
|
"爱你哦!", "预计到达时间?", "发生什么情况?", "注意安全", "在路上", "给我打电话",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -86,7 +86,7 @@ class QuickMessageView: UIView {
|
||||||
backgroundColor = .clear
|
backgroundColor = .clear
|
||||||
setupUI()
|
setupUI()
|
||||||
setupRx()
|
setupRx()
|
||||||
setupTagData(list: list)
|
setupTagData(list: QuickMessageView.messageList)
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder aDecoder: NSCoder) {
|
required init?(coder aDecoder: NSCoder) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
//
|
||||||
|
// SignInModel.swift
|
||||||
|
// QuickLocation
|
||||||
|
//
|
||||||
|
// Created by 八条 on 2026/6/17.
|
||||||
|
//
|
||||||
|
|
||||||
|
import ObjectMapper
|
||||||
|
import RxDataSources
|
||||||
|
|
||||||
|
struct SignInInfoResponse: BaseModelProtocol {
|
||||||
|
// 状态码
|
||||||
|
var code: String?
|
||||||
|
// 消息
|
||||||
|
var message: String?
|
||||||
|
//
|
||||||
|
var model: SignInModel?
|
||||||
|
|
||||||
|
init?(map: Map) {}
|
||||||
|
|
||||||
|
mutating func mapping(map: Map) {
|
||||||
|
code <- map["code"]
|
||||||
|
message <- map["msg"]
|
||||||
|
model <- map["data"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SignInModel: Mappable, Equatable {
|
||||||
|
var uuid: String = UUID().uuidString
|
||||||
|
///
|
||||||
|
var missCount: Int = 0
|
||||||
|
var alertCount: Int = 0
|
||||||
|
var lastTime: Int = 0
|
||||||
|
/// 状态 0未签到 1已签到 2已有2天未签到
|
||||||
|
var signInStatus: Int = 0
|
||||||
|
var signCount: Int = 0
|
||||||
|
var email: String = ""
|
||||||
|
|
||||||
|
|
||||||
|
init?(map: Map) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func mapping(map: Map) {
|
||||||
|
missCount <- map["missCount"]
|
||||||
|
alertCount <- map["alertCount"]
|
||||||
|
lastTime <- map["lastTime"]
|
||||||
|
signInStatus <- map["signInStatus"]
|
||||||
|
signCount <- map["signCount"]
|
||||||
|
email <- map["email"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
//
|
||||||
|
// SignInVC.swift
|
||||||
|
// QuickLocation
|
||||||
|
//
|
||||||
|
// Created by 八条 on 2026/6/17.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import RxSwift
|
||||||
|
import RxCocoa
|
||||||
|
import CoreLocation
|
||||||
|
|
||||||
|
class SignInVC: BaseViewController {
|
||||||
|
|
||||||
|
fileprivate var rootView: SignInView!
|
||||||
|
/// 当前用户坐标(由外部传入)
|
||||||
|
var currentCoordinate: CLLocationCoordinate2D?
|
||||||
|
|
||||||
|
override func loadView() {
|
||||||
|
rootView = SignInView(frame: UIScreen.main.bounds)
|
||||||
|
view = rootView
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
requestSignInInfo()
|
||||||
|
|
||||||
|
rootView.signInLottieView.rx.tapGesture.subscribe(onNext: { [weak self] _ in
|
||||||
|
guard let c = self?.currentCoordinate else { return }
|
||||||
|
MQTTService.shared.reportSignIn(lat: c.latitude, lon: c.longitude, addr: "")
|
||||||
|
DLToast.show(text: "签到成功") {
|
||||||
|
self?.requestSignInInfo()
|
||||||
|
}
|
||||||
|
}).disposed(by: disposeBag)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - API
|
||||||
|
private func requestSignInInfo() {
|
||||||
|
DLToast.showLoading()
|
||||||
|
UserService.signInInfo().subscribe(onNext: { response in
|
||||||
|
guard let model = response.model else { return }
|
||||||
|
self.rootView.setupData(model)
|
||||||
|
}, onError: { _ in }).disposed(by: disposeBag)
|
||||||
|
}
|
||||||
|
|
||||||
|
init(currentUserCoord: CLLocationCoordinate2D?) {
|
||||||
|
self.currentCoordinate = currentUserCoord
|
||||||
|
super.init(nibName: nil, bundle: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,279 @@
|
||||||
|
//
|
||||||
|
// SignInView.swift
|
||||||
|
// QuickLocation
|
||||||
|
//
|
||||||
|
// Created by 八条 on 2026/6/17.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import RxSwift
|
||||||
|
import RxCocoa
|
||||||
|
import Lottie
|
||||||
|
import CoreLocation
|
||||||
|
|
||||||
|
class SignInView: UIView {
|
||||||
|
|
||||||
|
var disposeBag = DisposeBag()
|
||||||
|
|
||||||
|
func setupData(_ model: SignInModel) {
|
||||||
|
|
||||||
|
signInTextImg.image = UIImage(named: model.signInStatus == 1 ? "SignIn/today_text" : "SignIn/signIn_text")
|
||||||
|
|
||||||
|
let text = "已连续签到\(model.signCount)天"
|
||||||
|
let attr = NSMutableAttributedString(string: text)
|
||||||
|
let range = (text as NSString).range(of: model.signCount.string)
|
||||||
|
attr.addAttribute(.foregroundColor, value: UIColor(hexStr: "#FF8B39"), range: range)
|
||||||
|
signInDaysLab.attributedText = attr
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 签到按钮回调
|
||||||
|
var onSignInTap: ((CLLocationCoordinate2D?) -> Void)?
|
||||||
|
/// 当前坐标(由 VC 传入)
|
||||||
|
var currentCoordinate: CLLocationCoordinate2D?
|
||||||
|
|
||||||
|
private func setupRx() {
|
||||||
|
backBtn.rx.tap.subscribe(onNext: { _ in
|
||||||
|
AppRouter.shared.popOrDismiss()
|
||||||
|
}).disposed(by: disposeBag)
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setupUI() {
|
||||||
|
addSubview(navBgView)
|
||||||
|
addSubview(navBarView)
|
||||||
|
navBarView.addSubview(navTitleLabel)
|
||||||
|
navBarView.addSubview(backBtn)
|
||||||
|
|
||||||
|
addSubview(emailView)
|
||||||
|
addSubview(signInLottieView)
|
||||||
|
addSubview(signInTextImg)
|
||||||
|
addSubview(signInDaysLab)
|
||||||
|
addSubview(tipsView)
|
||||||
|
addSubview(agreementTV)
|
||||||
|
|
||||||
|
navBgView.layoutChain
|
||||||
|
.edges(excludingEdge: .bottom)
|
||||||
|
.heightToWidth(160/375)
|
||||||
|
|
||||||
|
navBarView.layoutChain
|
||||||
|
.edges(excludingEdge: .bottom)
|
||||||
|
.height(kNaviHeight)
|
||||||
|
|
||||||
|
navTitleLabel.layoutChain
|
||||||
|
.top(kStatusBarHeight + 12)
|
||||||
|
.centerY(backBtn)
|
||||||
|
.centerX()
|
||||||
|
|
||||||
|
backBtn.layoutChain
|
||||||
|
.centerY(navTitleLabel)
|
||||||
|
.left(15)
|
||||||
|
.width(24)
|
||||||
|
.height(24)
|
||||||
|
|
||||||
|
emailView.layoutChain
|
||||||
|
.topToBottomOfView(navBarView, offset: 20)
|
||||||
|
.centerX()
|
||||||
|
|
||||||
|
signInLottieView.layoutChain
|
||||||
|
.topToBottomOfView(emailView, offset: 30)
|
||||||
|
.edgesHorzontal(16)
|
||||||
|
.heightToWidth(1.0)
|
||||||
|
|
||||||
|
signInTextImg.layoutChain
|
||||||
|
.centerX(signInLottieView)
|
||||||
|
.centerY(signInLottieView)
|
||||||
|
|
||||||
|
signInDaysLab.layoutChain
|
||||||
|
.topToBottomOfView(signInLottieView, offset: 16)
|
||||||
|
.centerX()
|
||||||
|
|
||||||
|
agreementTV.layoutChain
|
||||||
|
.centerX()
|
||||||
|
.bottom(kSafeBottomMargin + 30)
|
||||||
|
|
||||||
|
tipsView.layoutChain
|
||||||
|
.bottomToTopOfView(agreementTV, offset: -20)
|
||||||
|
.edgesHorzontal(40)
|
||||||
|
.centerX()
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy var navBgView: UIImageView = {
|
||||||
|
let iv = UIImageView()
|
||||||
|
iv.image = UIImage(named: "Common/navBar_bg_2")
|
||||||
|
iv.contentMode = .scaleAspectFill
|
||||||
|
return iv
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var navBarView: UIView = {
|
||||||
|
let view = UIView()
|
||||||
|
view.backgroundColor = .clear
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var navTitleLabel: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.text = "还在吗?"
|
||||||
|
label.font = .systemFont(ofSize: 18, weight: .medium)
|
||||||
|
label.textColor = ThemeManager.shared.color.titleAuxColor
|
||||||
|
label.textAlignment = .center
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var backBtn: UIButton = {
|
||||||
|
let btn = UIButton(type: .custom)
|
||||||
|
btn.setImage(UIImage(named: "Common/back"), for: .normal)
|
||||||
|
btn.extendEdgeInsets = UIEdgeInsets(top: 54, left: 15, bottom: 100, right: 100)
|
||||||
|
return btn
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var emailView: UIView = {
|
||||||
|
let view = UIView()
|
||||||
|
view.backgroundColor = .clear
|
||||||
|
|
||||||
|
let title = UILabel()
|
||||||
|
title.text = "紧急人邮箱:"
|
||||||
|
title.textColor = UIColor(hexStr: "#999999")
|
||||||
|
title.font = .systemFont(ofSize: 14, weight: .regular)
|
||||||
|
view.addSubview(title)
|
||||||
|
title.layoutChain
|
||||||
|
.left()
|
||||||
|
.centerY()
|
||||||
|
.width(84)
|
||||||
|
|
||||||
|
view.addSubview(emailLab)
|
||||||
|
emailLab.layoutChain
|
||||||
|
.leftToRightOfView(title)
|
||||||
|
.edgesVertical(2)
|
||||||
|
|
||||||
|
let icon = UIImageView()
|
||||||
|
icon.image = UIImage(named: "Group/edit")
|
||||||
|
view.addSubview(icon)
|
||||||
|
icon.layoutChain
|
||||||
|
.leftToRightOfView(emailLab, offset: 10)
|
||||||
|
.right(15)
|
||||||
|
.width(20)
|
||||||
|
.height(20)
|
||||||
|
.centerY()
|
||||||
|
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var emailLab: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.text = "暂未添加"
|
||||||
|
label.textColor = UIColor(hexStr: "#333333")
|
||||||
|
label.font = .systemFont(ofSize: 14, weight: .medium)
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var signInLottieView: LottieAnimationView = {
|
||||||
|
let view = LottieAnimationView(name: "sign_in_continuous_data")
|
||||||
|
view.loopMode = .loop
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var signInTextImg: UIImageView = {
|
||||||
|
let view = UIImageView(image: UIImage(named: "SignIn/signIn_text"))
|
||||||
|
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var signInDaysLab: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.textColor = UIColor(hexStr: "#333333")
|
||||||
|
label.font = .systemFont(ofSize: 16, weight: .medium)
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var tipsView: UIView = {
|
||||||
|
let view = UIView()
|
||||||
|
view.backgroundColor = UIColor(hexStr: "#F5FBFF")
|
||||||
|
view.cornerRadius = 5
|
||||||
|
|
||||||
|
let icon = UIImageView(image: UIImage(named: "SignIn/tips"))
|
||||||
|
view.addSubview(icon)
|
||||||
|
icon.layoutChain
|
||||||
|
.top(14)
|
||||||
|
.left(12)
|
||||||
|
.width(14)
|
||||||
|
.height(14)
|
||||||
|
|
||||||
|
view.addSubview(tipsLab)
|
||||||
|
tipsLab.layoutChain
|
||||||
|
.leftToRightOfView(icon, offset: 3)
|
||||||
|
.edgesVertical(13)
|
||||||
|
.right(14)
|
||||||
|
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var tipsLab: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.text = "提示:2日未签到,系统将以您的名义, 在次日邮件通知您的紧急联系人。"
|
||||||
|
label.numberOfLines = 0
|
||||||
|
label.textColor = UIColor(hexStr: "#666666")
|
||||||
|
label.font = .systemFont(ofSize: 14, weight: .regular)
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var agreementTV: UITextView = {
|
||||||
|
let textView = UITextView()
|
||||||
|
textView.font = .systemFont(ofSize: 12, weight: .regular)
|
||||||
|
textView.backgroundColor = .clear
|
||||||
|
textView.isEditable = false
|
||||||
|
textView.isScrollEnabled = false
|
||||||
|
textView.isSelectable = false
|
||||||
|
textView.linkTextAttributes = [:]
|
||||||
|
textView.delegate = self
|
||||||
|
|
||||||
|
let text = "签到即同意 用户协议 和 隐私政策"
|
||||||
|
let attributedString = NSMutableAttributedString(string: text)
|
||||||
|
attributedString.addAttributes([.foregroundColor: UIColor(hexStr: "#666666")],
|
||||||
|
range: NSRange(location: 0, length: text.length))
|
||||||
|
attributedString.addAttributes([.foregroundColor: UIColor(hexStr: "#16B3FF"),
|
||||||
|
.link: "UserAgreement"],
|
||||||
|
range: (text as NSString).range(of: "用户协议"))
|
||||||
|
attributedString.addAttributes([.foregroundColor: UIColor(hexStr: "#16B3FF"),
|
||||||
|
.link: "PrivacyPolicy"],
|
||||||
|
range: (text as NSString).range(of: "隐私政策"))
|
||||||
|
|
||||||
|
textView.attributedText = attributedString
|
||||||
|
return textView
|
||||||
|
}()
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: .zero)
|
||||||
|
backgroundColor = .white
|
||||||
|
setupUI()
|
||||||
|
setupRx()
|
||||||
|
|
||||||
|
signInLottieView.play()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder aDecoder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SignInView: UITextViewDelegate {
|
||||||
|
func textView(_ textView: UITextView,
|
||||||
|
shouldInteractWith URL: URL,
|
||||||
|
in characterRange: NSRange,
|
||||||
|
interaction: UITextItemInteraction) -> Bool {
|
||||||
|
if URL.absoluteString == "UserAgreement" {
|
||||||
|
AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.userAgreementUrl])
|
||||||
|
}
|
||||||
|
if URL.absoluteString == "PrivacyPolicy" {
|
||||||
|
AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.privacyPolicyUrl])
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
private func openURL(_ url: String) {}
|
||||||
|
}
|
||||||
|
|
@ -41,6 +41,9 @@ final class LoginViewModel: BaseViewModel {
|
||||||
guard let model = response.model else { return }
|
guard let model = response.model else { return }
|
||||||
Defaults[\.loginToken] = model.token
|
Defaults[\.loginToken] = model.token
|
||||||
DLToast.showSuccess(text: "登录成功") {
|
DLToast.showSuccess(text: "登录成功") {
|
||||||
|
if let userId = model.uid {
|
||||||
|
MQTTService.shared.updateClientID("smartdrive_\(userId)")
|
||||||
|
}
|
||||||
NotificationCenter.default.post(name: .RefreshUserConfigNotification, object: nil)
|
NotificationCenter.default.post(name: .RefreshUserConfigNotification, object: nil)
|
||||||
AppRouter.shared.popOrDismiss()
|
AppRouter.shared.popOrDismiss()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,13 @@ class NavigationVC: BaseViewController {
|
||||||
private func setupMap() {
|
private func setupMap() {
|
||||||
#if !targetEnvironment(simulator)
|
#if !targetEnvironment(simulator)
|
||||||
rootView.mapView.delegate = self
|
rootView.mapView.delegate = self
|
||||||
rootView.mapView.showsUserLocation = true
|
// 添加起点标注(当前用户位置)
|
||||||
|
if let from = currentUserCoord, CLLocationCoordinate2DIsValid(from) {
|
||||||
|
let startAnn = MAPointAnnotation()
|
||||||
|
startAnn.coordinate = from
|
||||||
|
startAnn.title = "起点"
|
||||||
|
rootView.mapView.addAnnotation(startAnn)
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -153,7 +159,7 @@ extension NavigationVC: AMapNaviDriveManagerDelegate {
|
||||||
if let polyline = MAPolyline(coordinates: &mutableCoords, count: UInt(coords.count)) {
|
if let polyline = MAPolyline(coordinates: &mutableCoords, count: UInt(coords.count)) {
|
||||||
rootView.mapView.add(polyline)
|
rootView.mapView.add(polyline)
|
||||||
routeOverlay = polyline
|
routeOverlay = polyline
|
||||||
rootView.mapView.setVisibleMapRect(polyline.boundingMapRect, animated: true)
|
rootView.mapView.setVisibleMapRect(polyline.boundingMapRect, edgePadding: UIEdgeInsets(top: 80, left: 50, bottom: 260, right: 50), animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
let distM = Int(route.routeLength)
|
let distM = Int(route.routeLength)
|
||||||
|
|
@ -178,15 +184,16 @@ extension NavigationVC: AMapNaviDriveManagerDelegate {
|
||||||
extension NavigationVC: MAMapViewDelegate {
|
extension NavigationVC: MAMapViewDelegate {
|
||||||
func mapView(_ mapView: MAMapView!, viewFor annotation: MAAnnotation!) -> MAAnnotationView! {
|
func mapView(_ mapView: MAMapView!, viewFor annotation: MAAnnotation!) -> MAAnnotationView! {
|
||||||
if annotation is MAUserLocation { return nil }
|
if annotation is MAUserLocation { return nil }
|
||||||
let identifier = "NavPin"
|
let identifier = "NavEnd"
|
||||||
var view = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? MAPinAnnotationView
|
var view = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
|
||||||
if view == nil {
|
if view == nil {
|
||||||
view = MAPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
|
view = MAAnnotationView(annotation: annotation, reuseIdentifier: identifier)
|
||||||
} else {
|
} else {
|
||||||
view?.annotation = annotation
|
view?.annotation = annotation
|
||||||
}
|
}
|
||||||
// view?.pinColor = .red
|
let isEnd = annotation.title == member.name
|
||||||
// view?.canShowCallout = true
|
view?.image = UIImage(named: isEnd ? "Map/end" : "Map/current")
|
||||||
|
view?.centerOffset = CGPoint(x: 0, y: -22)
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,10 @@ class VipRechargeVC: BaseViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func reactiveAction() {
|
private func reactiveAction() {
|
||||||
|
rootView.payBtnView.rx.tapGesture.subscribe(onNext: { _ in
|
||||||
|
self.requestOrderPayParams()
|
||||||
|
}).disposed(by: disposeBag)
|
||||||
|
|
||||||
Observable.zip(
|
Observable.zip(
|
||||||
rootView.expenseCollectionView.rx.itemSelected,
|
rootView.expenseCollectionView.rx.itemSelected,
|
||||||
rootView.expenseCollectionView.rx.modelSelected(VipExpenseModel.self)
|
rootView.expenseCollectionView.rx.modelSelected(VipExpenseModel.self)
|
||||||
|
|
@ -84,7 +88,7 @@ class VipRechargeVC: BaseViewController {
|
||||||
// MARK: - API
|
// MARK: - API
|
||||||
private func requestRechargeInfo() {
|
private func requestRechargeInfo() {
|
||||||
DLToast.showLoading()
|
DLToast.showLoading()
|
||||||
SystemService.rechargeInfo(type: "member").subscribe(onNext: { [weak self] response in
|
OrderService.rechargeInfo(type: "member").subscribe(onNext: { [weak self] response in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
self.viewModel.loadData(list: response.list)
|
self.viewModel.loadData(list: response.list)
|
||||||
self.rootView.setupPayTypes(self.viewModel.payType)
|
self.rootView.setupPayTypes(self.viewModel.payType)
|
||||||
|
|
@ -92,4 +96,64 @@ class VipRechargeVC: BaseViewController {
|
||||||
self.rootView.discountLab.text = self.viewModel.discountPriceString
|
self.rootView.discountLab.text = self.viewModel.discountPriceString
|
||||||
}).disposed(by: disposeBag)
|
}).disposed(by: disposeBag)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - API支付参数
|
||||||
|
private func requestOrderPayParams() {
|
||||||
|
DLToast.showLoading()
|
||||||
|
let types = viewModel.payType.components(separatedBy: ",").map { $0.trimmingCharacters(in: .whitespaces) }
|
||||||
|
OrderService.orderPayParams(goodsId: viewModel.goodsId,
|
||||||
|
payType: types[rootView.selectedPayTypeTag]).subscribe(onNext: { response in
|
||||||
|
guard let data = response.data else { return }
|
||||||
|
|
||||||
|
let payType = types[self.rootView.selectedPayTypeTag]
|
||||||
|
if payType == "weixin" { // 微信
|
||||||
|
// WXApi.registerApp(model.appId, universalLink: AppSettings.kAppsUniversalLink)
|
||||||
|
//
|
||||||
|
// let request: PayReq = PayReq()
|
||||||
|
// request.partnerId = model.partnerId
|
||||||
|
// request.prepayId = model.prepayId
|
||||||
|
// request.package = model.packageValue
|
||||||
|
// request.nonceStr = model.nonceStr
|
||||||
|
// request.timeStamp = UInt32(model.timeStamp) ?? 0
|
||||||
|
// request.sign = model.sign
|
||||||
|
// WXApi.send(request)
|
||||||
|
}
|
||||||
|
else if payType == "alipay" { // 支付宝
|
||||||
|
if let payParam = data["payParam"] as? String, let appId = data["payParam"] as? String {
|
||||||
|
AlipaySDK.defaultService().payOrder(payParam, fromScheme: "Alipay\(appId)") { resultDic in
|
||||||
|
print("支付宝callback -> \(resultDic)")
|
||||||
|
guard let result = resultDic,
|
||||||
|
let resultStatus = result["resultStatus"] as? String else { return }
|
||||||
|
/**
|
||||||
|
9000 订单支付成功。
|
||||||
|
8000 正在处理中,支付结果未知(有可能已经支付成功),请查询商家订单列表中订单的支付状态。
|
||||||
|
4000 订单支付失败。
|
||||||
|
5000 重复请求。
|
||||||
|
6001 用户中途取消。
|
||||||
|
6002 网络连接出错。
|
||||||
|
6004 支付结果未知(有可能已经支付成功),请查询商家订单列表中订单的支付状态。
|
||||||
|
其它 其它支付错误。
|
||||||
|
*/
|
||||||
|
if resultStatus == "9000" {
|
||||||
|
self.showPayResultPop(showCloseBtn: false,
|
||||||
|
status: true,
|
||||||
|
title: "支付成功",
|
||||||
|
message: "恭喜您!成功开通\(self.viewModel.goodsName)",
|
||||||
|
confirmText: "确定", confirmBlock: {
|
||||||
|
AppRouter.shared.popOrDismiss()
|
||||||
|
}, cancelBlock: { })
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
self.showPayResultPop(status: false,
|
||||||
|
title: "支付失败",
|
||||||
|
message: "很抱歉,请您重新支付!",
|
||||||
|
confirmText: "重新支付", confirmBlock: { }, cancelText: "取消", cancelBlock: {
|
||||||
|
AppRouter.shared.popOrDismiss()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, onError: { _ in }).disposed(by: disposeBag)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,17 @@ class VipRechargeVM {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var list: [VipExpenseModel] = []
|
var list: [VipExpenseModel] = []
|
||||||
|
|
||||||
|
var goodsId: String {
|
||||||
|
guard list.count > 0 else { return "" }
|
||||||
|
return list[selectedIndex].goods_id
|
||||||
|
}
|
||||||
|
|
||||||
|
var goodsName: String {
|
||||||
|
guard list.count > 0 else { return "" }
|
||||||
|
return list[selectedIndex].goods_name
|
||||||
|
}
|
||||||
|
|
||||||
var payType: String {
|
var payType: String {
|
||||||
guard list.count > 0 else { return "" }
|
guard list.count > 0 else { return "" }
|
||||||
return list[selectedIndex].pay_type
|
return list[selectedIndex].pay_type
|
||||||
|
|
|
||||||
|
|
@ -71,16 +71,16 @@ class VipRechargeView: UIView {
|
||||||
.heightToWidth(144/375)
|
.heightToWidth(144/375)
|
||||||
.bottom()
|
.bottom()
|
||||||
|
|
||||||
payTypeStackView.layoutChain
|
|
||||||
.top(25)
|
|
||||||
.edgesHorzontal(16)
|
|
||||||
.centerX()
|
|
||||||
|
|
||||||
payBtnView.layoutChain
|
payBtnView.layoutChain
|
||||||
.edgesHorzontal(16)
|
.edgesHorzontal(16)
|
||||||
.heightToWidth(50/343)
|
.heightToWidth(50/343)
|
||||||
.centerY()
|
.centerY()
|
||||||
|
|
||||||
|
payTypeStackView.layoutChain
|
||||||
|
.top(13)
|
||||||
|
.edgesHorzontal(16)
|
||||||
|
.bottomToTopOfView(payBtnView)
|
||||||
|
|
||||||
payPriceView.layoutChain
|
payPriceView.layoutChain
|
||||||
.left(32)
|
.left(32)
|
||||||
.centerY(payBtnView, offset: -7)
|
.centerY(payBtnView, offset: -7)
|
||||||
|
|
@ -549,8 +549,8 @@ class VipRechargeView: UIView {
|
||||||
let stack = UIStackView()
|
let stack = UIStackView()
|
||||||
stack.axis = .horizontal
|
stack.axis = .horizontal
|
||||||
stack.spacing = 30
|
stack.spacing = 30
|
||||||
// stack.distribution = .fillEqually
|
// stack.distribution = .fill
|
||||||
stack.alignment = .center
|
stack.alignment = .leading
|
||||||
return stack
|
return stack
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
@ -571,6 +571,7 @@ class VipRechargeView: UIView {
|
||||||
for (idx, (icon, name)) in payTypeMap.enumerated() {
|
for (idx, (icon, name)) in payTypeMap.enumerated() {
|
||||||
let isSelected = idx == 0
|
let isSelected = idx == 0
|
||||||
let view = makePayTypeView(tag: idx, icon: icon, name: name, isSelected: isSelected)
|
let view = makePayTypeView(tag: idx, icon: icon, name: name, isSelected: isSelected)
|
||||||
|
view.layoutChain.width(110).height(22)
|
||||||
payTypeStackView.addArrangedSubview(view)
|
payTypeStackView.addArrangedSubview(view)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
//
|
||||||
|
// OrderService.swift
|
||||||
|
// QuickLocation
|
||||||
|
//
|
||||||
|
// Created by 八条 on 2026/6/17.
|
||||||
|
//
|
||||||
|
|
||||||
|
import RxSwift
|
||||||
|
import Moya
|
||||||
|
|
||||||
|
struct OrderService {
|
||||||
|
static let disposeBag = DisposeBag()
|
||||||
|
|
||||||
|
/// 充值内容
|
||||||
|
/// - Parameters:
|
||||||
|
/// - type: 类型 member
|
||||||
|
static func rechargeInfo(type: String) -> Observable<VipExpenseResponse> {
|
||||||
|
let api = OrderAPI.rechargeInfo(type: type).multiTarget
|
||||||
|
return APIProvider.request(token: api)
|
||||||
|
.map(VipExpenseResponse.self)
|
||||||
|
.asObservable()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 支付参数
|
||||||
|
/// - Parameters:
|
||||||
|
/// - goodsId: 商品ID
|
||||||
|
/// - payType: alipay、weixin
|
||||||
|
/// - source: center
|
||||||
|
/// - extra: 额外参数
|
||||||
|
static func orderPayParams(goodsId: String, payType: String, source: String="center", extra: [String:Any]=[:]) -> Observable<ResponseModel> {
|
||||||
|
let api = OrderAPI.orderPayParams(goodsId: goodsId, payType: payType, source: source, extra: extra).multiTarget
|
||||||
|
return APIProvider.request(token: api)
|
||||||
|
.map(ResponseModel.self)
|
||||||
|
.asObservable()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -26,16 +26,6 @@ struct SystemService {
|
||||||
.asObservable()
|
.asObservable()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 充值内容
|
|
||||||
/// - Parameters:
|
|
||||||
/// - type: 类型 member
|
|
||||||
static func rechargeInfo(type: String) -> Observable<VipExpenseResponse> {
|
|
||||||
let api = SystemAPI.rechargeInfo(type: type).multiTarget
|
|
||||||
return APIProvider.request(token: api)
|
|
||||||
.map(VipExpenseResponse.self)
|
|
||||||
.asObservable()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 微信客服
|
/// 微信客服
|
||||||
static func wechatService() -> Observable<ResponseModel> {
|
static func wechatService() -> Observable<ResponseModel> {
|
||||||
let api = SystemAPI.wechatService.multiTarget
|
let api = SystemAPI.wechatService.multiTarget
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,14 @@ struct UserService {
|
||||||
.asObservable()
|
.asObservable()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 签到信息
|
||||||
|
static func signInInfo() -> Observable<SignInInfoResponse> {
|
||||||
|
let api = UserAPI.signInInfo.multiTarget
|
||||||
|
return APIProvider.request(token: api)
|
||||||
|
.map(SignInInfoResponse.self)
|
||||||
|
.asObservable()
|
||||||
|
}
|
||||||
|
|
||||||
/// 更换手机
|
/// 更换手机
|
||||||
static func changePhone(timestamp: String, phone: String, code: String) -> Observable<ResponseModel> {
|
static func changePhone(timestamp: String, phone: String, code: String) -> Observable<ResponseModel> {
|
||||||
let api = UserAPI.changePhone(timestamp: timestamp, phone: phone, code: code).multiTarget
|
let api = UserAPI.changePhone(timestamp: timestamp, phone: phone, code: code).multiTarget
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,281 @@
|
||||||
|
//
|
||||||
|
// PayResultPopVC.swift
|
||||||
|
// QuickLocation
|
||||||
|
//
|
||||||
|
// Created by 八条 on 2026/6/17.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import RxSwift
|
||||||
|
import RxCocoa
|
||||||
|
import URLNavigator
|
||||||
|
|
||||||
|
class PayResultPopVC: DLCustomPopVC {
|
||||||
|
|
||||||
|
var disposeBag = DisposeBag()
|
||||||
|
|
||||||
|
// MARK: - Accessor
|
||||||
|
public var confirmBlock: (() -> Void)?
|
||||||
|
public var cancelBlock: (() -> Void)?
|
||||||
|
|
||||||
|
public var status: Bool? {
|
||||||
|
didSet {
|
||||||
|
guard let status = status else { return }
|
||||||
|
logoImgView.image = UIImage(named: status ? "Popup/success" : "Popup/failure")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public var titleText: String? {
|
||||||
|
didSet {
|
||||||
|
titleLab.text = titleText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public var contentText: String? {
|
||||||
|
didSet {
|
||||||
|
contentLab.text = contentText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public var cancelText: String? {
|
||||||
|
didSet {
|
||||||
|
closeBtn.setTitle(cancelText, for: .normal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public var confirmText: String? {
|
||||||
|
didSet {
|
||||||
|
confirmBtn.setTitle(confirmText, for: .normal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setupSubviews() {
|
||||||
|
contentBgView.addSubview(logoImgView)
|
||||||
|
contentView.addSubview(headerBgImg)
|
||||||
|
|
||||||
|
if titleText != nil,
|
||||||
|
titleText?.isEmpty == false {
|
||||||
|
contentView.addSubview(titleLab)
|
||||||
|
}
|
||||||
|
|
||||||
|
if contentText != nil,
|
||||||
|
contentText?.isEmpty == false {
|
||||||
|
contentView.addSubview(contentLab)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cancelText?.isEmpty == false || confirmText?.isEmpty == false {
|
||||||
|
contentView.addSubview(stackView)
|
||||||
|
}
|
||||||
|
|
||||||
|
closeBtn.isHidden = !(cancelText?.isEmpty == false)
|
||||||
|
confirmBtn.isHidden = !(confirmText?.isEmpty == false)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setupLayout() {
|
||||||
|
logoImgView.layoutChain
|
||||||
|
.centerX()
|
||||||
|
.top(-44)
|
||||||
|
.width(88)
|
||||||
|
.height(88)
|
||||||
|
|
||||||
|
headerBgImg.layoutChain
|
||||||
|
.edges(excludingEdge: .bottom)
|
||||||
|
.heightToWidth(100/315)
|
||||||
|
|
||||||
|
var tempView: UIView?
|
||||||
|
if titleText != nil,
|
||||||
|
titleText?.isEmpty == false {
|
||||||
|
titleLab.layoutChain
|
||||||
|
.top(69)
|
||||||
|
.edgesHorzontal(20)
|
||||||
|
tempView = titleLab
|
||||||
|
}
|
||||||
|
|
||||||
|
if contentText != nil,
|
||||||
|
contentText?.isEmpty == false {
|
||||||
|
|
||||||
|
if let tempView = tempView {
|
||||||
|
contentLab.layoutChain
|
||||||
|
.edgesHorzontal(20)
|
||||||
|
.topToBottomOfView(tempView, offset: 20)
|
||||||
|
} else {
|
||||||
|
contentLab.layoutChain
|
||||||
|
.top(53)
|
||||||
|
.edgesHorzontal(20)
|
||||||
|
}
|
||||||
|
tempView = contentLab
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let tempView = tempView else { return }
|
||||||
|
if cancelText?.isEmpty == false || confirmText?.isEmpty == false {
|
||||||
|
stackView.layoutChain
|
||||||
|
.topToBottomOfView(tempView, offset: 30)
|
||||||
|
.left(20)
|
||||||
|
.right(20)
|
||||||
|
.bottom(15)
|
||||||
|
|
||||||
|
confirmBtn.layoutChain
|
||||||
|
.height(50)
|
||||||
|
|
||||||
|
closeBtn.layoutChain
|
||||||
|
.height(50)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - UI
|
||||||
|
private lazy var bgView: UIView = {
|
||||||
|
let view = UIView()
|
||||||
|
view.backgroundColor = .black.withAlphaComponent(0.5)
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var popView: UIView = {
|
||||||
|
let view = UIView()
|
||||||
|
view.backgroundColor = .clear
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var popBgView: UIView = {
|
||||||
|
let view = UIView()
|
||||||
|
view.backgroundColor = .white
|
||||||
|
view.cornerRadius = 30
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var logoImgView: UIImageView = {
|
||||||
|
let view = UIImageView()
|
||||||
|
view.backgroundColor = .clear
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var headerBgImg: UIImageView = {
|
||||||
|
let view = UIImageView(image: UIImage(named: "Popup/header_bg"))
|
||||||
|
view.contentMode = .scaleAspectFill
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var titleLab: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.font = .systemFont(ofSize: 20, weight: .bold)
|
||||||
|
label.textColor = UIColor(hexStr: "#1A1A1A")
|
||||||
|
label.textAlignment = .center
|
||||||
|
label.numberOfLines = 0
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var contentLab: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.font = .systemFont(ofSize: 14, weight: .medium)
|
||||||
|
label.textColor = UIColor(hexStr: "#767676")
|
||||||
|
label.textAlignment = .center
|
||||||
|
label.numberOfLines = 0
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var stackView: UIStackView = {
|
||||||
|
let view = UIStackView(arrangedSubviews: [confirmBtn, closeBtn])
|
||||||
|
view.spacing = 10
|
||||||
|
view.axis = .vertical
|
||||||
|
view.alignment = .fill
|
||||||
|
view.distribution = .fill
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var confirmBtn: UIButton = {
|
||||||
|
let btn = UIButton(type: .custom)
|
||||||
|
btn.setTitle("是", for: .normal)
|
||||||
|
btn.setTitleColor(.white, for: .normal)
|
||||||
|
btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
|
||||||
|
btn.setBackgroundImage(UIImage(named: "Common/button_bg_2"), for: .normal)
|
||||||
|
btn.cornerRadius = 25
|
||||||
|
btn.addTouchBlock { [weak self] _ in
|
||||||
|
self?.dismiss(animated: true, completion: {
|
||||||
|
self?.confirmBlock?()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return btn
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var closeBtn: UIButton = {
|
||||||
|
let btn = UIButton(type: .custom)
|
||||||
|
btn.setTitle("否", for: .normal)
|
||||||
|
btn.setTitleColor(UIColor(hexStr: "#16B3FF"), for: .normal)
|
||||||
|
btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
|
||||||
|
btn.backgroundColor = .clear
|
||||||
|
btn.addTouchBlock { [weak self] _ in
|
||||||
|
self?.dismiss(animated: true, completion: {
|
||||||
|
self?.cancelBlock?()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return btn
|
||||||
|
}()
|
||||||
|
|
||||||
|
// MARK: - Lifecycle
|
||||||
|
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
|
||||||
|
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
|
||||||
|
popStyle = .center
|
||||||
|
centerCornerRadius = 30
|
||||||
|
}
|
||||||
|
|
||||||
|
public required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
public override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
setupSubviews()
|
||||||
|
setupLayout()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public extension UIViewController {
|
||||||
|
/// 显示弹窗
|
||||||
|
/// - Parameters:
|
||||||
|
/// - status: 支付状态 true false
|
||||||
|
/// - title: 标题
|
||||||
|
/// - message: 文本内容
|
||||||
|
/// - confirmText: 确认按钮文案
|
||||||
|
/// - confirmBlock: 确认按钮点击回调
|
||||||
|
/// - cancelText: 取消按钮文案
|
||||||
|
/// - cancelBlock: 取消按钮点击回调
|
||||||
|
func showPayResultPop(showCloseBtn: Bool = true,
|
||||||
|
status: Bool,
|
||||||
|
title: String?=nil,
|
||||||
|
message: String?=nil,
|
||||||
|
confirmText: String?=nil,
|
||||||
|
confirmBlock: (() -> Void)?=nil,
|
||||||
|
cancelText: String?=nil,
|
||||||
|
cancelBlock: (() -> Void)?=nil) {
|
||||||
|
if title == nil && message == nil { return }
|
||||||
|
let vc = PayResultPopVC()
|
||||||
|
vc.titleText = title
|
||||||
|
vc.status = status
|
||||||
|
vc.contentText = message
|
||||||
|
vc.confirmText = confirmText
|
||||||
|
vc.confirmBlock = confirmBlock
|
||||||
|
vc.cancelText = cancelText
|
||||||
|
vc.cancelBlock = cancelBlock
|
||||||
|
vc.closeBtn.isHidden = !showCloseBtn
|
||||||
|
vc.dimmingClick = showCloseBtn
|
||||||
|
present(vc, animated: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func showPayResultPop(showCloseBtn: Bool = true,
|
||||||
|
status: Bool,
|
||||||
|
title: String?=nil,
|
||||||
|
message: String?=nil,
|
||||||
|
confirmText: String?=nil,
|
||||||
|
confirmBlock: (() -> Void)?=nil,
|
||||||
|
cancelText: String?=nil,
|
||||||
|
cancelBlock: (() -> Void)?=nil) {
|
||||||
|
if title == nil && message == nil { return }
|
||||||
|
let vc = PayResultPopVC()
|
||||||
|
vc.titleText = title
|
||||||
|
vc.status = status
|
||||||
|
vc.contentText = message
|
||||||
|
vc.confirmText = confirmText
|
||||||
|
vc.confirmBlock = confirmBlock
|
||||||
|
vc.cancelText = cancelText
|
||||||
|
vc.cancelBlock = cancelBlock
|
||||||
|
vc.closeBtn.isHidden = !showCloseBtn
|
||||||
|
vc.dimmingClick = showCloseBtn
|
||||||
|
UIViewController.topMost?.present(vc, animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||