29 Commits
Author SHA1 Message Date
jiayangyangandClaude Opus 4.7 bfce0d5885 fix(sos): 群成员面板cell整行可拨打电话,修复编译缺失属性声明和import
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-04 20:00:57 +08:00
jiayangyangandClaude Opus 4.7 5b719599ba chore: 地图消息Cell圆角优化及IM登录日志
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-04 16:31:49 +08:00
jiayangyangandClaude Opus 4.7 ee47bba29a fix(sos): isLiaisonUser移至viewWillAppear,急救员入口工具栏隐藏结束咨询和档案,群成员加载加菊花,视频加号走IM默认
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-04 16:29:15 +08:00
jiayangyangandClaude Opus 4.7 a6a0f0a4ce feat(sos): 应急中心页面重构,新增参与订单模型及相关接口,补充首页图标资源
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-22 14:48:45 +08:00
jiayangyangandClaude Opus 4.7 8a8a914a8c feat(sos): 应急就医群视频通话加号邀请及健康档案详情页接口对接
- 多人视频页面恢复右上角加号按钮,接入自有半屏群成员面板
- 选人后自动发起视频通话邀请并即时显示受邀成员
- IM 登录同步 setSelfInfo,解决通话成员显示 ID 问题
- 健康档案详情页接入一人一案接口,移除硬编码数据
- 新增 Pods 修改记录文档

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-20 17:56:10 +08:00
jiayangyangandClaude Opus 4.7 ee498064cc feat(sos): 集成微信SDK,实现地图卡片长按转发微信;新增急救资源详情页及群成员面板
- 手动集成微信 OpenSDK-NoPay,创建 XJWeChatManager 统一管理分享能力
- 地图卡片新增长按手势,通过代理模式实现「转发到微信」,分享含高德导航链接
- 聊天页新增群成员侧滑面板,支持查看成员列表及一键拨号
- 新增急救资源详情页(XJFirstAidResourceDetailVC)及选择联系人页
- 首页健康知识/资讯模块,含双视图列表及 H5 跳转
- 修复急救资源详情页编译报错

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-14 17:53:44 +08:00
jiayangyangandClaude Opus 4.7 6337454956 feat(home): 首页增加健康知识/资讯模块,含双视图列表及H5跳转
- 新增健康知识视图(标签切换+搜索+列表)和健康资讯视图(纯列表无搜索)
- 对接健康栏目列表和文章分页接口,资讯无子分类直接用父级ID
- 接入更多/搜索/详情H5跳转,统一用通用加密串传参
- 键盘弹起时自动避让,从H5回来刷新文章收藏数

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-29 18:46:58 +08:00
NSArray 2c2f307247 feat: HomeV2 手表数据区高度动态调整 & 绑定弹窗姓名工号布局优化
- XJHomeWatchDataView 新增 heightChangeBlock,无数据/未登录高度 104,有数据高度 200
- XJHomePageV2HeardView 初始高度改为 104,绑定回调动态更新约束带动画
- BindWatchPopView 姓名工号同行布局,工号固定右侧优先显示,姓名占满剩余空间
2026-03-19 16:50:19 +08:00
NSArray 6f9f903ca1 修改弹窗逻辑 2026-03-13 17:20:45 +08:00
NSArray 1bfe617cab 手表解绑功能 2026-03-12 18:08:53 +08:00
NSArray a47d1a56fa 积分银行 2026-03-11 17:59:56 +08:00
NSArray d0ff8c2c19 fix: 修复 WKWebView 白屏及 finishActivity JS Bridge 失效问题
- XJBaseWebViewVC: 补全 finishActivity 消息分发,基类默认实现改为 pop 返回
- XJBaseWebViewVC: 新增 decidePolicyForNavigationAction 拦截非 HTTP scheme(alipay:// 等),避免 WKWebView 加载失败导致白屏
- XJBaseWebViewVC: 新增 webViewWebContentProcessDidTerminate,进程被系统杀死后自动 reload
- XJBankWebDetailViewController: 移除重复的 finishActivity override,复用基类 pop 逻辑
- AppDelegate: 移除导致启动卡顿的 WKWebView 预热代码
- HomeV2: 将 Controllview 相关文件移入 Controllview 子目录,整理目录结构
2026-03-11 17:58:23 +08:00
NSArray b69578aa4a chore: 添加 Claude Code 项目配置文件 2026-03-09 09:43:43 +08:00
NSArray c7925e3189 chore: 版本升级至 1.0.11 并切换正式环境
- 版本号 1.0.10 → 1.0.11,Build 号 1 → 2
- API 环境切换至正式地址(api-jkglpt.iosp.ydpt.tech)
- 首页 Banner 请求增加 loading 状态显示
- 重构 QuestionViewController:移除 verifyToken 流程,改用 isLogin 判断
- 删除废弃方法(verifyTokenData、getUpDateinfo、backUp、updateHomeDate)
- 更新首页顶部图片资源(组7 → 组9)
- 清理 AppDelegate 中空的 DEBUG 编译条件块
2026-03-06 16:59:25 +08:00
NSArray 82a432f77a 首页监测自测修改 2026-03-05 18:07:03 +08:00
NSArray c5b5149bb1 首页手表监测 2026-03-04 18:07:02 +08:00
NSArray 823063653b 手表功能 2026-03-03 18:12:00 +08:00
NSArray aa34d4623e 新疆首页新需求 2026-02-05 20:24:38 +08:00
History 3c241b193b 新疆1.0.8版本 2026-01-22 17:14:35 +08:00
History a7d78ef4d8 模拟功能 2026-01-22 09:35:35 +08:00
History 57643da94d 新疆修改 2026-01-22 09:35:14 +08:00
History 4aba54ce74 更新新疆需求 2025-11-21 13:46:29 +08:00
History 2ec6c65bef 新疆员工端更新请求地址,手机号、icon 2025-11-05 10:41:28 +08:00
History 8f7d08f1e1 改图标 2025-10-10 15:09:10 +08:00
History 2d2396bd53 新疆修改 2025-09-30 11:24:46 +08:00
History b2d90a7c81 修改应急中心 2025-09-26 13:47:44 +08:00
History 0ffc7ba2b2 修改员工端项目名称图标 2025-07-14 10:06:00 +08:00
History 4eec6512e7 删除文件 2025-07-02 18:36:30 +08:00
History cc4663206b 修改组织关系!删除无用代码 2025-07-02 18:34:25 +08:00
1172 changed files with 29087 additions and 4824 deletions
+196
View File
@@ -0,0 +1,196 @@
# Agent 行为准则 & XinjiangProject iOS 开发规范
---
## 一、Agent 行为准则
### 0. 语言强制
- 强制使用简体中文进行所有交互(代码除外)。
### 1. 抽象设计确认
- 涉及抽象设计、架构调整或新功能模块时,必须先用文字或 Mermaid 图对齐设计思路。
- 必须等待用户确认方案后,才能开始编写代码。
### 2. 任务清单确认
- 执行任何实质性任务前,必须先列出详细的任务清单。
- 必须等待用户明确回复(如"好的"、"开始")后,才能进入执行阶段。
### 3. 分步执行与确认
- 代码量较大或逻辑复杂的任务,禁止一次性完成。
- 拆分为多个步骤,每步完成后汇报进度并询问"是否可以进行下一步?"。
### 4. 所有修改必须确认
- 对代码库的任何修改(新建文件、修改文件、删除文件、执行 pod install 等)前,必须先描述变更内容。
- 必须等待用户明确回复"确认"或"同意"后,才能执行。
### 9. 代码注释语言规范
- 所有注释使用简体中文。
- 标识符(变量名、函数名、类名)仍使用英文。
---
## 二、项目技术规范
### 技术栈
- **主语言**: Objective-C
- **混编**: 允许 OC/Swift 混编,OC 为主。引入 Swift 文件前**必须征得用户确认**。
- **UI 框架**: UIKit
- **架构模式**: MVC + Manager 层
- **包管理**: CocoaPods,使用 `.xcworkspace` 打开项目
- **最低系统版本**: iOS 12.0
---
### 项目目录结构
```
XinjiangProject/
├── Project/ # 业务模块(按功能划分)
│ ├── Base/ # 基类 ViewController
│ ├── AppDelegate/
│ ├── Login_Register/
│ ├── HomeV2/
│ ├── Homepage/
│ ├── Monitoring/
│ ├── MainCenter/
│ ├── BANK/
│ ├── SOS/
│ ├── Qusetion/
│ ├── TUIChat/
│ ├── CustomTUIChat/
│ └── simulationUser(模拟用户)/
├── Manager/ # 业务逻辑管理层
│ ├── NetworkHelpManager/ # 网络层(XJPNetAPI、JKCQNetworkingWithCache
│ ├── UserManager/
│ ├── AudioManager/
│ ├── TUIManager/
│ └── RuntimeManager/
├── Categorys/ # UIKit 分类扩展
├── Utils/ # 工具类
├── Define/ # 宏定义(颜色、字体、接口地址、Key)
└── ThirdParty/ # 本地化第三方库
```
新增模块按以下结构组织:
```
Project/ModuleName/
├── Controller/
├── View/
└── Model/
```
---
### 命名规范
**类名(PascalCase):**
- 新建类统一使用前缀 `XJ`,如 `XJOrderViewController``XJUserModel`
- 历史遗留 `HQ` 前缀类(如 `HQUserInfo`)维护时保持原前缀,不得重命名
- 分类命名:`ClassName+ExtensionName`,如 `UIView+Extension`
**方法名(camelCase):**
```objc
- (void)setupNavigationBar;
- (void)loadUserDataWithType:(NSInteger)type;
```
**属性修饰符规范:**
```objc
@property (nonatomic, strong) UIView *containerView; // 对象用 strong
@property (nonatomic, copy) NSString *userName; // 字符串/Block 用 copy
@property (nonatomic, assign) NSInteger pageIndex; // 基本类型用 assign
@property (nonatomic, weak) id<Protocol> delegate; // 代理用 weak
```
**宏常量:**
```objc
#define kNavBgColor [UIColor colorWithHexString:@"#00AE68"] // 颜色用 k 前缀
#define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width // 系统级用大写
```
---
### 代码组织(#pragma mark
```objc
#pragma mark - ————— Life Cycle —————
#pragma mark - ————— Setter / Getter —————
#pragma mark - ————— Private Methods —————
#pragma mark - ————— Network —————
#pragma mark - ————— UITableViewDataSource —————
#pragma mark - ————— UITableViewDelegate —————
```
---
### 内存管理
Block 内防循环引用,使用项目全局 `kWeakSelf` 宏:
```objc
kWeakSelf(self);
[self.manager doSomethingWithCompletion:^{
[weakself updateUI];
}];
```
---
### UI 布局
frame 与 Masonry 均可使用,根据实际场景判断,不强制统一。
屏幕适配使用项目已定义宏(基于 375pt 基准):
```objc
kRealValue(x) // 尺寸等比缩放
kFontSize(x) // 字体等比缩放
```
---
### 网络层规范
项目网络层使用 `XJPNetAPI` + `JKCQNetworkingWithCache`
回调通过 `performSelector` 动态分发,**遵循以下固定签名**:
**发起请求:**
```objc
// init:tag:NeedToken: 初始化,self 作为代理,tag 区分同一 VC 内的不同请求
XJPNetAPI *api = [[XJPNetAPI alloc] init:self tag:@"USERINFO" NeedToken:token];
[api getUserInfo:paramDic];
```
**实现回调(固定方法签名,不得修改):**
```objc
// 请求成功
- (void)Sucess:(id)response tag:(NSString *)tag {
if ([tag isEqualToString:@"USERINFO"]) {
// 处理用户信息数据
}
}
// 请求失败
- (void)Failed:(NSString *)message tag:(NSString *)tag {
[self showMBProgressHUDOnlyWithString:message];
}
```
**注意事项:**
- `Sucess` 为项目约定拼写(非笔误),禁止修改方法名
- 同一 VC 内多个请求通过 `tag` 字符串区分,在回调中用 `if/else` 分支处理
- API 地址统一定义在 `StatusMacros.h`,禁止在业务代码中硬编码 URL
---
### 禁止事项
- 禁止将 API Key、SDKAPPID 等敏感信息硬编码在业务文件中(统一放 `ThirdMacros.h`
- 禁止在主线程执行网络请求、数据库读写、文件 IO 等耗时操作
- 禁止在 Category 中声明存储属性(需用 `objc_setAssociatedObject`
- 禁止修改 `Sucess:tag:` / `Failed:tag:` 的方法签名
- 禁止未经确认自行封装或绕过 `XJPNetAPI` 发起网络请求
+1 -1
View File
@@ -1,5 +1,5 @@
platform :ios, '12.0'
platform :ios, '15.0'
# 忽略引入库的所有警告
inhibit_all_warnings!
+1 -1
View File
@@ -511,6 +511,6 @@ SPEC CHECKSUMS:
YYKit: 7cda43304a8dc3696c449041e2cb3107b4e236e7
YYModel: 2a7fdd96aaa4b86a824e26d0c517de8928c04b30
PODFILE CHECKSUM: c63ef0a5edf68dd395621c435af5c0063b38442a
PODFILE CHECKSUM: 9ebe0e8991fab6e5cf3d18a72b82760099c4bc48
COCOAPODS: 1.16.2
@@ -7,6 +7,8 @@
objects = {
/* Begin PBXBuildFile section */
188C3FFF3005E07600461C07 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 188C3FFE3005E07600461C07 /* Security.framework */; };
188C40013005E08000461C07 /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 188C40003005E08000461C07 /* CoreTelephony.framework */; };
2A9D6F4901C83B23A09A207B /* libPods-XinjiangProject.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5380821CF956D8001EF91CA7 /* libPods-XinjiangProject.a */; };
/* End PBXBuildFile section */
@@ -31,6 +33,10 @@
1809E4622E092C710034C8FC /* XinjiangProject.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XinjiangProject.app; sourceTree = BUILT_PRODUCTS_DIR; };
1809E47D2E092C740034C8FC /* XinjiangProjectTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = XinjiangProjectTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
1809E4872E092C740034C8FC /* XinjiangProjectUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = XinjiangProjectUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
188C3FFE3005E07600461C07 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
188C40003005E08000461C07 /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; };
188C40023005E08B00461C07 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
188C40033005E09100461C07 /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; };
5380821CF956D8001EF91CA7 /* libPods-XinjiangProject.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-XinjiangProject.a"; sourceTree = BUILT_PRODUCTS_DIR; };
D5F062871D7E5499A760A0A9 /* Pods-XinjiangProject.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-XinjiangProject.release.xcconfig"; path = "Target Support Files/Pods-XinjiangProject/Pods-XinjiangProject.release.xcconfig"; sourceTree = "<group>"; };
F4F935FBD1765B37B37D212D /* Pods-XinjiangProject.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-XinjiangProject.debug.xcconfig"; path = "Target Support Files/Pods-XinjiangProject/Pods-XinjiangProject.debug.xcconfig"; sourceTree = "<group>"; };
@@ -72,6 +78,8 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
188C40013005E08000461C07 /* CoreTelephony.framework in Frameworks */,
188C3FFF3005E07600461C07 /* Security.framework in Frameworks */,
2A9D6F4901C83B23A09A207B /* libPods-XinjiangProject.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -118,6 +126,10 @@
5E0194FB12246C95B3FA5215 /* Frameworks */ = {
isa = PBXGroup;
children = (
188C40033005E09100461C07 /* libc++.tbd */,
188C40023005E08B00461C07 /* libz.tbd */,
188C40003005E08000461C07 /* CoreTelephony.framework */,
188C3FFE3005E07600461C07 /* Security.framework */,
5380821CF956D8001EF91CA7 /* libPods-XinjiangProject.a */,
);
name = Frameworks;
@@ -207,7 +219,7 @@
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = 1;
LastUpgradeCheck = 1630;
LastUpgradeCheck = 2630;
TargetAttributes = {
1809E4612E092C710034C8FC = {
CreatedOnToolsVersion = 16.3;
@@ -374,33 +386,35 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = XinjiangProject/XinjiangProject.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = A7CC5LW224;
ENABLE_MODULE_VERIFIER = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_PREFIX_HEADER = "$(SRCROOT)/XinjiangProject/Supporting Files/PrefixHeader.pch";
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "$(SRCROOT)/XinjiangProject/Supporting Files/Info.plist";
INFOPLIST_KEY_CFBundleDisplayName = "新疆亚克西";
INFOPLIST_KEY_CFBundleDisplayName = "健康油我";
INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO;
INFOPLIST_KEY_NSCameraUsageDescription = "健康咨询员工端需要访问您的相机用来档案功能,是否同意?";
INFOPLIST_KEY_NSLocationAlwaysAndWhenInUseUsageDescription = "APP需要您的定位服务,否则可能无法使用。";
INFOPLIST_KEY_NSLocationAlwaysUsageDescription = "APP需要您的定位服务,否则可能无法使用。";
INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "APP需要您的定位服务,否则可能无法使用。";
INFOPLIST_KEY_NSMicrophoneUsageDescription = "健康咨询员工端需要访问您的麦克风用来视频录制,是否同意?";
INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = "新疆员工端需要访问您的相册上传图片,方便您的使用,是否同意?";
INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "健康咨询想使用您的相册功能 是否同意?";
INFOPLIST_KEY_NSCameraUsageDescription = "健康油我需要访问您的相机用来档案功能,是否同意?";
INFOPLIST_KEY_NSLocationAlwaysAndWhenInUseUsageDescription = "健康油我需要您的定位服务,否则可能无法使用。";
INFOPLIST_KEY_NSLocationAlwaysUsageDescription = "健康油我需要您的定位服务,否则可能无法使用。";
INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "健康油我需要您的定位服务,否则可能无法使用。";
INFOPLIST_KEY_NSMicrophoneUsageDescription = "健康油我需要访问您的麦克风用来视频录制,是否同意?";
INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = "健康油我需要访问您的相册上传图片,方便您的使用,是否同意?";
INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "健康油我想使用您的相册功能 是否同意?";
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
INFOPLIST_KEY_UIUserInterfaceStyle = Light;
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
IPHONEOS_DEPLOYMENT_TARGET = 15;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
MARKETING_VERSION = 1.0.14;
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20";
PRODUCT_BUNDLE_IDENTIFIER = com.questionTools.XinjiangProject;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
@@ -418,33 +432,35 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = XinjiangProject/XinjiangProject.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = A7CC5LW224;
ENABLE_MODULE_VERIFIER = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_PREFIX_HEADER = "$(SRCROOT)/XinjiangProject/Supporting Files/PrefixHeader.pch";
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "$(SRCROOT)/XinjiangProject/Supporting Files/Info.plist";
INFOPLIST_KEY_CFBundleDisplayName = "新疆亚克西";
INFOPLIST_KEY_CFBundleDisplayName = "健康油我";
INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO;
INFOPLIST_KEY_NSCameraUsageDescription = "健康咨询员工端需要访问您的相机用来档案功能,是否同意?";
INFOPLIST_KEY_NSLocationAlwaysAndWhenInUseUsageDescription = "APP需要您的定位服务,否则可能无法使用。";
INFOPLIST_KEY_NSLocationAlwaysUsageDescription = "APP需要您的定位服务,否则可能无法使用。";
INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "APP需要您的定位服务,否则可能无法使用。";
INFOPLIST_KEY_NSMicrophoneUsageDescription = "健康咨询员工端需要访问您的麦克风用来视频录制,是否同意?";
INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = "新疆员工端需要访问您的相册上传图片,方便您的使用,是否同意?";
INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "健康咨询想使用您的相册功能 是否同意?";
INFOPLIST_KEY_NSCameraUsageDescription = "健康油我需要访问您的相机用来档案功能,是否同意?";
INFOPLIST_KEY_NSLocationAlwaysAndWhenInUseUsageDescription = "健康油我需要您的定位服务,否则可能无法使用。";
INFOPLIST_KEY_NSLocationAlwaysUsageDescription = "健康油我需要您的定位服务,否则可能无法使用。";
INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "健康油我需要您的定位服务,否则可能无法使用。";
INFOPLIST_KEY_NSMicrophoneUsageDescription = "健康油我需要访问您的麦克风用来视频录制,是否同意?";
INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = "健康油我需要访问您的相册上传图片,方便您的使用,是否同意?";
INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "健康油我想使用您的相册功能 是否同意?";
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
INFOPLIST_KEY_UIUserInterfaceStyle = Light;
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
IPHONEOS_DEPLOYMENT_TARGET = 15;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
MARKETING_VERSION = 1.0.14;
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20";
PRODUCT_BUNDLE_IDENTIFIER = com.questionTools.XinjiangProject;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
@@ -509,12 +525,13 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.4;
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
};
name = Debug;
};
@@ -565,11 +582,12 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.4;
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
VALIDATE_PRODUCT = YES;
};
name = Release;
@@ -0,0 +1,102 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "2630"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"
buildArchitectures = "Automatic">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "1809E4612E092C710034C8FC"
BuildableName = "XinjiangProject.app"
BlueprintName = "XinjiangProject"
ReferencedContainer = "container:XinjiangProject.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "1809E47C2E092C740034C8FC"
BuildableName = "XinjiangProjectTests.xctest"
BlueprintName = "XinjiangProjectTests"
ReferencedContainer = "container:XinjiangProject.xcodeproj">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "1809E4862E092C740034C8FC"
BuildableName = "XinjiangProjectUITests.xctest"
BlueprintName = "XinjiangProjectUITests"
ReferencedContainer = "container:XinjiangProject.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "1809E4612E092C710034C8FC"
BuildableName = "XinjiangProject.app"
BlueprintName = "XinjiangProject"
ReferencedContainer = "container:XinjiangProject.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "1809E4612E092C710034C8FC"
BuildableName = "XinjiangProject.app"
BlueprintName = "XinjiangProject"
ReferencedContainer = "container:XinjiangProject.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -1,6 +1,6 @@
//
// NSArray+Sudoku.h
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/3/4.
//
@@ -1,6 +1,6 @@
//
// NSArray+Sudoku.m
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/3/4.
//
@@ -1,6 +1,6 @@
//
// NSAttributedString+Extension.h
// EscortProject
// XinjiangProject
//
// Created by 仁康信息 on 2023/3/14.
//
@@ -1,6 +1,6 @@
//
// NSAttributedString+Extension.m
// EscortProject
// XinjiangProject
//
// Created by 仁康信息 on 2023/3/14.
//
@@ -91,7 +91,7 @@ static char edgeKey;
break;
case DIYStyleImgBottom:
NSLog(@"%f",titleX);
DLog(@"%f",titleX);
self.titleEdgeInsets = UIEdgeInsetsMake(((selfH - totalH)/2.0 - titleY),
-(titleX + titleW/2.0 - selfW/2.0),
-((selfH - totalH)/2.0 - titleY),
@@ -156,7 +156,7 @@ static char edgeKey;
break;
case DIYStyleImgBottom:
NSLog(@"%f",titleX);
DLog(@"%f",titleX);
self.titleEdgeInsets = UIEdgeInsetsMake(((selfH - totalH)/2.0 - titleY),
-(titleX + titleW/2.0 - selfW/2.0),
-((selfH - totalH)/2.0 - titleY),
@@ -220,7 +220,7 @@ static char edgeKey;
break;
case DIYStyleImgBottom:
NSLog(@"%f",titleX);
DLog(@"%f",titleX);
self.titleEdgeInsets = UIEdgeInsetsMake(((selfH - totalH)/2.0 - titleY),
-(titleX + titleW/2.0 - selfW/2.0),
-((selfH - totalH)/2.0 - titleY),
@@ -288,7 +288,7 @@ static char edgeKey;
break;
case DIYStyleImgBottom:
NSLog(@"%f",titleX);
DLog(@"%f",titleX);
self.titleEdgeInsets = UIEdgeInsetsMake(((selfH - totalH)/2.0 - titleY),
-(titleX + titleW/2.0 - selfW/2.0),
-((selfH - totalH)/2.0 - titleY),
@@ -1,6 +1,6 @@
//
// UIDevice+model.h
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/3/29.
//
@@ -1,6 +1,6 @@
//
// UIDevice+model.m
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/3/29.
//
@@ -1,6 +1,6 @@
//
// UIImage+RoundedCorner.h
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/4/24.
//
@@ -1,6 +1,6 @@
//
// UIImage+RoundedCorner.m
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/4/24.
//
@@ -15,13 +15,11 @@
#define KNotificationLoginIMResult @"loginIMResult"
//切换tabar
#define KNotificSelectHomePageTabbar @"SlectHomePageTabBar"
#define KNotificSelectSoSTabbar @"SlectSoSTabBar"
#define KNotificSelectQuestionTabbar @"SlectQuestionTabBar"
#define KNotificSelectSOSCenterTabbar @"SlectSoSTabBar"
#define KNotificSelectWatchTabbar @"SlectMonitoringTabBar"
#define KNotificSelectPhysicalTabbar @"SlectPhysicalTabBar"
#define KNotificSelectFileTabbar @"SlectFileTabBar"
//同意协议
@@ -63,31 +61,52 @@
#pragma mark: 网络前缀
#define ResourceAddress [NSString stringWithFormat:@"%@/file/show/",Http]
//生产环境
//#define Http @"https://api.cqygjk.com"//
//#define H5Http @"https://console.cqygjk.com/"///
//#define H5DevHost @"cqyt.out.yg.icdat.cn"//
//#define IntervenH5 @"https://console.cqygjk.com"
//#define Http UserDefaultObjectForKey(@"HTTPS")//
//#define H5DevHost UserDefaultObjectForKey(@"H5DevHost")//
//#define IntervenH5 UserDefaultObjectForKey(@"IntervenH5")
//正式地址
//#define Http @"https://api-jkglpt.iosp.ydpt.tech"//
//#define H5DevHost @"api-jkglpt.iosp.ydpt.tech"//
//#define IntervenH5 @"https://console-jkglpt.iosp.ydpt.tech"
//#define SCHEME @"https" //
//#define OtherHttp @"https://api-jkglpt.iosp.ydpt.tech/hb" //
//测试环境地址
//四合一
//正文斌 @"http://192.168.1.28"。青海项目:https://quarry-api.yg.icdat.cn 四合一://https://starry.test.icdat.cn
//#define Http @"https://starry.test.icdat.cn"
//#define H5DevHost @"starry.test.icdat.cn"//
//#define IntervenH5 @"https://starry.out.icdat.cn"
//开发环境地址
#define Http @"http://cqyt.dev.yg.dt.io"//
#define H5DevHost @"cqyt.dev.yg.dt.io"//
#define IntervenH5 @"http://cms.dev.yg.dt.io"
#define BASEURL @"https://yyjk.cqygjk.com" //北边接口前缀
#define SCHEME @"http" //
//最新新疆测试地址
//#define Http @"http://192.168.1.223"//彭杰
// 最新地址
//#define Http @"http://192.168.1.47"//王昊
#define Http @"https://xj-api.yixiong-tech.com:8081"//
#define H5DevHost @"xjxc-api.mcrm.vip:8888"//
#define IntervenH5 @"http://10.10.10.228:23006/"
#define SCHEME @"https" //
#define OtherHttp @"https://gstest.superwx.cn/xj_health" //
#pragma mark - ——————— 健康知识/资讯 ————————
// H5 页面地址
#define kHealthKnowMoreH5 @"/healthnewsweb/healthKnow.html"
#define kHealthNewsMoreH5 @"/healthnewsweb/healthNews.html"
#define kHealthDetailH5 @"/healthnewsweb/healthNewsDetail.html"
#define kHealthSearchH5 @"/healthnewsweb/healthSecrch.html"
// HMAC-SHA256 签名密钥
#define kHealthKnowledgeSecretKey @"XJp3EHpcnwReXc1A"
//测试 健康知识+资讯
//#define kHealthKnowledgeBaseURL @"https://gstest.superwx.cn/healthcheck"
//#define kHealthKnowledgeH5Host @"https://gstest.superwx.cn"
//正式 健康知识+资讯
#define kHealthKnowledgeBaseURL @"https://api-jkglpt.iosp.ydpt.tech/hb"
#define kHealthKnowledgeH5Host @"https://console-jkglpt.iosp.ydpt.tech/hb"
// API 路径
#define kHealthKnowledgeTokenPath @"/pe/frontend/init"
#define kHealthKnowledgeCategoryPath @"/cms/frontend/category/list"
#define kHealthKnowledgeArticleListPath @"/cms/frontend/articleList"
// 急救宣教资源
#define kFirstAidResourceDetailPath @"/health-emergency/api/emergency/firstAid/resource/resource/queryById"
#endif /* StatusMacros_h */
@@ -10,9 +10,11 @@
#define ThirdMacros_h
//微信
#define kAppKey_Wechat @""
#define kAppKey_Wechat @"wxb33cd60beda0a212"
#define kSecret_Wechat @""
#define kSecret_Wechat @"9de1222d6c32af184538d2ae25d1f5a2"
#define kUniversalLink_Wechat @"https://www.rk-health.com"
#define UMShareAppKey @""
@@ -22,10 +24,11 @@
#define buglyAppid @""
#define SecretKey @"XJp3EHpcnwReXc1A"
//高德key
#define AMAPSDKKEY @"e5e5b1aa469fcf577c829165bae860dd"
#define AMAPSDKKEY @"43f28dcc5782a0aa98169624f6e94b76"
#define KNotificAgreeProtoocl @"AGREEPMAP"
@@ -184,10 +184,12 @@ alpha:1.0])
//数据验证
#define StrValid(f) ([f isKindOfClass:[NSNull class]] || f == nil || [f length] < 1 || [f isEqualToString:@"(null)"] || [f isEqualToString:@"<null>"] || [f isEqualToString:@"null"]? YES : NO)
#define SafeStr(f) (StrValid(f) ? f:@"")
#define HasString(str,key) ([str rangeOfString:key].location!=NSNotFound)
#define ValidStr(f) StrValid(f)
#define SafeStr(f) (!StrValid(f) ? f:@"-")
#define HasString(str,key) ([str rangeOfString:key].location!=NSNotFound)
#define ValidDict(f) (f!=nil && [f isKindOfClass:[NSDictionary class]])
#define ValidArray(f) (f!=nil && [f isKindOfClass:[NSArray class]] && [f count]>0)
#define ValidNum(f) (f!=nil && [f isKindOfClass:[NSNumber class]])
@@ -1,6 +1,6 @@
//
// CQAudioPlayManager.h
// EscortProject
// XinjiangProject
//
// Created by 仁康信息 on 2023/12/5.
//
@@ -1,6 +1,6 @@
//
// CQAudioPlayManager.m
// EscortProject
// XinjiangProject
//
// Created by 仁康信息 on 2023/12/5.
//
@@ -1,6 +1,6 @@
//
// DownToolsManager.h
// EscortProject
// XinjiangProject
//
// Created by 仁康信息 on 2023/12/1.
//
@@ -1,6 +1,6 @@
//
// DownToolsManager.m
// EscortProject
// XinjiangProject
//
// Created by 仁康信息 on 2023/12/1.
//
@@ -26,7 +26,7 @@
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
//下载进度
progress ? progress(downloadProgress) : nil;
NSLog(@"下载进度:%.2f%%",100.0*downloadProgress.completedUnitCount/downloadProgress.totalUnitCount);
DLog(@"下载进度:%.2f%%",100.0*downloadProgress.completedUnitCount/downloadProgress.totalUnitCount);
} destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
//拼接缓存目录
@@ -35,11 +35,11 @@
//拼接文件路径
NSString *filePath = [downloadStr stringByAppendingPathComponent:fileDir];
NSLog(@"downloadStr = %@",downloadStr);
DLog(@"downloadStr = %@",downloadStr);
return [NSURL fileURLWithPath:filePath];
} completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
NSLog(@"%@---%@", filePath, filePath.absoluteString);
DLog(@"%@---%@", filePath, filePath.absoluteString);
success ? success(filePath.absoluteString /** NSURL->NSString*/) : nil;
failure && error ? failure(error) : nil;
}];
@@ -57,7 +57,7 @@
//获取路径
NSString *documentsPath = [ReaderDocument documentsPath];
//可根据路径command + shift + G查看该路径下的所有的pdf文件
NSLog(@"%@", documentsPath);
DLog(@"%@", documentsPath);
NSString *filePath = [documentsPath stringByAppendingPathComponent:fileName];
ReaderDocument *document = [ReaderDocument withDocumentFilePath:filePath password:nil];
if (document != nil)
@@ -72,7 +72,7 @@
[self downloadWithURL:url fileDir:fileName progress:^(NSProgress *progress) {
} success:^(NSString *filePath) {
NSLog(@"%@", filePath);
DLog(@"%@", filePath);
//下载完成直接打开
[self downLoadPdfFileByUrl:url fileName:fileName];
} failure:^(NSError *error) {
@@ -93,7 +93,7 @@
NSString *filePath = [path stringByAppendingPathComponent:fileName];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL result = [fileManager fileExistsAtPath:filePath];
NSLog(@"这个文件已经存在:%@",result?@"是的":@"不存在");
DLog(@"这个文件已经存在:%@",result?@"是的":@"不存在");
return result;
}
@@ -53,4 +53,9 @@ typedef void (^FileDownloadFail)(int code, NSString * desc);
#pragma mark - 下载文件方法
- (void)downLoadFileWithUrl:(NSString *)urlStr Path:(NSString*)path downloadProgress:(void (^)(NSProgress *downloadProgress))progress SuccessBlock:(FileDownloadSucc)success FileDownloadFail:(FileDownloadFail)failure;
#pragma mark - 表单带参数
- (void)httpPostFormDataRequest:(NSString *)api params:(NSMutableDictionary *)params;
//外部接口
- (void)httpOtherPostRequest:(NSString *)api params:(NSMutableDictionary *)params;
@end
@@ -8,7 +8,7 @@
//
#import "JKCQNetworkingWithCache.h"
#import <CommonCrypto/CommonHMAC.h>
#define DYLog(...) NSLog(__VA_ARGS__) //如果不需要打印数据, 注释掉NSLog
@@ -20,6 +20,8 @@ typedef NS_ENUM(NSInteger, RequestType) {
RequestTypeMultiUpload,//多个上传
RequestTypeDownload,
RequestTypeUpLoadVideo,//上传视频
RequestTypeParmFormData,//参数表单
RequestTypeOterTypePost//外部接口
};
@implementation JKCQNetworkingWithCache
@@ -63,6 +65,11 @@ typedef NS_ENUM(NSInteger, RequestType) {
[self httpRequestWithUrlStr:api params:params requestType:RequestTypePost isCache:YES cacheKey:api imageKey:nil withData:nil withDataArray:nil];
}
- (void)httpOtherPostRequest:(NSString *)api params:(NSMutableDictionary *)params
{
[self httpRequestWithUrlStr:api params:params requestType:RequestTypeOterTypePost isCache:NO cacheKey:nil imageKey:nil withData:nil withDataArray:nil];
}
#pragma mark - 上传文件方法
//上传单张图片
- (void)upLoadDataWithUrlStr:(NSString *)api params:(NSMutableDictionary *)params imageKey:(NSString *)name withData:(NSData *)data
@@ -115,6 +122,13 @@ typedef NS_ENUM(NSInteger, RequestType) {
//5.开始启动下载任务
[task resume];
}
#pragma mark:表单上传参数
- (void)httpPostFormDataRequest:(NSString *)api params:(NSMutableDictionary *)params {
[self httpRequestWithUrlStr:api params:params requestType:RequestTypeParmFormData isCache:YES cacheKey:api imageKey:nil withData:nil withDataArray:nil];
}
#pragma mark - 网络请求统一处理
/**
@@ -142,6 +156,15 @@ typedef NS_ENUM(NSInteger, RequestType) {
if (![self requestBeforeJudgeConnect]) {//断网
[self showError:@"请检查网络设置"];
DYLog(@"\n\n----%@------\n\n",@"没有网络");
UIWindow *keyWindow = UIApplication.sharedApplication.windows.firstObject;
for (UIWindow *window in UIApplication.sharedApplication.windows) {
if (window.isKeyWindow) {
keyWindow = window;
break;
}
}
[MBProgressHUD hideHUDForView:keyWindow animated:YES];
return;
}
@@ -188,8 +211,18 @@ typedef NS_ENUM(NSInteger, RequestType) {
}else
{
NSLog(@"%@",url);
UIWindow *keyWindow = UIApplication.sharedApplication.windows.firstObject;
for (UIWindow *window in UIApplication.sharedApplication.windows) {
if (window.isKeyWindow) {
keyWindow = window;
break;
}
}
[MBProgressHUD hideHUDForView:keyWindow animated:YES];
[self showError:@"网络服务出错"];
}
// }
@@ -218,7 +251,19 @@ typedef NS_ENUM(NSInteger, RequestType) {
}
else
{
[self showError:@"网络服务出错"];
NSLog(@"%@",url);
[MBProgressHUD hideHUDForView:[HQCommonUtils getCurrentVC].view animated:YES];
UIWindow *keyWindow = UIApplication.sharedApplication.windows.firstObject;
for (UIWindow *window in UIApplication.sharedApplication.windows) {
if (window.isKeyWindow) {
keyWindow = window;
break;
}
}
[MBProgressHUD hideHUDForView:keyWindow animated:YES];
[EasyTextView showErrorText:@"请求超时"];
}
}];
@@ -296,6 +341,99 @@ typedef NS_ENUM(NSInteger, RequestType) {
}];
}else if(requestType == RequestTypeParmFormData) {//参数表单上传
[session.requestSerializer setValue:@"application/x-www-form-urlencoded;charset=utf-8" forHTTPHeaderField:@"Content-Type"];
[session POST:url parameters:nil headers:@{@"X-Access-Token":self.needToken} constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
// 这里我们通过将每一个键值对转换成 multipart 数据块来实现
[formData appendPartWithFormData:[params[@"userId"] dataUsingEncoding:NSUTF8StringEncoding] name:@"userId"];
} progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
// 请求成功处理
[weakSelf dealWithResponseObject:responseObject cacheUrl:url];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
// 请求失败处理
NSString * statusCode = [error.userInfo objectForKey:@"NSLocalizedDescription"];
if ([statusCode containsString:@"(401)"]) {
DLog(@"%@",error.userInfo);
[EasyTextView showErrorText:@"身份验证过期"];
[HQCommonUtils keyedArchiverWithData:nil key:LoginUserInfo];
KPostNotification(KNotificationLoginStateChange, @NO);
}
else {
[MBProgressHUD hideHUDForView:[HQCommonUtils getCurrentVC].view animated:YES];
UIWindow *keyWindow = UIApplication.sharedApplication.windows.firstObject;
for (UIWindow *window in UIApplication.sharedApplication.windows) {
if (window.isKeyWindow) {
keyWindow = window;
break;
}
}
[MBProgressHUD hideHUDForView:keyWindow animated:YES];
[EasyTextView showErrorText:@"请求超时"];
}
}];
}else if(requestType == RequestTypeOterTypePost) {//参数表单上传
//获取当前时间戳
NSDate *date = [NSDate date];
NSTimeInterval time = [date timeIntervalSince1970];
NSString *timeString = [NSString stringWithFormat:@"%.0f", time];
[session.requestSerializer setValue:@"application/json;charset=utf-8" forHTTPHeaderField:@"Content-Type"];
//加密
NSString * needSign = [NSString stringWithFormat:@"%@%@",timeString,params];
NSString * sign = [self signWithTimestamp:timeString body:params secretKey:SecretKey];
DLog(@"%@",sign);
[session POST:url parameters:params headers:@{@"X-Timestamp":timeString,@"X-Sign":sign} progress:^(NSProgress * _Nonnull downloadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
[weakSelf dealWithResponseObject:responseObject cacheUrl:allUrl];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSString * statusCode = [error.userInfo objectForKey:@"NSLocalizedDescription"];
if ([statusCode containsString:@"401"]) {
DLog(@"%@",error.userInfo);
[HQCommonUtils keyedArchiverWithData:nil key:LoginUserInfo];
KPostNotification(KNotificationLoginStateChange, @NO);
if (![HQCommonUtils isLogin]) {
[EasyTextView showErrorText:@"请您登录"];
}
else{
[EasyTextView showErrorText:@"身份信息已过期"];
}
}
else
{
NSLog(@"%@",url);
[MBProgressHUD hideHUDForView:[HQCommonUtils getCurrentVC].view animated:YES];
UIWindow *keyWindow = UIApplication.sharedApplication.windows.firstObject;
for (UIWindow *window in UIApplication.sharedApplication.windows) {
if (window.isKeyWindow) {
keyWindow = window;
break;
}
}
[MBProgressHUD hideHUDForView:keyWindow animated:YES];
[EasyTextView showErrorText:@"请求超时"];
}
}];
}
}
@@ -345,7 +483,7 @@ typedef NS_ENUM(NSInteger, RequestType) {
}
if ([response.allKeys containsObject:@"code"]) {
if ([[response objectForKey:@"code"] integerValue] == 200)
if ([[response objectForKey:@"code"] integerValue] == 200 ||( [[response objectForKey:@"code"] integerValue] == 0 && [url containsString:@"listAll"]))
{
flag = true;
}else
@@ -504,5 +642,38 @@ typedef NS_ENUM(NSInteger, RequestType) {
self.requestDelegate=nil;
}
#pragma mark:外部加密sign
- (NSString *)signWithTimestamp:(NSString *)timestamp
body:(NSDictionary *)bodyDict
secretKey:(NSString *)secretKey {
// 1 字典转 JSON
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:bodyDict options:0 error:nil];
NSString *body = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
// 2 拼接字符串
NSString *signString = [NSString stringWithFormat:@"%@%@", timestamp, body];
// 3 HMAC-SHA256
const char *key = [secretKey UTF8String];
const char *data = [signString UTF8String];
unsigned char result[CC_SHA256_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA256,
key,
strlen(key),
data,
strlen(data),
result);
// 4 转16进制
NSMutableString *hash = [NSMutableString string];
for (int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
[hash appendFormat:@"%02x", result[i]];
}
return hash;
}
@end
@@ -1,27 +0,0 @@
//
// SDGETHealthTokenManager.h
// EscortProject
//
// Created by 仁康信息 on 2024/1/4.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
typedef void (^successBlock)(NSDictionary *responseObject);
typedef void (^failedBlock)(NSError *error);
@interface SDGETHealthTokenManager : NSObject
+(SDGETHealthTokenManager *)getHealthTokenManager;
- (void)getTokenSuccess:(successBlock)success
failed:(failedBlock)failed;
-(void)getUserJoinStatusSuccess:(successBlock)success
failed:(failedBlock)failed;
@end
NS_ASSUME_NONNULL_END
@@ -1,195 +0,0 @@
//
// SDGETHealthTokenManager.m
// EscortProject
//
// Created by 仁康信息 on 2024/1/4.
//
#import "SDGETHealthTokenManager.h"
#include <CommonCrypto/CommonDigest.h>
#import "RSAObjC.h"
@interface SDGETHealthTokenManager ()
@property (nonatomic,strong)AFHTTPSessionManager *session;
@end
@implementation SDGETHealthTokenManager
#pragma mark - 初始化单例
+(SDGETHealthTokenManager *)getHealthTokenManager
{
static SDGETHealthTokenManager *manager = nil;
static dispatch_once_t pred;
dispatch_once(&pred, ^{
manager = [[self alloc] init];
});
return manager;
}
-(id)init
{
self = [super init];
if (self) {
_session = [AFHTTPSessionManager manager];
/***********请求的序列化**********/
//传Json 对象
_session.requestSerializer = [AFJSONRequestSerializer serializer];
//设置超时时间
[_session.requestSerializer willChangeValueForKey:@"timeoutInterval"];
_session.requestSerializer.timeoutInterval = 10.f;
[_session.requestSerializer didChangeValueForKey:@"timeoutInterval"];
/**********响应的序列化**************/
_session.responseSerializer = [AFJSONResponseSerializer serializer];
_session.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",@"text/json",@"text/plain" ,@"text/javascript",@"text/html",nil];
}
return self;
}
-(void)httpRequestWithURL:(NSString *)url
parameters:(NSDictionary*)paraDic
hearders:(NSDictionary *)hearder
success:(successBlock)success
failed:(failedBlock)failed
{
NSString *fullURL = [NSString stringWithFormat:@"%@/%@",BASEURL,url];
[_session POST:fullURL parameters:paraDic headers:hearder progress:^(NSProgress * _Nonnull uploadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
success(responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
failed(error);
}];
}
-(void)httpRequestGetWithURL:(NSString *)url
parameters:(NSDictionary*)paraDic
hearders:(NSDictionary *)hearder
success:(successBlock)success
failed:(failedBlock)failed
{
NSString *fullURL = [NSString stringWithFormat:@"%@/%@",BASEURL,url];
[_session GET:fullURL parameters:paraDic headers:hearder progress:nil success:^(NSURLSessionTask *task, NSDictionary * responseObject) {
success(responseObject);
} failure:^(NSURLSessionTask *operation, NSError *error) {
failed(error);
}];
}
- (void)getTokenSuccess:(successBlock)success failed:(failedBlock)failed {
NSMutableDictionary * dic = [[NSMutableDictionary alloc] init];
NSMutableDictionary * headerDic = [[NSMutableDictionary alloc] init];
NSDate * date = [NSDate date];
NSDateFormatter *matter = [[NSDateFormatter alloc] init];
matter.dateFormat = @"yyyyMMddHHmmss";
NSString * dateString = [matter stringFromDate:date];
[dic setObject:dateString forKey:@"timeSign"];
NSMutableDictionary * sigDic = [[NSMutableDictionary alloc] init];
[sigDic setObject:dateString forKey:@"timeSign"];
NSString * needSersy = [sigDic modelToJSONString];
// 时间戳
NSError *parseError;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:sigDic options:0 error:&parseError];
if (parseError) {
//解析出错
}
NSString * str = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
// 时间戳
NSMutableString * str3 = [[NSMutableString alloc]initWithString:str];
[str3 replaceOccurrencesOfString:@"\\" withString:@"" options:1 range:NSMakeRange(0, str3.length)];
[str3 appendString:@"dd05f1c54d63749eda95f9fa6d49v442a"];
NSString * md5str = [self getMd5_32Bit_String:str3];
[headerDic setObject:dateString forKey:@"X-TIMESTAMP"];
[headerDic setObject:md5str forKey:@"X-Sign"];
[self httpRequestGetWithURL:@"gateway/sys/getPublicKey" parameters:dic hearders:@{@"X-TIMESTAMP":dateString,@"X-Sign":md5str} success:^(NSDictionary * _Nonnull responseObject) {
if ([responseObject.allKeys containsObject:@"code"]) {
if ([[responseObject objectForKey:@"code"] integerValue] == 200)
{
NSString *pubkey ;
if ([responseObject.allKeys containsObject:@"result"]) {
pubkey = [NSString stringWithFormat:@"-----BEGIN PUBLIC KEY-----\n%@\n-----END PUBLIC KEY-----",responseObject[@"result"]];
// 时间戳
}
HQUserInfo * user = [HQCommonUtils keyedUnarchiverWithKey:LoginUserInfo];
NSString *ret = [RSAObjC encrypt:user.idCard PublicKey:pubkey];
DLog(@"encrypted: %@", ret);
if (ValidStr(ret)) {
// KPostNotification(KNotificationLoginStateChange, @NO);
return;
}
NSMutableDictionary * parmDic = [[NSMutableDictionary alloc] init];
[parmDic setObject:[NSString stringWithFormat:@"RSA_%@",ret] forKey: @"idcard"];
NSDate * date = [NSDate date];
NSDateFormatter *matter = [[NSDateFormatter alloc] init];
matter.dateFormat = @"yyyyMMddHHmmss";
NSString * dateString = [matter stringFromDate:date];
NSError *parseError;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:parmDic options:0 error:&parseError];
if (parseError) {
//解析出错
}
NSString * str = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
// 时间戳
NSMutableString * str3 = [[NSMutableString alloc]initWithString:str];
[str3 replaceOccurrencesOfString:@"\\" withString:@"" options:1 range:NSMakeRange(0, str3.length)];
[str3 appendString:@"dd05f1c54d63749eda95f9fa6d49v442a"];
NSString * md5str = [self getMd5_32Bit_String:str3];
[self httpRequestWithURL:@"gateway/sys/thirdAppGetTokenByIdCard" parameters:parmDic hearders:@{@"X-TIMESTAMP":dateString,@"X-Sign":md5str} success:success failed:failed];
}
else
{
success(responseObject);
}
}
} failed:^(NSError * _Nonnull error) {
}];
}
- (NSString *)getMd5_32Bit_String:(NSString *)srcString {
// 参数 srcString 传进来的字符串
// 参数 isUppercase 是否需要大小写
const char *cStr = [srcString UTF8String];
unsigned char digest[CC_MD5_DIGEST_LENGTH];
CC_MD5( cStr, (CC_LONG)srcString.length, digest );
NSMutableString *result = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
[result appendFormat:@"%02X", digest[i]];
return result;
}
@end
@@ -1,33 +0,0 @@
//
// SDHttpRequest.h
// colorPrintingMaster
//
// Created by 青山小明 on 17/5/3.
// Copyright © 2017年 zhangming. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef void (^successBlock)(NSDictionary *responseObject);
typedef void (^failedBlock)(NSError *error);
@interface SDHttpRequest : NSObject
+(SDHttpRequest *)httpRequest;
#pragma mark - 首页
- (void)getInterWatchDataUrlWithParm:(NSMutableDictionary *)parmDic
Success:(successBlock)success
failed:(failedBlock)failed;
#pragma mark -
-(void)postWithParameter:(NSDictionary *)para
images:(NSArray *)images
success:(successBlock)success
failed:(failedBlock)failed;
//获取服务地址
- (void)getChangeUrlSuccess:(successBlock)success
failed:(failedBlock)failed;
@end
@@ -1,133 +0,0 @@
//
// SDHttpRequest.m
// colorPrintingMaster
//
// Created by 青山小明 on 17/5/3.
// Copyright © 2017年 zhangming. All rights reserved.
//
#import "SDHttpRequest.h"
#import "AFNetworking.h"
#include <CommonCrypto/CommonDigest.h>
#import "RSAObjC.h"
//static SDHttpRequest *singleton = nil;
@interface SDHttpRequest ()
@property (nonatomic,strong)AFHTTPSessionManager *session;
@end
@implementation SDHttpRequest
#pragma mark - 初始化单例
+(SDHttpRequest *)httpRequest
{
static SDHttpRequest *manager = nil;
static dispatch_once_t pred;
dispatch_once(&pred, ^{
manager = [[self alloc] init];
});
return manager;
}
-(id)init
{
self = [super init];
if (self) {
_session = [AFHTTPSessionManager manager];
/***********请求的序列化**********/
//传Json 对象
_session.requestSerializer = [AFJSONRequestSerializer serializer];
//设置超时时间
[_session.requestSerializer willChangeValueForKey:@"timeoutInterval"];
_session.requestSerializer.timeoutInterval = 30.f;
[_session.requestSerializer didChangeValueForKey:@"timeoutInterval"];
/**********响应的序列化**************/
_session.responseSerializer = [AFJSONResponseSerializer serializer];
_session.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",@"text/json",@"text/plain" ,@"text/javascript",@"text/html",nil];
}
return self;
}
#pragma mark---请求调用的方法
-(void)httpRequestWithURL:(NSString *)url
parameters:(NSDictionary*)paraDic
success:(successBlock)success
failed:(failedBlock)failed
{
NSUserDefaults * tokenDefaul = [NSUserDefaults standardUserDefaults];
NSString * token = [tokenDefaul objectForKey:KHEALTHTOKEN];
NSString *fullURL = [NSString stringWithFormat:@"%@/%@",BASEURL,url];
[_session POST:fullURL parameters:paraDic headers: @{@"X-Access-Token":token} progress:^(NSProgress * _Nonnull uploadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
success(responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
failed(error);
}];
}
- (void)uploadImagesWithURL:(NSString *)url
parameters:(NSDictionary *)paraDic
hearders:(NSDictionary *)hearder
imagesKey:(NSString *)imagesKey
images:(NSArray *)images
success:(successBlock)success
failed:(failedBlock)failed
{
NSString *fullURL = [NSString stringWithFormat:@"%@/%@",BASEURL,url];
[_session POST:fullURL parameters:paraDic headers:hearder constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
for (UIImage *image in images)
{
[formData appendPartWithFileData:UIImageJPEGRepresentation(image, 0.5)
name:imagesKey
fileName:@"1.jpeg"
mimeType:@"image/jpeg"];
}
} progress:^(NSProgress * _Nonnull uploadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
success(responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
failed(error);
}];
}
-(void)httpRequestGetWithURL:(NSString *)url
parameters:(NSDictionary*)paraDic
success:(successBlock)success
failed:(failedBlock)failed
{
NSUserDefaults * tokenDefaul = [NSUserDefaults standardUserDefaults];
NSString * token = [tokenDefaul objectForKey:KHEALTHTOKEN];
NSString *fullURL = [NSString stringWithFormat:@"%@/%@",BASEURL,url];
[_session GET:fullURL parameters:paraDic headers:@{@"X-Access-Token":token} progress:nil success:^(NSURLSessionTask *task, NSDictionary * responseObject) {
success(responseObject);
} failure:^(NSURLSessionTask *operation, NSError *error) {
failed(error);
}];
}
#pragma mark - 首页
- (void)getInterWatchDataUrlWithParm:(NSMutableDictionary *)parmDic
Success:(successBlock)success
failed:(failedBlock)failed {
//参数
[self httpRequestGetWithURL:@"health-watch/watchH5Api/indexDataNew"
parameters:parmDic success:success failed:failed];
}
@end
@@ -9,7 +9,7 @@
#import <Foundation/Foundation.h>
#import "JKCQNetworkingWithCache.h"
@interface JKCQAPI : NSObject
@interface XJPNetAPI : NSObject
@property (nonatomic,strong) JKCQNetworkingWithCache * httpRequest;
@@ -27,7 +27,28 @@
- (void)GetSoSHomePageResources:(NSMutableDictionary *)pamraDic;
- (void)PostEndSoSIMQuestion:(NSMutableDictionary *)pamraDic;
- (void)getSoSCarInfoLocationHome:(NSMutableDictionary *)parmDic;
// 急救员 - 搜索专家
- (void)getSearchExpert:(NSMutableDictionary *)parmDic;
// 急救员 - 搜索员工
- (void)getSearchEmployee:(NSMutableDictionary *)parmDic;
// 急救员 - 我参与的应急工单
- (void)getMyParticipatedOrders:(NSMutableDictionary *)parmDic;
// 急救员 - 创建群聊(不发起音视频通话)
- (void)getCreateGroupMagFirstAider:(NSMutableDictionary *)parmDic;
// 急救员 - 邀请进群
- (void)postAddGroupUser:(NSMutableDictionary *)parmDic;
// 急救员 - 移除群成员
- (void)postRemoveGroupUser:(NSMutableDictionary *)parmDic;
// 急救员 - 判断是否联络员
- (void)getIsLiaisonUser:(NSMutableDictionary *)parmDic;
// 急救员 - 群成员列表
- (void)getGroupMemberList:(NSMutableDictionary *)parmDic;
// 急救员 - 实际群成员列表(经腾讯IM验证,含isSelf字段)
- (void)getActualGroupMemberList:(NSMutableDictionary *)parmDic;
// 急救员 - 宣教资源详情
- (void)getFirstAidResourceDetail:(NSMutableDictionary *)parmDic;
// 一人一案 - 健康档案详情
- (void)getOnePersonCase:(NSMutableDictionary *)parmDic;
//首页接口
- (void)GetQuetsionRecordsList:(NSMutableDictionary *)parmDic;
@@ -73,6 +94,7 @@
- (void)getOneKeyQuestionByID:(NSMutableDictionary *)parmDic;
- (void)postSearchOneKeyQuestionData:(NSMutableDictionary *)parmDic;
- (void)getHistoryReportById:(NSMutableDictionary *)parmDic;
- (void)recordDoctorCardInfoClick:(NSMutableDictionary *)parmDic;
#pragma mark:咨询人管理
@@ -123,4 +145,68 @@
- (void)getMinitringWatchData:(NSMutableDictionary *)parmDic;
- (void)getInterMonitoringMaxMinData:(NSMutableDictionary *)parmDic;
- (void)getWarningWatchListV2Data:(NSMutableDictionary *)parmDic;
- (void)getWranHistoryList:(NSMutableDictionary *)parmDic;
- (void)getSOSDoctorRecordList:(NSMutableDictionary *)parmDic;
- (void)getSOSDoctorDetailInfo:(NSMutableDictionary *)parmDic;
- (void)getSOSSmallSumData:(NSMutableDictionary *)parmDic;
- (void)healthAccountLogin:(NSMutableDictionary *)parmDic;
//版本更新
- (void)GetAppVesionUpdata:(NSMutableDictionary *)parmDic;
#pragma mark:模拟数据
//获取模拟用户信息(判断是否为模拟)
- (void)postSimulationUser:(NSMutableDictionary *)parmDic;
//获取系统用户数据(查询全部用户,不做租户隔离)
- (void)getSimulationUserList:(NSMutableDictionary *)parmDic;
//开启模拟
- (void)postStartedSimulationUser:(NSMutableDictionary *)parmDic;
//恢复用户状态
- (void)postRecoverySimulationUser:(NSMutableDictionary *)parmDic;
//消息
- (void)getUserMessageList:(NSMutableDictionary *)parmDic;
- (void)getUserMessageDetailConnet:(NSMutableDictionary *)parmDic;
- (void)getHomepageBannerList:(NSMutableDictionary *)parmDic;
//我的积分
- (void)getPointsBankHeard:(NSMutableDictionary *)parmDic;
- (void)postPointsBankRankData:(NSMutableDictionary *)parmDic;
- (void)postPointsBankSourceDetail:(NSMutableDictionary *)parmDic;
- (void)postPointsCheckInCard:(NSMutableDictionary *)parmDic;
//积分任务
- (void)postPointsTaskList:(NSMutableDictionary *)parmDic;
//图片地址
- (void)getDetailImageAddress:(NSMutableDictionary *)parmDic;
//轮播图一次性全请求
- (void)getHomeBannerAllData:(NSMutableDictionary *)parmDic;
//手表接口
- (void)getHomeWatchWearBool:(NSMutableDictionary *)parmDic;
- (void)getHomeWatchData:(NSMutableDictionary *)parmDic;
- (void)getWebNeedEncryptionKey:(NSMutableDictionary *)parmDic;
//绑定手表
- (void)getBindWatchDevice:(NSMutableDictionary *)parmDic;
//解绑手表
- (void)getUnBindWatchDevice:(NSMutableDictionary *)parmDic;
- (void)postPointsUnmberData:(NSMutableDictionary *)parmDic;
@end
@@ -1,18 +1,12 @@
//
// API.m
// XZYNetworking
//
// Created by on 2017/12/25.
// Copyright © 2017 . All rights reserved.
//
#import "JKCQAPI.h"
#import "XJPNetAPI.h"
#define needToken httpRequest.needToken
#define isLoginFlag httpRequest.isLoginFlag
@implementation JKCQAPI
@implementation XJPNetAPI
#pragma mark - init方法
@synthesize httpRequest;
@@ -70,11 +64,66 @@
- (void)getSoSCarInfoLocationHome:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/medical-center/api/ambulance/nearbyAmbulance",Http] params:parmDic];
}
// -
- (void)getSearchExpert:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-emergency/api/emergency/order/searchExpert",Http] params:parmDic];
}
// -
- (void)getIsLiaisonUser:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-emergency/emergency/LargeScreenNew/isLiaisonUser",Http] params:parmDic];
}
// -
- (void)getCreateGroupMagFirstAider:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-emergency/api/emergency/createGroupMagFirstAider",Http] params:parmDic];
}
// -
- (void)getMyParticipatedOrders:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-emergency/api/emergency/order/myParticipatedOrders",Http] params:parmDic];
}
// -
- (void)getSearchEmployee:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-emergency/api/emergency/order/searchEmployee",Http] params:parmDic];
}
// -
- (void)postAddGroupUser:(NSMutableDictionary *)parmDic {
[httpRequest httpPostRequest:[NSString stringWithFormat:@"%@/health-emergency/api/emergency/addGroupUser",Http] params:parmDic];
}
// -
- (void)postRemoveGroupUser:(NSMutableDictionary *)parmDic {
[httpRequest httpPostRequest:[NSString stringWithFormat:@"%@/health-emergency/api/emergency/removeGroupUser",Http] params:parmDic];
}
// -
- (void)getGroupMemberList:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-emergency/api/emergency/order/getGroupMemberList",Http] params:parmDic];
}
// - IM验证isSelf字段
- (void)getActualGroupMemberList:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-emergency/api/emergency/order/getActualGroupMemberList",Http] params:parmDic];
}
// -
- (void)getFirstAidResourceDetail:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-emergency/api/emergency/firstAid/resource/resource/queryById",Http] params:parmDic];
}
// -
- (void)getOnePersonCase:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-emergency/emergency/LargeScreenNew/onePersonCase",Http] params:parmDic];
}
- (void)getNearbyHomePageHospitalPoint:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/medical-center/api/resource/nearbyResource",Http] params:parmDic];
@@ -106,6 +155,13 @@
}
//
- (void)recordDoctorCardInfoClick:(NSMutableDictionary *)parmDic {
[httpRequest httpPostRequest:[NSString stringWithFormat:@"%@/health-consultation/con-message/saveReadLog",Http] params:parmDic];
}
- (void)GetAllHistoryChatRecord:(NSMutableDictionary *)parmDic {
//http://192.168.1.28/health-consultation/?groupId=1801087415104962560&pageNo=1&pageSize=10
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-consultation/api/consult/conSession/selectImMessagePageListSession",Http] params:parmDic];
@@ -550,7 +606,7 @@
- (void)getUserAgreementPrivacy:(NSMutableDictionary *)parmDic {
//GET https://cqyt.test.yg.icdat.cn/health-consultation/api/consult/conDoctor/selectDictList?dictKey=jump_url HTTP/1.1
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-consultation/api/consult/conDoctor/selectDictList?dictKey=qh_ios_jump_url",Http] params:parmDic];
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-consultation/api/consult/conDoctor/selectDictList?dictKey=jump_url",Http] params:parmDic];
}
@@ -747,5 +803,185 @@
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-watch/watchH5Api/indexDataNew",Http] params:parmDic];
}
//
- (void)getWarningWatchListV2Data:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-watch/watchH5Api/indexDataNew/v2",Http] params:parmDic];
}
- (void)getInterMonitoringMaxMinData:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-watch/watchH5Api/thresholdSetting",Http] params:parmDic];
}
- (void)getWranHistoryList:(NSMutableDictionary *)parmDic {
// https://health-api.tzgl.shuziweidao.com/health-watch/watchH5Api/historicalWarn?eventType=spo2&queryDate=2025-07-01&userId=1898914204455915521&pageNo=1&pageSize=100
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-watch/watchH5Api/historicalWarn",Http] params:parmDic];
}
//
- (void)getSOSDoctorRecordList:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-emergency/api/emergency/order/initUserOrderPage",Http] params:parmDic];
}
- (void)getSOSDoctorDetailInfo:(NSMutableDictionary *)parmDic {
//GET https://cqyt.test.yg.icdat.cn/health-emergency/api/emergency/order/orderThrough?id=1744265549623332865 HTTP/1.1
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-emergency/api/emergency/order/getOrderById",Http] params:parmDic];
}
//
- (void)getSOSSmallSumData:(NSMutableDictionary *)parmDic {
//
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-emergency/api/emergency/order/orderThrough",Http] params:parmDic];
}
//
- (void)healthAccountLogin:(NSMutableDictionary *)parmDic {
[httpRequest httpPostRequest:[NSString stringWithFormat:@"%@/sys/mLoginAnYan",Http] params:parmDic];
}
//
- (void)GetAppVesionUpdata:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-system/version/getSysVersionDetailByPackageName",Http] params:parmDic];
}
#pragma mark:模拟用户
- (void)postSimulationUser:(NSMutableDictionary *)parmDic {
[httpRequest httpPostRequest:[NSString stringWithFormat:@"%@/health-system/test/fakeUser",Http] params:parmDic];
}
//
- (void)getSimulationUserList:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-system/sys/user/listAll",Http] params:parmDic];
}
//
- (void)postStartedSimulationUser:(NSMutableDictionary *)parmDic{
[httpRequest httpPostFormDataRequest:[NSString stringWithFormat:@"%@/health-system/test/fake",Http] params:parmDic];
}
//
- (void)postRecoverySimulationUser:(NSMutableDictionary *)parmDic{
[httpRequest httpPostRequest:[NSString stringWithFormat:@"%@/health-system/test/restore",Http] params:parmDic];
}
- (void)getUserMessageList:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-system/app/sys/message/notice/list",Http] params:parmDic];
}
- (void)getUserMessageDetailConnet:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-system/app/sys/message/notice/queryById",Http] params:parmDic];
}
//
- (void)getHomepageBannerList:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/sys/api/banner/selectBannerList",Http] params:parmDic];
}
- (void)getWebNeedEncryptionKey:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-system/api/sys/encryptInfo",Http] params:parmDic];
}
//
- (void)getPointsBankHeard:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-system/bank/userPoints/app/myPoints",Http] params:parmDic];
}
//
- (void)postPointsBankRankData:(NSMutableDictionary *)parmDic {
[httpRequest httpPostRequest:[NSString stringWithFormat:@"%@/health-system/bank/userPoints/app/pointRanking",Http] params:parmDic];
}
//
- (void)postPointsBankSourceDetail:(NSMutableDictionary *)parmDic {
[httpRequest httpPostRequest:[NSString stringWithFormat:@"%@/health-system/bank/userPoints/app/pointRecord",Http] params:parmDic];
}
//
- (void)postPointsCheckInCard:(NSMutableDictionary *)parmDic {
[httpRequest httpPostRequest:[NSString stringWithFormat:@"%@/health-system/bank/userPoints/app/pointCheckIn",Http] params:parmDic];
}
//
- (void)postPointsTaskList:(NSMutableDictionary *)parmDic {
[httpRequest httpPostRequest:[NSString stringWithFormat:@"%@/health-system/bank/userPoints/app/pointsTaskList",Http] params:parmDic];
}
//
- (void)getDetailImageAddress:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-consultation/consultation/conSession/getPicUrl",Http] params:parmDic];
}
- (void)getHomeBannerAllData:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-system/sys/api/banner/selectAllBannerList",Http] params:parmDic];
}
#pragma mark:手表相关
//
- (void)getHomeWatchWearBool:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-watch/api/watchData/findWatchInfo",Http] params:parmDic];
}
//
- (void)getHomeWatchData:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-watch/api/watchData/userWatchDataAll",Http] params:parmDic];
}
- (void)getBindWatchDevice:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-watch/watch/watchDevice/app/bindDevice",Http] params:parmDic];
}
//
- (void)getUnBindWatchDevice:(NSMutableDictionary *)parmDic {
[httpRequest httpGetRequest:[NSString stringWithFormat:@"%@/health-watch/watch/watchDevice/app/unbundleDevice",Http] params:parmDic];
}
//
- (void)postPointsUnmberData:(NSMutableDictionary *)parmDic {
[httpRequest httpOtherPostRequest:[NSString stringWithFormat:@"%@/api/v1/users/point-details",OtherHttp] params:parmDic];
}
@end
@@ -1,6 +1,6 @@
//
// ESCTUIManager.h
// EscortProject
// XinjiangProject
//
// Created by 仁康信息 on 2023/2/16.
//
@@ -1,6 +1,6 @@
//
// ESCTUIManager.m
// EscortProject
// XinjiangProject
//
// Created by 仁康信息 on 2023/2/16.
//
@@ -28,9 +28,12 @@
[TUILogin login:sdkAppid userID:userID userSig:userSig succ:^{
// KPostNotification(KNotificationLoginIMResult, @YES);
HQUserInfo *user = [HQCommonUtils keyedUnarchiverWithKey:LoginUserInfo];
[[TUICallKit createInstance] setSelfInfo:user.realname avatar:user.avatar succ:nil fail:nil];
DLog(@"IM登录成功");
} fail:^(int code, NSString *msg) {
[EasyTextView showErrorText:@"IM登录失败"];
@@ -76,10 +79,10 @@
[TUIChatConfig defaultConfig].enableAudioCall = isAudio; // YES:开启,NO:关闭
// 把 TUIC2CChatViewController 添加到自己的 ViewController
HQBaseViewController * currentVc =(HQBaseViewController *)[HQCommonUtils getCurrentVC];
XJBaseViewController * currentVc =(XJBaseViewController *)[HQCommonUtils getCurrentVC];
if (!currentVc) {
currentVc = [[HQBaseViewController alloc] init];
currentVc = [[XJBaseViewController alloc] init];
}
[currentVc addChildViewController:vc];
[currentVc.view addSubview:vc.view];
@@ -103,7 +106,6 @@
}
+ (void)sendGroupVideo:(NSString *)groupID withUserIdList:(NSArray *)userList {
[[TUICallKit createInstance] groupCall:groupID userIdList:userList callMediaType:TUICallMediaTypeVideo];
}
@@ -21,9 +21,10 @@
[aCoder encodeObject:self.depart_id forKey:@"depart_id"];
[aCoder encodeObject:self.parentId forKey:@"parentId"];
[aCoder encodeObject:self.departName forKey:@"departName"];
[aCoder encodeObject:self.workNo forKey:@"workNo"];
[aCoder encodeObject:self.token forKey:@"token"];
[aCoder encodeObject:self.sex_dictText forKey:@"sex_dictText"];
}
@@ -43,6 +44,8 @@
self.parentId = [aDecoder decodeObjectForKey:@"parentId"];
self.departName = [aDecoder decodeObjectForKey:@"departName"];
self.token = [aDecoder decodeObjectForKey:@"token"];
self.workNo = [aDecoder decodeObjectForKey:@"workNo"];
self.sex_dictText = [aDecoder decodeObjectForKey:@"sex_dictText"];
}
@@ -51,21 +54,41 @@
- (void)setUserInfo:(NSDictionary *)userInfo {
if (![userInfo isKindOfClass:[NSDictionary class]]) {
return;
}
_userInfo = userInfo;
self.user_id = [_userInfo objectForKey:@"id"];
self.avatar = [NSString stringWithFormat:@"%@%@",ResourceAddress,[_userInfo objectForKey:@"avatar"]];
self.phone = [_userInfo objectForKey:@"phone"];
self.realname = [_userInfo objectForKey:@"realname"];
self.username = [_userInfo objectForKey:@"username"];
self.sex = [_userInfo objectForKey:@"sex"];
self.idCard = [_userInfo objectForKey:@"idCard"];
self.personType = [_userInfo objectForKey:@"personType"];
self.secondDepart = [_userInfo objectForKey:@"secondDepart"];
self.sex_dictText = [_userInfo objectForKey:@"sex_dictText"];
self.depart_id = [self.secondDepart objectForKey:@"id"];
self.parentId = [self.secondDepart objectForKey:@"parentId"];
self.departName = [self.secondDepart objectForKey:@"departName"];
// 一个小工具块,用于安全取值(避免 NSNull)
id (^safeValue)(id obj) = ^id(id obj) {
return (obj && ![obj isKindOfClass:[NSNull class]]) ? obj : nil;
};
self.user_id = safeValue(userInfo[@"id"]);
NSString *avatarPath = safeValue(userInfo[@"avatar"]);
self.avatar = avatarPath ? [NSString stringWithFormat:@"%@%@", ResourceAddress, avatarPath] : nil;
self.phone = safeValue(userInfo[@"phone"]);
self.realname = safeValue(userInfo[@"realname"]);
self.username = safeValue(userInfo[@"username"]);
self.sex = safeValue(userInfo[@"sex"]);
self.idCard = safeValue(userInfo[@"idCard"]);
self.personType = safeValue(userInfo[@"personType"]);
self.sex_dictText = safeValue(userInfo[@"sex_dictText"]);
self.workNo = safeValue(userInfo[@"workNo"]);
NSDictionary *secondDepart = safeValue(userInfo[@"secondDepart"]);
if ([secondDepart isKindOfClass:[NSDictionary class]]) {
self.secondDepart = secondDepart;
self.depart_id = safeValue(secondDepart[@"id"]);
self.parentId = safeValue(secondDepart[@"parentId"]);
self.departName = safeValue(secondDepart[@"departName"]);
} else {
self.secondDepart = nil;
self.depart_id = self.parentId = self.departName = nil;
}
}
@@ -0,0 +1,44 @@
<?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">
<plist version="1.0">
<dict>
<key>AvailableLibraries</key>
<array>
<dict>
<key>BinaryPath</key>
<string>WechatOpenSDK.framework/WechatOpenSDK</string>
<key>LibraryIdentifier</key>
<string>ios-arm64</string>
<key>LibraryPath</key>
<string>WechatOpenSDK.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
</dict>
<dict>
<key>BinaryPath</key>
<string>WechatOpenSDK.framework/WechatOpenSDK</string>
<key>LibraryIdentifier</key>
<string>ios-arm64_x86_64-simulator</string>
<key>LibraryPath</key>
<string>WechatOpenSDK.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict>
</array>
<key>CFBundlePackageType</key>
<string>XFWK</string>
<key>XCFrameworkFormatVersion</key>
<string>1.0</string>
</dict>
</plist>
@@ -0,0 +1,17 @@
<?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">
<plist version="1.0">
<dict>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
</array>
</dict>
</plist>
@@ -0,0 +1,167 @@
重要!
SDK2.0.5
1. 支持模块化集成​:XCFramework 头文件引用改为标准化格式 #import <WechatOpenSDK/WXApi.h>,解决路径冲突并支持 Swift/ObjC 混合开发
2. 修复openWXApp偶现失败的问题
SDK2.0.4
1.增加privacy manifest文件
2.修复跳微信时可能卡顿的问题
SDK2.0.2
1. 优化XCFramework打包方式
SDK2.0.1
1. SDK支持XCFramework
SDK2.0.0
1. 分享能力支持内容防篡改校验
SDK1.9.9
1. 授权登录支持关闭自动授权
2. 分享支持添加签名,防止篡改
SDK1.9.7
1. 适配CocoaPods
SDK1.9.6
1. 适配iOS 16,减少读写剪切板
SDK1.9.4
1. 修复授权登录取消/拒绝时state字段没有带回
SDK1.9.3
1. 新增发起二维码支付能力
SDK1.9.2
1. 新增发起企微客服会话能力
SDK1.9.1
1. 音乐视频分享类型增加运营H5字段
SDK1.8.9
1. 增加音乐视频分享类型
SDK1.8.8
1. 增加游戏直播消息类型
SDK1.8.7.1
1. 修复Xcode11以下编译不通过
SDK1.8.7
1. 修复iPadOS,未安装微信的情况下,因为UA问题无法授权登录
2. 修复未安装微信的情况下, 适配了UIScene的App因为UIAlertView Crash
3. 增加Universal Link检测函数
SDK1.8.6.2
1. 修改包含"UIWebView"字符的类名
SDK1.8.6.1
1.短信授权登录使用的UIWebview切换成WKWebview
SDK1.8.6
1. 支持Universal Link拉起微信以及返回App
2. SDK移除MTA库
SDK1.8.5
1. 更换MTA库:取消对剪切板的访问, 防止和其他SDK竞争导致crash
2. NSMutableArray的MTA分类方法改名,减少命名冲突
3. 不含支付功能版本移除非税支付和医保支付接口
4. 分享音乐支持填写歌词和高清封面图
SDK1.8.4
1. 调整分享图片大小限制
2. 新增openBusinessView接口
SDK1.8.3
1. SDK增加调起微信刷卡支付接口
2. SDK增加小程序订阅消息接口
3. 修复小程序订阅消息接口没有resp的问题
SDK1.8.2
1. SDK增加开发票授权 WXInvoiceAuthInsert
2. SDK增加非税接口 WXNontaxPay
3. SDK增加医保接口 WXPayInsurance
4. 更换MTA库
SDK1.8.1
1. SDK打开小程序支持指定版本(体验,开发,正式版)
2. SDK分享小程序支持指定版本(体验,开发,正式版)
3. SDK支持输出log日志
SDK1.8.0
1. SDK支持打开小程序
2. SDK分享小程序支持shareTicket
SDK1.7.9
1. SDK订阅一次性消息
SDK1.7.8
1 SDK分享小程序支持大图
SDK1.7.7
1 增加SDK分享小程序
2 增加选择发票接口
SDK1.7.6
1. 提高稳定性
1 修复mta崩溃
2 新增接口支持开发者关闭mta数据统计上报
SDK1.7.5
1. 提高稳定性
2. 加快registerApp接口启动速度
SDK1.7.4
1. 更新支持iOS启用 ATS(App Transport Security)
2. 需要在工程中链接CFNetwork.framework
3. 在工程配置中的”Other Linker Flags”中加入”-Objc -all_load”
SDK1.7.3
1. 增强稳定性,适配iOS10
2. 修复小于32K的jpg格式缩略图设置失败的问题
SDK1.7.2
1. 修复因CTTeleponyNetworkInfo引起的崩溃问题
SDK1.7.1
1. 支持兼容ipv6(提升稳定性)
2. xCode Version 7.3.1 (7D1014) 编译
SDK1.7
1. 支持兼容ipv6
2. 修复若干问题增强稳定性
SDK1.6.3
1. xCode7.2 构建的sdk包。
2. 请使用xCode7.2进行编译。
3. 需要在Build Phases中Link Security.framework
4. 修复若干小问题。
SDK1.6.2
1、xCode7.1 构建的sdk包
2、请使用xCode7.1进行编译
SDK1.6.1
1、修复armv7s下,bitcode可能编译不过
2、解决warning
SDK1.6
1、iOS 9系统策略更新,限制了http协议的访问,此外应用需要在“Info.plist”中将要使用的URL Schemes列为白名单,才可正常检查其他应用是否安装。
受此影响,当你的应用在iOS 9中需要使用微信SDK的相关能力(分享、收藏、支付、登录等)时,需要在“Info.plist”里增加如下代码:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>weixin</string>
</array>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
2、开发者需要在工程中链接上 CoreTelephony.framework
3、解决bitcode编译不过问题
SDK1.5
1、废弃safeSendReq:接口,使用sendReq:即可。
2、新增+(BOOL) sendAuthReq:(SendAuthReq*) req viewController : (UIViewController*) viewController delegate:(id<WXApiDelegate>) delegate;
支持未安装微信情况下Auth,具体见WXApi.h接口描述
3、微信开放平台新增了微信模块用户统计功能,便于开发者统计微信功能模块的用户使用和活跃情况。开发者需要在工程中链接上:SystemConfiguration.framework,libz.dylib,libsqlite3.0.dylib。
@@ -0,0 +1,231 @@
//
// WXApi.h
// 所有Api接口
//
// Created by Wechat on 12-2-28.
// Copyright (c) 2012年 Tencent. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "WXApiObject.h"
NS_ASSUME_NONNULL_BEGIN
typedef BOOL(^WXGrantReadPasteBoardPermissionCompletion)(void);
#pragma mark - WXApiDelegate
/*! @brief 接收并处理来自微信终端程序的事件消息
*
* 接收并处理来自微信终端程序的事件消息,期间微信界面会切换到第三方应用程序。
* WXApiDelegate 会在handleOpenURL:delegate:中使用并触发。
*/
@protocol WXApiDelegate <NSObject>
@optional
/*! @brief 收到一个来自微信的请求,第三方应用程序处理完后调用sendResp向微信发送结果
*
* 收到一个来自微信的请求,异步处理完成后必须调用sendResp发送处理结果给微信。
* 可能收到的请求有GetMessageFromWXReq、ShowMessageFromWXReq等。
* @param req 具体请求内容,是自动释放的
*/
- (void)onReq:(BaseReq*)req;
/*! @brief 发送一个sendReq后,收到微信的回应
*
* 收到一个来自微信的处理结果。调用一次sendReq后会收到onResp。
* 可能收到的处理结果有SendMessageToWXResp、SendAuthResp等。
* @param resp具体的回应内容,是自动释放的
*/
- (void)onResp:(BaseResp*)resp;
/* ! @brief 用于在iOS16以及以上系统上,控制OpenSDK是否读取剪切板中微信传递的数据以及读取的时机
* 在iOS16以及以上系统,在SDK需要读取剪切板中微信写入的数据时,会回调该方法。没有实现默认会直接读取微信通过剪切板传递过来的数据
* 注意:
* 1. 只在iOS16以及以上的系统版本上回调;
* 2. 不实现时,OpenSDK会直接调用读取剪切板接口,读取微信传递过来的数据;
* 3. 若实现该方法:开发者需要通过调用completion(), 支持异步,通知SDK允许读取剪切板中微信传递的数据,
* 不调用completion()则代表不授权OpenSDK读取剪切板,会导致收不到onReq:, onResp:回调,无法后续业务流程。请谨慎使用
* 4. 不要长时间持有completion不释放,可能会导致内存泄漏。
*/
- (void)onNeedGrantReadPasteBoardPermissionWithURL:(nonnull NSURL *)openURL completion:(nonnull WXGrantReadPasteBoardPermissionCompletion)completion;
@end
#pragma mark - WXApiLogDelegate
@protocol WXApiLogDelegate <NSObject>
- (void)onLog:(NSString*)log logLevel:(WXLogLevel)level;
@end
#pragma mark - WXApi
/*! @brief 微信Api接口函数类
*
* 该类封装了微信终端SDK的所有接口
*/
@interface WXApi : NSObject
/*! @brief WXApi的成员函数,向微信终端程序注册第三方应用。
*
* 需要在每次启动第三方应用程序时调用。
* @attention 请保证在主线程中调用此函数
* @param appid 微信开发者ID
* @param universalLink 微信开发者Universal Link
* @return 成功返回YES,失败返回NO。
*/
+ (BOOL)registerApp:(NSString *)appid universalLink:(NSString *)universalLink;
/*! @brief 处理旧版微信通过URL启动App时传递的数据
*
* 需要在 application:openURL:sourceApplication:annotation:或者application:handleOpenURL中调用。
* @param url 微信启动第三方应用时传递过来的URL
* @param delegate WXApiDelegate对象,用来接收微信触发的消息。
* @return 成功返回YES,失败返回NO。
*/
+ (BOOL)handleOpenURL:(NSURL *)url delegate:(nullable id<WXApiDelegate>)delegate;
/*! @brief 处理微信通过Universal Link启动App时传递的数据
*
* 需要在 application:continueUserActivity:restorationHandler:中调用。
* @param userActivity 微信启动第三方应用时系统API传递过来的userActivity
* @param delegate WXApiDelegate对象,用来接收微信触发的消息。
* @return 成功返回YES,失败返回NO。
*/
+ (BOOL)handleOpenUniversalLink:(NSUserActivity *)userActivity delegate:(nullable id<WXApiDelegate>)delegate;
/*! @brief 检查微信是否已被用户安装
*
* @return 微信已安装返回YES,未安装返回NO。
*/
+ (BOOL)isWXAppInstalled;
/*! @brief 判断当前微信的版本是否支持OpenApi
*
* @return 支持返回YES,不支持返回NO。
*/
+ (BOOL)isWXAppSupportApi;
/*! @brief 判断当前微信的版本是否支持分享微信状态功能
*
* @attention 需在工程LSApplicationQueriesSchemes配置中添加weixinStateAPI
* @return 支持返回YES,不支持返回NO。
*/
+ (BOOL)isWXAppSupportStateAPI;
#ifndef BUILD_WITHOUT_PAY
/*! @brief 判断当前微信的版本是否支持二维码拉起微信支付
*
* @attention 需在工程LSApplicationQueriesSchemes配置中添加weixinQRCodePayAPI
* @return 支持返回YES,不支持返回NO。
*/
+ (BOOL)isWXAppSupportQRCodePayAPI;
#endif
/*! @brief 获取微信的itunes安装地址
*
* @return 微信的安装地址字符串。
*/
+ (NSString *)getWXAppInstallUrl;
/*! @brief 获取当前微信SDK的版本号
*
* @return 返回当前微信SDK的版本号
*/
+ (NSString *)getApiVersion;
/*! @brief 打开微信
*
* @return 成功返回YES,失败返回NO。
*/
+ (BOOL)openWXApp;
/*! @brief 发送请求到微信,等待微信返回onResp
*
* 函数调用后,会切换到微信的界面。第三方应用程序等待微信返回onResp。微信在异步处理完成后一定会调用onResp。支持以下类型
* SendAuthReq、SendMessageToWXReq、PayReq等。
* @param req 具体的发送请求。
* @param completion 调用结果回调block
*/
+ (void)sendReq:(BaseReq *)req completion:(void (^ __nullable)(BOOL success))completion;
/*! @brief 收到微信onReq的请求,发送对应的应答给微信,并切换到微信界面
*
* 函数调用后,会切换到微信的界面。第三方应用程序收到微信onReq的请求,异步处理该请求,完成后必须调用该函数。可能发送的相应有
* GetMessageFromWXResp、ShowMessageFromWXResp等。
* @param resp 具体的应答内容
* @param completion 调用结果回调block
*/
+ (void)sendResp:(BaseResp*)resp completion:(void (^ __nullable)(BOOL success))completion;
/*! @brief 发送Auth请求到微信,支持用户没安装微信,等待微信返回onResp
*
* 函数调用后,会切换到微信的界面。第三方应用程序等待微信返回onResp。微信在异步处理完成后一定会调用onResp。支持SendAuthReq类型。
* @param req 具体的发送请求。
* @param viewController 当前界面对象。
* @param delegate WXApiDelegate对象,用来接收微信触发的消息。
* @param completion 调用结果回调block
*/
+ (void)sendAuthReq:(SendAuthReq *)req viewController:(UIViewController*)viewController delegate:(nullable id<WXApiDelegate>)delegate completion:(void (^ __nullable)(BOOL success))completion;
/*! @brief 测试函数,用于排查当前App通过Universal Link方式分享到微信的流程
注意1: 调用自检函数之前必须要先调用registerApp:universalLink接口, 并确认调用成功
注意2: 自检过程中会有Log产生,可以先调用startLogByLevel函数,根据Log排查问题
注意3: 会多次回调block
注意4: 仅用于新接入SDK时调试使用,请勿在正式环境的调用
*
* 当completion回调的step为WXULCheckStepFinal时,表示检测通过,Universal Link接入成功
* @param completion 回调Block
*/
+ (void)checkUniversalLinkReady:(nonnull WXCheckULCompletion)completion;
/*! @brief WXApi的成员函数,接受微信的log信息。byBlock
注意1:SDK会强引用这个block,注意不要导致内存泄漏,注意不要导致内存泄漏
注意2:调用过一次startLog by block之后,如果再调用一次任意方式的startLoad,会释放上一次logBlock,不再回调上一个logBlock
*
* @param level 打印log的级别
* @param logBlock 打印log的回调block
*/
+ (void)startLogByLevel:(WXLogLevel)level logBlock:(WXLogBolock)logBlock;
/*! @brief WXApi的成员函数,接受微信的log信息。byDelegate
注意1:sdk会弱引用这个delegate,这里可加任意对象为代理,不需要与WXApiDelegate同一个对象
注意2:调用过一次startLog by delegate之后,再调用一次任意方式的startLoad,不会再回调上一个logDelegate对象
* @param level 打印log的级别
* @param logDelegate 打印log的回调代理,
*/
+ (void)startLogByLevel:(WXLogLevel)level logDelegate:(id<WXApiLogDelegate>)logDelegate;
/*! @brief 停止打印log,会清理block或者delegate为空,释放block
* @param
*/
+ (void)stopLog;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,68 @@
//
// WechatAuthSDK.h
// WechatAuthSDK
//
// Created by 李凯 on 13-11-29.
// Copyright (c) 2013年 Tencent. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
enum AuthErrCode {
WechatAuth_Err_Ok = 0, //Auth成功
WechatAuth_Err_NormalErr = -1, //普通错误
WechatAuth_Err_NetworkErr = -2, //网络错误
WechatAuth_Err_GetQrcodeFailed = -3, //获取二维码失败
WechatAuth_Err_Cancel = -4, //用户取消授权
WechatAuth_Err_Timeout = -5, //超时
};
@protocol WechatAuthAPIDelegate<NSObject>
@optional
- (void)onAuthGotQrcode:(UIImage *)image; //得到二维码
- (void)onQrcodeScanned; //二维码被扫描
- (void)onAuthFinish:(int)errCode AuthCode:(nullable NSString *)authCode; //成功登录
@end
@interface WechatAuthSDK : NSObject{
NSString *_sdkVersion;
__weak id<WechatAuthAPIDelegate> _delegate;
}
@property(nonatomic, weak, nullable) id<WechatAuthAPIDelegate> delegate;
@property(nonatomic, readonly) NSString *sdkVersion; //authSDK版本号
/*! @brief 发送登录请求,等待WechatAuthAPIDelegate回调
*
* @param appId 微信开发者ID
* @param nonceStr 一个随机的尽量不重复的字符串,用来使得每次的signature不同
* @param timeStamp 时间戳
* @param scope 应用授权作用域,拥有多个作用域用逗号(,)分隔
* @param signature 签名
* @param schemeData 会在扫码后拼在scheme后
* @return 成功返回YES,失败返回NO
注:该实现只保证同时只有一个Auth在运行,Auth未完成或未Stop再次调用Auth接口时会返回NO。
*/
- (BOOL)Auth:(NSString *)appId
nonceStr:(NSString *)nonceStr
timeStamp:(NSString *)timeStamp
scope:(NSString *)scope
signature:(NSString *)signature
schemeData:(nullable NSString *)schemeData;
/*! @brief 暂停登录请求
*
* @return 成功返回YES,失败返回NO。
*/
- (BOOL)StopAuth;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,9 @@
// WechatOpenSDK.h
//
// Created by Wechat.
// Copyright (c) 2012年 Tencent. All rights reserved.
//
#import <WechatOpenSDK/WXApi.h>
#import <WechatOpenSDK/WXApiObject.h>
#import <WechatOpenSDK/WechatAuthSDK.h>
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>com.tencent.WechatOpenSDK</string>
<key>CFBundleVersion</key>
<string>1.0.0</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>12.0</string>
<key>CFBundleExecutable</key>
<string>WechatOpenSDK</string>
</dict>
</plist>
@@ -0,0 +1,5 @@
framework module WechatOpenSDK {
umbrella header "WechatOpenSDK.h"
export *
link "WechatOpenSDK"
}
@@ -0,0 +1,231 @@
//
// WXApi.h
// 所有Api接口
//
// Created by Wechat on 12-2-28.
// Copyright (c) 2012年 Tencent. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "WXApiObject.h"
NS_ASSUME_NONNULL_BEGIN
typedef BOOL(^WXGrantReadPasteBoardPermissionCompletion)(void);
#pragma mark - WXApiDelegate
/*! @brief 接收并处理来自微信终端程序的事件消息
*
* 接收并处理来自微信终端程序的事件消息,期间微信界面会切换到第三方应用程序。
* WXApiDelegate 会在handleOpenURL:delegate:中使用并触发。
*/
@protocol WXApiDelegate <NSObject>
@optional
/*! @brief 收到一个来自微信的请求,第三方应用程序处理完后调用sendResp向微信发送结果
*
* 收到一个来自微信的请求,异步处理完成后必须调用sendResp发送处理结果给微信。
* 可能收到的请求有GetMessageFromWXReq、ShowMessageFromWXReq等。
* @param req 具体请求内容,是自动释放的
*/
- (void)onReq:(BaseReq*)req;
/*! @brief 发送一个sendReq后,收到微信的回应
*
* 收到一个来自微信的处理结果。调用一次sendReq后会收到onResp。
* 可能收到的处理结果有SendMessageToWXResp、SendAuthResp等。
* @param resp具体的回应内容,是自动释放的
*/
- (void)onResp:(BaseResp*)resp;
/* ! @brief 用于在iOS16以及以上系统上,控制OpenSDK是否读取剪切板中微信传递的数据以及读取的时机
* 在iOS16以及以上系统,在SDK需要读取剪切板中微信写入的数据时,会回调该方法。没有实现默认会直接读取微信通过剪切板传递过来的数据
* 注意:
* 1. 只在iOS16以及以上的系统版本上回调;
* 2. 不实现时,OpenSDK会直接调用读取剪切板接口,读取微信传递过来的数据;
* 3. 若实现该方法:开发者需要通过调用completion(), 支持异步,通知SDK允许读取剪切板中微信传递的数据,
* 不调用completion()则代表不授权OpenSDK读取剪切板,会导致收不到onReq:, onResp:回调,无法后续业务流程。请谨慎使用
* 4. 不要长时间持有completion不释放,可能会导致内存泄漏。
*/
- (void)onNeedGrantReadPasteBoardPermissionWithURL:(nonnull NSURL *)openURL completion:(nonnull WXGrantReadPasteBoardPermissionCompletion)completion;
@end
#pragma mark - WXApiLogDelegate
@protocol WXApiLogDelegate <NSObject>
- (void)onLog:(NSString*)log logLevel:(WXLogLevel)level;
@end
#pragma mark - WXApi
/*! @brief 微信Api接口函数类
*
* 该类封装了微信终端SDK的所有接口
*/
@interface WXApi : NSObject
/*! @brief WXApi的成员函数,向微信终端程序注册第三方应用。
*
* 需要在每次启动第三方应用程序时调用。
* @attention 请保证在主线程中调用此函数
* @param appid 微信开发者ID
* @param universalLink 微信开发者Universal Link
* @return 成功返回YES,失败返回NO。
*/
+ (BOOL)registerApp:(NSString *)appid universalLink:(NSString *)universalLink;
/*! @brief 处理旧版微信通过URL启动App时传递的数据
*
* 需要在 application:openURL:sourceApplication:annotation:或者application:handleOpenURL中调用。
* @param url 微信启动第三方应用时传递过来的URL
* @param delegate WXApiDelegate对象,用来接收微信触发的消息。
* @return 成功返回YES,失败返回NO。
*/
+ (BOOL)handleOpenURL:(NSURL *)url delegate:(nullable id<WXApiDelegate>)delegate;
/*! @brief 处理微信通过Universal Link启动App时传递的数据
*
* 需要在 application:continueUserActivity:restorationHandler:中调用。
* @param userActivity 微信启动第三方应用时系统API传递过来的userActivity
* @param delegate WXApiDelegate对象,用来接收微信触发的消息。
* @return 成功返回YES,失败返回NO。
*/
+ (BOOL)handleOpenUniversalLink:(NSUserActivity *)userActivity delegate:(nullable id<WXApiDelegate>)delegate;
/*! @brief 检查微信是否已被用户安装
*
* @return 微信已安装返回YES,未安装返回NO。
*/
+ (BOOL)isWXAppInstalled;
/*! @brief 判断当前微信的版本是否支持OpenApi
*
* @return 支持返回YES,不支持返回NO。
*/
+ (BOOL)isWXAppSupportApi;
/*! @brief 判断当前微信的版本是否支持分享微信状态功能
*
* @attention 需在工程LSApplicationQueriesSchemes配置中添加weixinStateAPI
* @return 支持返回YES,不支持返回NO。
*/
+ (BOOL)isWXAppSupportStateAPI;
#ifndef BUILD_WITHOUT_PAY
/*! @brief 判断当前微信的版本是否支持二维码拉起微信支付
*
* @attention 需在工程LSApplicationQueriesSchemes配置中添加weixinQRCodePayAPI
* @return 支持返回YES,不支持返回NO。
*/
+ (BOOL)isWXAppSupportQRCodePayAPI;
#endif
/*! @brief 获取微信的itunes安装地址
*
* @return 微信的安装地址字符串。
*/
+ (NSString *)getWXAppInstallUrl;
/*! @brief 获取当前微信SDK的版本号
*
* @return 返回当前微信SDK的版本号
*/
+ (NSString *)getApiVersion;
/*! @brief 打开微信
*
* @return 成功返回YES,失败返回NO。
*/
+ (BOOL)openWXApp;
/*! @brief 发送请求到微信,等待微信返回onResp
*
* 函数调用后,会切换到微信的界面。第三方应用程序等待微信返回onResp。微信在异步处理完成后一定会调用onResp。支持以下类型
* SendAuthReq、SendMessageToWXReq、PayReq等。
* @param req 具体的发送请求。
* @param completion 调用结果回调block
*/
+ (void)sendReq:(BaseReq *)req completion:(void (^ __nullable)(BOOL success))completion;
/*! @brief 收到微信onReq的请求,发送对应的应答给微信,并切换到微信界面
*
* 函数调用后,会切换到微信的界面。第三方应用程序收到微信onReq的请求,异步处理该请求,完成后必须调用该函数。可能发送的相应有
* GetMessageFromWXResp、ShowMessageFromWXResp等。
* @param resp 具体的应答内容
* @param completion 调用结果回调block
*/
+ (void)sendResp:(BaseResp*)resp completion:(void (^ __nullable)(BOOL success))completion;
/*! @brief 发送Auth请求到微信,支持用户没安装微信,等待微信返回onResp
*
* 函数调用后,会切换到微信的界面。第三方应用程序等待微信返回onResp。微信在异步处理完成后一定会调用onResp。支持SendAuthReq类型。
* @param req 具体的发送请求。
* @param viewController 当前界面对象。
* @param delegate WXApiDelegate对象,用来接收微信触发的消息。
* @param completion 调用结果回调block
*/
+ (void)sendAuthReq:(SendAuthReq *)req viewController:(UIViewController*)viewController delegate:(nullable id<WXApiDelegate>)delegate completion:(void (^ __nullable)(BOOL success))completion;
/*! @brief 测试函数,用于排查当前App通过Universal Link方式分享到微信的流程
注意1: 调用自检函数之前必须要先调用registerApp:universalLink接口, 并确认调用成功
注意2: 自检过程中会有Log产生,可以先调用startLogByLevel函数,根据Log排查问题
注意3: 会多次回调block
注意4: 仅用于新接入SDK时调试使用,请勿在正式环境的调用
*
* 当completion回调的step为WXULCheckStepFinal时,表示检测通过,Universal Link接入成功
* @param completion 回调Block
*/
+ (void)checkUniversalLinkReady:(nonnull WXCheckULCompletion)completion;
/*! @brief WXApi的成员函数,接受微信的log信息。byBlock
注意1:SDK会强引用这个block,注意不要导致内存泄漏,注意不要导致内存泄漏
注意2:调用过一次startLog by block之后,如果再调用一次任意方式的startLoad,会释放上一次logBlock,不再回调上一个logBlock
*
* @param level 打印log的级别
* @param logBlock 打印log的回调block
*/
+ (void)startLogByLevel:(WXLogLevel)level logBlock:(WXLogBolock)logBlock;
/*! @brief WXApi的成员函数,接受微信的log信息。byDelegate
注意1:sdk会弱引用这个delegate,这里可加任意对象为代理,不需要与WXApiDelegate同一个对象
注意2:调用过一次startLog by delegate之后,再调用一次任意方式的startLoad,不会再回调上一个logDelegate对象
* @param level 打印log的级别
* @param logDelegate 打印log的回调代理,
*/
+ (void)startLogByLevel:(WXLogLevel)level logDelegate:(id<WXApiLogDelegate>)logDelegate;
/*! @brief 停止打印log,会清理block或者delegate为空,释放block
* @param
*/
+ (void)stopLog;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,68 @@
//
// WechatAuthSDK.h
// WechatAuthSDK
//
// Created by 李凯 on 13-11-29.
// Copyright (c) 2013年 Tencent. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
enum AuthErrCode {
WechatAuth_Err_Ok = 0, //Auth成功
WechatAuth_Err_NormalErr = -1, //普通错误
WechatAuth_Err_NetworkErr = -2, //网络错误
WechatAuth_Err_GetQrcodeFailed = -3, //获取二维码失败
WechatAuth_Err_Cancel = -4, //用户取消授权
WechatAuth_Err_Timeout = -5, //超时
};
@protocol WechatAuthAPIDelegate<NSObject>
@optional
- (void)onAuthGotQrcode:(UIImage *)image; //得到二维码
- (void)onQrcodeScanned; //二维码被扫描
- (void)onAuthFinish:(int)errCode AuthCode:(nullable NSString *)authCode; //成功登录
@end
@interface WechatAuthSDK : NSObject{
NSString *_sdkVersion;
__weak id<WechatAuthAPIDelegate> _delegate;
}
@property(nonatomic, weak, nullable) id<WechatAuthAPIDelegate> delegate;
@property(nonatomic, readonly) NSString *sdkVersion; //authSDK版本号
/*! @brief 发送登录请求,等待WechatAuthAPIDelegate回调
*
* @param appId 微信开发者ID
* @param nonceStr 一个随机的尽量不重复的字符串,用来使得每次的signature不同
* @param timeStamp 时间戳
* @param scope 应用授权作用域,拥有多个作用域用逗号(,)分隔
* @param signature 签名
* @param schemeData 会在扫码后拼在scheme后
* @return 成功返回YES,失败返回NO
注:该实现只保证同时只有一个Auth在运行,Auth未完成或未Stop再次调用Auth接口时会返回NO。
*/
- (BOOL)Auth:(NSString *)appId
nonceStr:(NSString *)nonceStr
timeStamp:(NSString *)timeStamp
scope:(NSString *)scope
signature:(NSString *)signature
schemeData:(nullable NSString *)schemeData;
/*! @brief 暂停登录请求
*
* @return 成功返回YES,失败返回NO。
*/
- (BOOL)StopAuth;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,9 @@
// WechatOpenSDK.h
//
// Created by Wechat.
// Copyright (c) 2012年 Tencent. All rights reserved.
//
#import <WechatOpenSDK/WXApi.h>
#import <WechatOpenSDK/WXApiObject.h>
#import <WechatOpenSDK/WechatAuthSDK.h>
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>com.tencent.WechatOpenSDK</string>
<key>CFBundleVersion</key>
<string>1.0.0</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>12.0</string>
<key>CFBundleExecutable</key>
<string>WechatOpenSDK</string>
</dict>
</plist>
@@ -0,0 +1,5 @@
framework module WechatOpenSDK {
umbrella header "WechatOpenSDK.h"
export *
link "WechatOpenSDK"
}
@@ -0,0 +1,81 @@
//
// XJWeChatManager.h
// XinjiangProject
//
// 微信分享管理类(手动集成 WechatOpenSDK-NoPay
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
/// 微信分享结果回调
typedef void(^XJWeChatShareCompletion)(BOOL success, NSString *_Nullable errorMsg);
@interface XJWeChatManager : NSObject
+ (instancetype)sharedManager;
#pragma mark - 注册
/// 注册微信 SDK(需在 AppDelegate didFinishLaunching 中调用)
/// @param appID 微信开放平台 AppID
/// @param universalLink 通用链接
- (BOOL)registerWithAppID:(NSString *)appID universalLink:(NSString *)universalLink;
/// 处理微信 URL 回调(AppDelegate handleOpenURL 中调用)
- (BOOL)handleOpenURL:(NSURL *)url;
/// 处理微信 Universal Link 回调(AppDelegate continueUserActivity 中调用)
- (BOOL)handleOpenUniversalLink:(NSUserActivity *)userActivity;
#pragma mark - 分享
/// 分享文字
- (void)shareText:(NSString *)text
toScene:(int)scene
completion:(XJWeChatShareCompletion _Nullable)completion;
/// 分享图片(NSData
- (void)shareImageData:(NSData *)imageData
toScene:(int)scene
completion:(XJWeChatShareCompletion _Nullable)completion;
/// 分享网页
/// @param title 标题
/// @param desc 描述
/// @param webpageUrl 网页链接
/// @param thumbImage 缩略图(不超过 32KB
/// @param scene 分享目标:WXSceneSession=好友, WXSceneTimeline=朋友圈
- (void)shareWebpageWithTitle:(NSString *)title
desc:(NSString *)desc
webpageUrl:(NSString *)webpageUrl
thumbImage:(UIImage *_Nullable)thumbImage
toScene:(int)scene
completion:(XJWeChatShareCompletion _Nullable)completion;
/// 分享小程序卡片
/// @param title 标题
/// @param desc 描述
/// @param webpageUrl 兼容低版本网页链接
/// @param userName 小程序原始IDgh_ 开头)
/// @param path 小程序页面路径
/// @param miniProgramType 小程序类型:0=正式版, 1=开发版, 2=体验版
- (void)shareMiniProgramWithTitle:(NSString *)title
desc:(NSString *)desc
webpageUrl:(NSString *)webpageUrl
userName:(NSString *)userName
path:(NSString *)path
miniProgramType:(NSUInteger)miniProgramType
thumbImage:(UIImage *_Nullable)thumbImage
completion:(XJWeChatShareCompletion _Nullable)completion;
#pragma mark - 工具
/// 是否安装微信
- (BOOL)isWeChatInstalled;
/// 微信是否支持 OpenAPI
- (BOOL)isWeChatSupportApi;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,160 @@
//
// XJWeChatManager.m
// XinjiangProject
//
// 微信分享管理类
//
#import "XJWeChatManager.h"
#import <WechatOpenSDK/WXApi.h>
@interface XJWeChatManager () <WXApiDelegate>
@property (nonatomic, copy) XJWeChatShareCompletion shareCompletion;
@end
@implementation XJWeChatManager
#pragma mark - ————— 单例 —————
+ (instancetype)sharedManager {
static XJWeChatManager *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[XJWeChatManager alloc] init];
});
return instance;
}
#pragma mark - ————— 注册 —————
- (BOOL)registerWithAppID:(NSString *)appID universalLink:(NSString *)universalLink {
return [WXApi registerApp:appID universalLink:universalLink];
}
- (BOOL)handleOpenURL:(NSURL *)url {
return [WXApi handleOpenURL:url delegate:self];
}
- (BOOL)handleOpenUniversalLink:(NSUserActivity *)userActivity {
return [WXApi handleOpenUniversalLink:userActivity delegate:self];
}
#pragma mark - ————— 分享 —————
- (void)shareText:(NSString *)text
toScene:(int)scene
completion:(XJWeChatShareCompletion)completion {
self.shareCompletion = completion;
SendMessageToWXReq *req = [[SendMessageToWXReq alloc] init];
req.bText = YES;
req.text = text;
req.scene = scene;
[WXApi sendReq:req completion:nil];
}
- (void)shareImageData:(NSData *)imageData
toScene:(int)scene
completion:(XJWeChatShareCompletion)completion {
self.shareCompletion = completion;
WXMediaMessage *message = [WXMediaMessage message];
message.thumbData = nil;
WXImageObject *imageObject = [WXImageObject object];
imageObject.imageData = imageData;
message.mediaObject = imageObject;
SendMessageToWXReq *req = [[SendMessageToWXReq alloc] init];
req.bText = NO;
req.message = message;
req.scene = scene;
[WXApi sendReq:req completion:nil];
}
- (void)shareWebpageWithTitle:(NSString *)title
desc:(NSString *)desc
webpageUrl:(NSString *)webpageUrl
thumbImage:(UIImage *)thumbImage
toScene:(int)scene
completion:(XJWeChatShareCompletion)completion {
self.shareCompletion = completion;
WXMediaMessage *message = [WXMediaMessage message];
message.title = title;
message.description = desc;
if (thumbImage) {
message.thumbData = UIImageJPEGRepresentation(thumbImage, 0.5);
}
WXWebpageObject *webpageObject = [WXWebpageObject object];
webpageObject.webpageUrl = webpageUrl;
message.mediaObject = webpageObject;
SendMessageToWXReq *req = [[SendMessageToWXReq alloc] init];
req.bText = NO;
req.message = message;
req.scene = scene;
[WXApi sendReq:req completion:nil];
}
- (void)shareMiniProgramWithTitle:(NSString *)title
desc:(NSString *)desc
webpageUrl:(NSString *)webpageUrl
userName:(NSString *)userName
path:(NSString *)path
miniProgramType:(NSUInteger)miniProgramType
thumbImage:(UIImage *)thumbImage
completion:(XJWeChatShareCompletion)completion {
self.shareCompletion = completion;
WXMediaMessage *message = [WXMediaMessage message];
message.title = title;
message.description = desc;
if (thumbImage) {
message.thumbData = UIImageJPEGRepresentation(thumbImage, 0.5);
}
WXMiniProgramObject *miniProgramObject = [WXMiniProgramObject object];
miniProgramObject.webpageUrl = webpageUrl;
miniProgramObject.userName = userName;
miniProgramObject.path = path;
miniProgramObject.miniProgramType = miniProgramType;
message.mediaObject = miniProgramObject;
SendMessageToWXReq *req = [[SendMessageToWXReq alloc] init];
req.bText = NO;
req.message = message;
req.scene = WXSceneSession;
[WXApi sendReq:req completion:nil];
}
#pragma mark - ————— 工具 —————
- (BOOL)isWeChatInstalled {
return [WXApi isWXAppInstalled];
}
- (BOOL)isWeChatSupportApi {
return [WXApi isWXAppSupportApi];
}
#pragma mark - ————— WXApiDelegate —————
- (void)onResp:(BaseResp *)resp {
if ([resp isKindOfClass:[SendMessageToWXResp class]]) {
if (self.shareCompletion) {
if (resp.errCode == WXSuccess) {
self.shareCompletion(YES, nil);
} else if (resp.errCode == WXErrCodeUserCancel) {
self.shareCompletion(NO, @"用户取消分享");
} else {
self.shareCompletion(NO, resp.errStr ?: @"分享失败");
}
self.shareCompletion = nil;
}
}
}
@end
@@ -0,0 +1,47 @@
//
// XJHealthKnowledgeManager.h
// XinjiangProject
//
// Created by Apple on 2026/6/29.
//
#import <Foundation/Foundation.h>
#import "XJHealthCategoryModel.h"
#import "XJHealthArticleModel.h"
NS_ASSUME_NONNULL_BEGIN
/// 健康知识网络管理器
@interface XJHealthKnowledgeManager : NSObject
+ (instancetype)sharedManager;
/// 当前 token(获取后缓存)
@property (nonatomic, copy, readonly, nullable) NSString * cachedToken;
/// 清除缓存的 token(退出登录时调用)
- (void)clearToken;
/// 获取 token
- (void)getTokenWithUserId:(NSString *)userId
workNo:(NSString *)workNo
success:(void (^)(NSString * token))success
failure:(void (^)(NSString * errorMsg))failure;
/// 获取栏目列表
- (void)getCategoryListWithToken:(NSString *)token
success:(void (^)(NSArray<XJHealthCategoryModel *> * categories))success
failure:(void (^)(NSString * errorMsg))failure;
/// 分页查询文章(showAppHomepage 固定 Y
- (void)getArticleListWithToken:(NSString *)token
categoryId:(NSInteger)categoryId
articleType:(nullable NSString *)articleType
pageNum:(NSInteger)pageNum
pageSize:(NSInteger)pageSize
success:(void (^)(NSArray<XJHealthArticleModel *> * articles, NSInteger total))success
failure:(void (^)(NSString * errorMsg))failure;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,222 @@
//
// XJHealthKnowledgeManager.m
// XinjiangProject
//
// Created by Apple on 2026/6/29.
//
#import "XJHealthKnowledgeManager.h"
#import <CommonCrypto/CommonHMAC.h>
#pragma mark - ————— Manager —————
@interface XJHealthKnowledgeManager ()
@property (nonatomic, copy) NSString * cachedToken;
@end
@implementation XJHealthKnowledgeManager
+ (instancetype)sharedManager {
static XJHealthKnowledgeManager * instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[XJHealthKnowledgeManager alloc] init];
});
return instance;
}
#pragma mark - ————— HMAC-SHA256 —————
- (void)clearToken {
self.cachedToken = nil;
DLog(@"[健康知识] Token 已清除");
}
+ (NSString *)hmacSHA256:(NSString *)data key:(NSString *)key {
const char * cKey = [key cStringUsingEncoding:NSUTF8StringEncoding];
const char * cData = [data cStringUsingEncoding:NSUTF8StringEncoding];
unsigned char result[CC_SHA256_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), result);
NSMutableString * hash = [[NSMutableString alloc] initWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
for (int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
[hash appendFormat:@"%02x", result[i]];
}
return hash;
}
#pragma mark - ————— 获取 Token —————
- (void)getTokenWithUserId:(NSString *)userId
workNo:(NSString *)workNo
success:(void (^)(NSString *))success
failure:(void (^)(NSString *))failure {
NSString * urlString = [NSString stringWithFormat:@"%@%@", kHealthKnowledgeBaseURL, kHealthKnowledgeTokenPath];
// 构建请求体
NSDictionary * bodyDict = @{ @"userId": userId ?: @"",
@"workNo": workNo ?: @"" };
NSData * bodyData = [NSJSONSerialization dataWithJSONObject:bodyDict options:0 error:nil];
NSString * bodyString = [[NSString alloc] initWithData:bodyData encoding:NSUTF8StringEncoding];
// 签名
NSString * timestamp = [NSString stringWithFormat:@"%.0f", [[NSDate date] timeIntervalSince1970]];
NSString * stringToSign = [NSString stringWithFormat:@"%@%@", timestamp, bodyString];
NSString * sign = [[self class] hmacSHA256:stringToSign key:kHealthKnowledgeSecretKey];
NSMutableURLRequest * request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:urlString]];
request.HTTPMethod = @"POST";
[request setValue:@"application/json; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
[request setValue:timestamp forHTTPHeaderField:@"X-Timestamp"];
[request setValue:sign forHTTPHeaderField:@"X-Sign"];
request.HTTPBody = bodyData;
DLog(@"[健康知识] 请求 Token URL: %@", urlString);
DLog(@"[健康知识] 签名串: %@", stringToSign);
DLog(@"[健康知识] X-Sign: %@", sign);
[self sendRequest:request completion:^(NSDictionary * json) {
DLog(@"[健康知识] Token 响应: %@", json);
if ([json[@"code"] integerValue] == 200) {
NSString * token = json[@"data"][@"token"];
if (!ValidStr(token)) {
self.cachedToken = token;
DLog(@"[健康知识] Token 获取成功: %@", token);
if (success) success(token);
} else {
DLog(@"[健康知识] Token 为空");
if (failure) failure(@"token 为空");
}
} else {
DLog(@"[健康知识] Token 失败: %@", json[@"msg"]);
if (failure) failure(json[@"msg"] ?: @"获取 token 失败");
}
} failure:^(NSString * errorMsg) {
DLog(@"[健康知识] Token 请求异常: %@", errorMsg);
if (failure) failure(errorMsg);
}];
}
#pragma mark - ————— 栏目列表 —————
- (void)getCategoryListWithToken:(NSString *)token
success:(void (^)(NSArray<XJHealthCategoryModel *> *))success
failure:(void (^)(NSString *))failure {
NSString * urlString = [NSString stringWithFormat:@"%@%@", kHealthKnowledgeBaseURL, kHealthKnowledgeCategoryPath];
NSMutableURLRequest * request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:urlString]];
request.HTTPMethod = @"GET";
[request setValue:token forHTTPHeaderField:@"token"];
[self sendRequest:request completion:^(NSDictionary * json) {
if ([json[@"code"] integerValue] == 200) {
NSArray * dataArray = json[@"data"];
NSMutableArray * categories = [[NSMutableArray alloc] init];
if ([dataArray isKindOfClass:[NSArray class]]) {
for (NSDictionary * dict in dataArray) {
XJHealthCategoryModel * m = [XJHealthCategoryModel modelWithDictionary:dict];
[categories addObject:m];
}
}
if (success) success(categories);
} else {
if (failure) failure(json[@"msg"] ?: @"获取栏目列表失败");
}
} failure:^(NSString * errorMsg) {
if (failure) failure(errorMsg);
}];
}
#pragma mark - ————— 分页查询文章 —————
- (void)getArticleListWithToken:(NSString *)token
categoryId:(NSInteger)categoryId
articleType:(NSString *)articleType
pageNum:(NSInteger)pageNum
pageSize:(NSInteger)pageSize
success:(void (^)(NSArray<XJHealthArticleModel *> *, NSInteger))success
failure:(void (^)(NSString *))failure {
NSMutableString * urlString = [NSMutableString stringWithFormat:@"%@%@", kHealthKnowledgeBaseURL, kHealthKnowledgeArticleListPath];
[urlString appendFormat:@"?categoryId=%ld&pageNum=%ld&pageSize=%ld&showAppHomepage=Y",
(long)categoryId, (long)pageNum, (long)pageSize];
if (!ValidStr(articleType)) {
[urlString appendFormat:@"&articleType=%@", articleType];
}
NSMutableURLRequest * request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:urlString]];
request.HTTPMethod = @"GET";
[request setValue:token forHTTPHeaderField:@"token"];
[self sendRequest:request completion:^(NSDictionary * json) {
if ([json[@"code"] integerValue] == 200) {
NSArray * rows = json[@"rows"];
NSInteger total = [json[@"total"] integerValue];
NSMutableArray * articles = [[NSMutableArray alloc] init];
if ([rows isKindOfClass:[NSArray class]]) {
for (NSDictionary * dict in rows) {
XJHealthArticleModel * m = [XJHealthArticleModel modelWithDictionary:dict];
[articles addObject:m];
}
}
if (success) success(articles, total);
} else {
if (failure) failure(json[@"msg"] ?: @"获取文章列表失败");
}
} failure:^(NSString * errorMsg) {
if (failure) failure(errorMsg);
}];
}
#pragma mark - ————— 通用请求 —————
- (void)sendRequest:(NSURLRequest *)request
completion:(void (^)(NSDictionary * json))completion
failure:(void (^)(NSString * errorMsg))failure {
DLog(@"[健康知识] >>> 请求: %@ %@", request.HTTPMethod, request.URL.absoluteString);
NSURLSession * session = [NSURLSession sharedSession];
NSURLSessionDataTask * task = [session dataTaskWithRequest:request
completionHandler:^(NSData * _Nullable data,
NSURLResponse * _Nullable response,
NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
DLog(@"[健康知识] <<< 网络错误: %@", error.localizedDescription);
if (failure) failure(error.localizedDescription);
return;
}
NSHTTPURLResponse * httpResp = (NSHTTPURLResponse *)response;
NSInteger statusCode = httpResp.statusCode;
DLog(@"[健康知识] <<< HTTP %ld", (long)statusCode);
if (statusCode != 200) {
NSString * msg = [NSString stringWithFormat:@"HTTP %ld", (long)statusCode];
DLog(@"[健康知识] <<< 请求失败: %@", msg);
if (failure) failure(msg);
return;
}
NSError * jsonError = nil;
NSDictionary * json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
if (jsonError || ![json isKindOfClass:[NSDictionary class]]) {
DLog(@"[健康知识] <<< JSON 解析失败");
if (failure) failure(@"数据解析失败");
return;
}
DLog(@"[健康知识] <<< 响应: %@", json);
if (completion) completion(json);
});
}];
[task resume];
}
@end
@@ -13,7 +13,6 @@
//初始化服务
-(void)initService;
- (void)chageUrlService;
//初始化 window
-(void)initWindow;
@@ -6,8 +6,9 @@
//
#import "AppDelegate+AppService.h"
#import "HQBaseTabBarController.h"
#import "HQLoginViewController.h"
#import "XJBaseTabBarController.h"
//#import "XJLoginViewController.h"
#import "XJLoginTopChangeViewController.h"
#import <IQKeyboardManager/IQKeyboardManager.h>
#import <AMapFoundationKit/AMapFoundationKit.h>
@@ -33,31 +34,41 @@
object:nil];
//切换SOStabbar
//切换咨询tabbar
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(tabBarSoSChange:)
name:KNotificSelectSoSTabbar
selector:@selector(tabBarQuestionChange:)
name:KNotificSelectQuestionTabbar
object:nil];
//切换应急tabbar
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(tabBarSOSChange:)
name:KNotificSelectSOSCenterTabbar
object:nil];
//切换体检tabbar
//切换监测tabbar
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(tabBarPhyChange:)
name:KNotificSelectPhysicalTabbar
selector:@selector(tabBarMonitoringChange:)
name:KNotificSelectWatchTabbar
object:nil];
//切换档案tabbar
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(tabBarFileChange:)
name:KNotificSelectFileTabbar
object:nil];
if ([HQCommonUtils isLogin]) {
//腾讯im
JKCQAPI * proctocolApi = [[JKCQAPI alloc] init:self tag:@"IMAPI" NeedToken:nil];
[proctocolApi GetIMLoginAccount:nil];
#if DEBUG
[self loginImAccount];
#else
[self loginImAccount];
#endif
}
}
- (void)loginImAccount {
XJPNetAPI * proctocolApi = [[XJPNetAPI alloc] init:self tag:@"IMAPI" NeedToken:nil];
[proctocolApi GetIMLoginAccount:nil];
}
#pragma mark ————— 初始化window —————
-(void)initWindow{
@@ -65,13 +76,13 @@
self.window.backgroundColor = KWhiteColor;
//直接进入显示登录页面
// if ([HQCommonUtils isLogin]) {
self.mainTabBar = [HQBaseTabBarController new];
self.mainTabBar = [XJBaseTabBarController new];
self.mainTabBar.delegate =self;
self.window.rootViewController = self.mainTabBar;
[self.window makeKeyAndVisible];
// }else {
// HQLoginViewController * loginvc = [[HQLoginViewController alloc] init];
// HQBaseNavigationController * nav = [[HQBaseNavigationController alloc] initWithRootViewController:loginvc];
// XJBaseNavigationController * nav = [[XJBaseNavigationController alloc] initWithRootViewController:loginvc];
// self.window.rootViewController = nav;
// }
// [self.window makeKeyAndVisible];
@@ -86,102 +97,6 @@
[[TUICallEngine createInstance] addObserver:self];
}
#pragma mark:请求前缀
- (void)chageUrlService {
AFHTTPSessionManager *session=[AFHTTPSessionManager manager];
// AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
session.responseSerializer.acceptableContentTypes=[NSSet setWithObjects:@"application/json",@"text/json",@"text/javascript",@"text/html",@"text/plain", nil];
//超时时间
session.requestSerializer.timeoutInterval= 30.f;
session.responseSerializer = [AFHTTPResponseSerializer serializer];
session.requestSerializer = [AFJSONRequestSerializer serializer];
session.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
NSMutableDictionary * parmDic = [[NSMutableDictionary alloc] init];
// 获取应用的版本号
NSString * version = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
// 将版本号按照点(.)分割成数组
NSArray * components = [version componentsSeparatedByString:@"."];
// 获取数组中的最后一个元素
NSString * lastComponent = [components lastObject];
// 如果需要将其转换为整数
NSInteger lastNumber = [lastComponent integerValue];
[parmDic setObject:@(lastNumber) forKey:@"version"];
[parmDic setObject:@"com.question.QinghaiProvince" forKey:@"pkg"];
[session GET:@"https://base.icdat.cn/v2/url" parameters:parmDic headers:@{@"X-ClientSign":@"Quarry"} progress:^(NSProgress * _Nonnull downloadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSString * dataString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
DLog(@"response\n%@\n",dataString);
NSData *requestData = [dataString dataUsingEncoding:NSUTF8StringEncoding];
id myResult = [NSJSONSerialization JSONObjectWithData:requestData options:NSJSONReadingMutableContainers error:nil];
//判断是否为字典
if ([myResult isKindOfClass:[NSDictionary class]]) {
NSDictionary *response = (NSDictionary *)myResult;
if ([response.allKeys containsObject:@"result"]) {
NSDictionary * resultDic = [response objectForKey:@"result"];
if ([resultDic.allKeys containsObject:@"api"]) {
[[NSUserDefaults standardUserDefaults] setObject:[resultDic objectForKey:@"api"] forKey:@"HTTPS"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSString * apiString = [resultDic objectForKey:@"api"];
//判断是否正在审
BOOL isExmine;
if ([apiString containsString:@"api.out.icdat.cn"]) { //正在审
isExmine = true;
}else
{
isExmine = false;
}
[[NSUserDefaults standardUserDefaults] setObject:@(isExmine) forKey:@"isExmine"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
if ([resultDic.allKeys containsObject:@"h5"]) {
[[NSUserDefaults standardUserDefaults] setObject:[resultDic objectForKey:@"h5"] forKey:@"IntervenH5"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
if ([resultDic.allKeys containsObject:@"h5Host"]) {
[[NSUserDefaults standardUserDefaults] setObject:[resultDic objectForKey:@"h5Host"] forKey:@"H5DevHost"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
if ([resultDic.allKeys containsObject:@"health"]) {
[[NSUserDefaults standardUserDefaults] setObject:[resultDic objectForKey:@"health"] forKey:@"BASEURL"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
KPostNotification(KNotificAgreeProtoocl, nil);
}
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSString * statusCode = [error.userInfo objectForKey:@"NSLocalizedDescription"];
//请求超时
if (error.code == -1001) {
[EasyTextView showErrorText:@"请求超时"];
}
[[NSUserDefaults standardUserDefaults] setObject:@"https://api.cqygjk.com" forKey:@"HTTPS"];
[[NSUserDefaults standardUserDefaults] setObject:@"https://yyjk.cqygjk.com/" forKey:@"BASEURL"];
[[NSUserDefaults standardUserDefaults] setObject:@"api.cqygjk.com" forKey:@"IntervenH5"];
[[NSUserDefaults standardUserDefaults] setObject:@"https://api.cqygjk.com" forKey:@"H5DevHost"];
[[NSUserDefaults standardUserDefaults] synchronize];
KPostNotification(KNotificAgreeProtoocl, nil);
}];
}
#pragma mark: 键盘回收
- (void)initIQKeyBord {
@@ -230,7 +145,7 @@
paragraphStyle.alignment = NSTextAlignmentLeft;
NSMutableAttributedString *message = [[NSMutableAttributedString alloc] initWithString:@"\n亲,感谢您对健康咨询员工端一直以来的信任!我们依据最新的监管要求更新了健康咨询员工端《隐私权政策》,特向您说明如下\n1.为向您提供交易相关基本功能,我们会收集、使用必要的信息;\n2.基于您的明示授权,我们可能会获取您的位置(为您提供服务)等信息,您有权拒绝或取消授权;\n3.我们会采取业界先进的安全措施保护您的信息安全;\n4.未经您同意,我们不会从第三方处获取、共享或向提供您的信息;" attributes:@{
NSMutableAttributedString *message = [[NSMutableAttributedString alloc] initWithString:@"\n亲,感谢您对健康油我一直以来的信任!我们依据最新的监管要求更新了健康油我《隐私权政策》,特向您说明如下\n1.为向您提供交易相关基本功能,我们会收集、使用必要的信息;\n2.基于您的明示授权,我们可能会获取您的位置(为您提供服务)等信息,您有权拒绝或取消授权;\n3.我们会采取业界先进的安全措施保护您的信息安全;\n4.未经您同意,我们不会从第三方处获取、共享或向提供您的信息;" attributes:@{
NSParagraphStyleAttributeName:paragraphStyle,
}];
@@ -245,7 +160,8 @@
[[NSUserDefaults standardUserDefaults] synchronize];
//更新用户授权高德SDK隐私协议状态. since 8.1.0
[MAMapView updatePrivacyAgree:AMapPrivacyAgreeStatusDidAgree];
[self chageUrlService];
KPostNotification(KNotificAgreeProtoocl, nil);
}];
@@ -254,7 +170,8 @@
[[NSUserDefaults standardUserDefaults] synchronize];
//更新用户授权高德SDK隐私协议状态. since 8.1.0
[MAMapView updatePrivacyAgree:AMapPrivacyAgreeStatusNotAgree];
[self chageUrlService];
KPostNotification(KNotificAgreeProtoocl, nil);
}];
[alert addAction:conform];
@@ -305,7 +222,7 @@
if (islogin) {//登录成功 重置Tabbar
self.mainTabBar = nil;
self.mainTabBar = [HQBaseTabBarController new];
self.mainTabBar = [XJBaseTabBarController new];
self.mainTabBar.delegate =self;
self.window.rootViewController = self.mainTabBar;
[self.window makeKeyAndVisible];
@@ -314,8 +231,8 @@
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.backgroundColor = KWhiteColor;
HQLoginViewController * loginvc = [[HQLoginViewController alloc] init];
HQBaseNavigationController * nav = [[HQBaseNavigationController alloc] initWithRootViewController:loginvc];
XJLoginTopChangeViewController * loginvc = [[XJLoginTopChangeViewController alloc] init];
XJBaseNavigationController * nav = [[XJBaseNavigationController alloc] initWithRootViewController:loginvc];
self.window.rootViewController = nav;
[self.window makeKeyAndVisible];
@@ -332,27 +249,24 @@
#pragma mark: 切换tabbar
- (void)tabBarSoSChange:(NSNotification *)notification {
- (void)tabBarQuestionChange:(NSNotification *)notification {
self.mainTabBar.selectedIndex = 1;
}
- (void)tabBarSOSChange:(NSNotification *)notification {
self.mainTabBar.selectedIndex = 2;
}
- (void)tabBarPhyChange:(NSNotification *)notification {
- (void)tabBarMonitoringChange:(NSNotification *)notification {
self.mainTabBar.selectedIndex = 3;
}
- (void)tabBarFileChange:(NSNotification *)notification {
self.mainTabBar.selectedIndex = 4;
}
+ (AppDelegate *)shareAppDelegate{
return (AppDelegate *)[[UIApplication sharedApplication] delegate];
@@ -6,7 +6,7 @@
//
#import <UIKit/UIKit.h>
#import "HQBaseTabBarController.h"
#import "XJBaseTabBarController.h"
/**腾讯IM**/
#import "TUIDefine.h"
#import "TUIBaseChatViewController.h"
@@ -22,7 +22,7 @@
@property (nonatomic,assign)NSInteger allowRotate;
@property (strong, nonatomic) HQBaseTabBarController * mainTabBar;
@property (strong, nonatomic) XJBaseTabBarController * mainTabBar;
@property (nonatomic,assign)NSInteger unreadNumber;
@@ -7,6 +7,7 @@
#import "AppDelegate.h"
#import "SJRotationManager.h"
#import "XJWeChatManager.h"
#import <SDWebImageWebPCoder/SDWebImageWebPCoder.h>
@implementation AppDelegate
@@ -20,10 +21,6 @@
//前缀请求
//初始化高德地图
[self configureAPIKey];
//前缀请求
[self chageUrlService];
[self initService];
//初始化window
[self initWindow];
@@ -37,15 +34,11 @@
SDImageWebPCoder*webPCoder = [SDImageWebPCoder sharedCoder];
[[SDImageCodersManager sharedManager] addCoder:webPCoder];
#if DEBUG
#else
[CheckProjectTool testAll];
#endif
// 注册微信 SDK
[[XJWeChatManager sharedManager] registerWithAppID:kAppKey_Wechat
universalLink:kUniversalLink_Wechat];
return YES;
}
@@ -66,6 +59,17 @@
}
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
if (window == self.window) {
// 遍历找到最顶层的 presented VC
UIViewController *vc = self.window.rootViewController;
while (vc.presentedViewController) { vc = vc.presentedViewController; }
// WKWebView 视频全屏(WKFullScreenViewController)或 AVPlayer 全屏时放行横屏
NSString *className = NSStringFromClass(vc.class);
if ([className containsString:@"FullScreen"] || [className containsString:@"AVPlayer"]) {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
return UIInterfaceOrientationMaskPortrait;
}
return [SJRotationManager supportedInterfaceOrientationsForWindow:window];
}
@@ -84,10 +88,15 @@
}
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
return [[XJWeChatManager sharedManager] handleOpenURL:url];
}
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray<id<UIUserActivityRestoring>> * __nullable restorableObjects))restorationHandler {
if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
return [[XJWeChatManager sharedManager] handleOpenUniversalLink:userActivity];
}
return YES;
}
@@ -0,0 +1,33 @@
//
// PointsBankHModel.h
// XinjiangProject
//
// Created by Apple on 2026/2/6.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface PointsBankHModel : NSObject
@property (nonatomic, assign) double points;
@property (nonatomic, assign) double addPointsSum;
@property (nonatomic, assign) double exchangePointsSum;
//RANK
@property (nonatomic, assign) double frequency;
@property (nonatomic, assign) double ruleCategory;
@property (nonatomic, copy) NSString * ruleDesc;
@property (nonatomic, copy) NSString * icon;
@property (nonatomic, assign) double status;
@property (nonatomic, assign) double delFlag;
@property (nonatomic, copy) NSString * createUser;
@property (nonatomic, copy) NSString * createTime;
@property (nonatomic, copy) NSString * lastModifyDate;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,12 @@
//
// PointsBankHModel.m
// XinjiangProject
//
// Created by Apple on 2026/2/6.
//
#import "PointsBankHModel.h"
@implementation PointsBankHModel
@end
@@ -0,0 +1,16 @@
//
// PointsBankDetailViewController.h
// XinjiangProject
//
// Created by Apple on 2026/2/6.
//
#import "XJBaseViewController.h"
NS_ASSUME_NONNULL_BEGIN
@interface PointsBankDetailViewController : XJBaseViewController
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,263 @@
//
// PointsBankDetailViewController.m
// XinjiangProject
//
// Created by Apple on 2026/2/6.
//
#import "PointsBankDetailViewController.h"
#import "PointsBankHModel.h"
#import "PointsBankHomeTopView.h"
@interface PointsBankDetailViewController ()<UITableViewDelegate,UITableViewDataSource>
@property (nonatomic, strong) UITableView * homeTable;
@property (nonatomic, assign) NSInteger pageNo;
@property (nonatomic, strong) PointsBankHomeTopView * topView;
@property (nonatomic, strong) NSMutableArray * dataArray;
@end
@implementation PointsBankDetailViewController
- (NSMutableArray *)dataArray {
if (!_dataArray) {
_dataArray = [[NSMutableArray alloc] init];
}
return _dataArray;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = KWhiteColor;
self.pageNo = 1;
[self createData];
[self createUI];
// Do any additional setup after loading the view.
}
- (void)createUI {
self.topView= [[PointsBankHomeTopView alloc] init];
[self.view addSubview:self.topView];
[self.topView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.right.mas_offset(0);
}];
self.homeTable = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
if ([[UIDevice currentDevice].systemVersion floatValue] >= 11) {
self.homeTable.estimatedRowHeight = 60;
if (@available(iOS 15.0, *)) {
self.homeTable.sectionHeaderTopPadding = 0;
} else {
// Fallback on earlier versions
}
self.homeTable.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
self.homeTable.delegate = self;
self.homeTable.dataSource = self;
self.homeTable.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
self.homeTable.showsVerticalScrollIndicator = NO;
self.homeTable.backgroundColor = KClearColor;
self.homeTable.rowHeight = UITableViewAutomaticDimension;
self.homeTable.estimatedRowHeight = 80;
[self.view addSubview:self.homeTable];
[self.homeTable mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(_topView.mas_bottom);
make.left.bottom.right.mas_offset(0);
}];
__weak __typeof(self) weakSelf = self;
self.homeTable.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
weakSelf.pageNo = 1;
[weakSelf.dataArray removeAllObjects];
[weakSelf createData];
}];
self.homeTable.mj_footer = [MJRefreshBackNormalFooter footerWithRefreshingBlock:^{
weakSelf.pageNo++;
[weakSelf createData];
}];
LYEmptyView *emptyView = [LYEmptyView emptyViewWithImageStr:@"noDataBox" titleStr:@"暂无数据" detailStr:@""];
//元素竖直方向的间距
emptyView.subViewMargin = 20.f;
//标题颜色
emptyView.titleLabTextColor = [UIColor blackColor];
//描述字体
emptyView.detailLabFont = [UIFont systemFontOfSize:17];
//按钮背景色
emptyView.actionBtnBackGroundColor = KWhiteColor;
emptyView.actionBtnWidth = CGFLOAT_MIN;
emptyView.actionBtnHeight = CGFLOAT_MIN;
//设置空内容占位图
self.homeTable.ly_emptyView = emptyView;
}
- (void)createData {
[self showMBProgressHUDWithString:@"加载中,请稍候..." autoHidden:false];
NSMutableDictionary * parmDic = [[NSMutableDictionary alloc] init];
[parmDic setObject:@(self.pageNo) forKey:@"pageNo"];
[parmDic setObject:@"10" forKey:@"pageSize"];
XJPNetAPI * listApi = [[XJPNetAPI alloc] init:self tag:@"LIST" NeedToken:@""];
[listApi getUserMessageList:parmDic];
}
#pragma mark - DataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.dataArray.count;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCell.new;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
- (CGFloat )tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return CGFLOAT_MIN;
}
- (CGFloat )tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
return CGFLOAT_MIN;
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
return UIView.new;
}
- (void)chageDataType:(UIButton *)typeBtn {
//请求接口
if (typeBtn.tag == 0) {
[self creeateRankDataWithTyep:@"1"];
}
if (typeBtn.tag == 1) {
[self creeateRankDataWithTyep:@"2"];
}
if (typeBtn.tag == 2) {
[self creeateRankDataWithTyep:@"0"];
}
}
- (void)creeateRankDataWithTyep:(NSString *)type {
//rankType(榜单类型,0总榜,1周榜,2月榜)
[self showMBProgressHUDWithString:@"加载中,请稍候..." autoHidden:false];
NSMutableDictionary * parmDic = [[NSMutableDictionary alloc] init];
[parmDic setObject:@(self.pageNo) forKey:@"pageNo"];
[parmDic setObject:@"10" forKey:@"pageSize"];
[parmDic setObject:type forKey:@"rankType"];
XJPNetAPI * listApi = [[XJPNetAPI alloc] init:self tag:@"DETAIL" NeedToken:@""];
[listApi postPointsBankSourceDetail:parmDic];
}
- (void)Failed:(NSString*)message tag:(NSString*)tag
{
[self.homeTable.mj_header endRefreshing];
[self.homeTable.mj_footer endRefreshing];
[self hiddenAllMBProgressHUD];
}
- (void)Sucess:(id)response tag:(NSString*)tag
{
[self.homeTable.mj_header endRefreshing];
[self.homeTable.mj_footer endRefreshing];
if ([tag isEqualToString:@"DETAIL"]) {
[self hiddenAllMBProgressHUD];
NSDictionary * responseDic = response;
PointsBankHModel * model = [PointsBankHModel modelWithDictionary:responseDic];
//points 可用积分 addPointsSum 累计积分 exchangePointsSum 累计兑换
self.topView.model = model;
}
if ([tag isEqualToString:@"RANK"]) {
NSDictionary * dic = response;
if ([dic.allKeys containsObject:@"page"]) {
NSDictionary * pageDic = [dic objectForKey:@"page"];
//取到排名
if ([pageDic.allKeys containsObject:@"records"]) {
NSArray * array = [pageDic objectForKey:@"records"];
for (NSDictionary * rankDic in array) {
PointsBankHModel * mdoel = [PointsBankHModel modelWithDictionary:rankDic];
[self.dataArray addObject:mdoel];
}
//处理结束 给数据
[self.homeTable reloadData];
}
}
}
//
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end
@@ -0,0 +1,19 @@
//
// PointsBankHomeTopView.h
// XinjiangProject
//
// Created by Apple on 2026/2/6.
//
#import <UIKit/UIKit.h>
#import "PointsBankHModel.h"
NS_ASSUME_NONNULL_BEGIN
@interface PointsBankHomeTopView : UIView
@property (nonatomic, strong) PointsBankHModel * model;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,144 @@
//
// PointsBankHomeTopView.m
// XinjiangProject
//
// Created by Apple on 2026/2/6.
//
#import "PointsBankHomeTopView.h"
@interface PointsBankHomeTopView ()
@property (nonatomic, strong) UILabel * pointsDataLabel;
@property (nonatomic, strong) UILabel * pointsAddLabel;
@property (nonatomic, strong) UILabel * exchangeLabel;
@end
@implementation PointsBankHomeTopView
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
}
*/
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self createUI];
}
return self;
}
- (void)createUI {
UILabel * haveLab = [[UILabel alloc] init];
haveLab.text = @"可用积分";
haveLab.textColor = CFontColor1;
haveLab.font = [UIFont systemFontOfSize:13 weight:UIFontWeightRegular];
[self addSubview:haveLab];
[haveLab mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_offset(15);
make.top.mas_offset(15);
}];
self.pointsDataLabel = [[UILabel alloc] init];
self.pointsDataLabel.text = @"--";
self.pointsDataLabel.textColor = CFontColor1;
self.pointsDataLabel.font = [UIFont systemFontOfSize:28 weight:UIFontWeightBold];
[self addSubview:self.pointsDataLabel];
[self.pointsDataLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(haveLab);
make.top.mas_equalTo(haveLab.mas_bottom).offset(12);
}];
UIButton * sourceBtn = [[UIButton alloc] init];
[sourceBtn setTitle:@"获取积分" forState:UIControlStateNormal];
[sourceBtn setTitleColor:KWhiteColor forState:UIControlStateNormal];
sourceBtn.titleLabel.font = SYSTEMFONT(15);
sourceBtn.layer.cornerRadius = 4;
sourceBtn.layer.masksToBounds = true;
sourceBtn.backgroundColor = UIColorHex(#21BEBE);
[self addSubview:sourceBtn];
[sourceBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.mas_offset(-15);
make.width.mas_offset(80);
make.height.mas_offset(32);
make.top.mas_offset(53);
}];
UILabel * addLab = [[UILabel alloc] init];
addLab.text = @"累计积分:";
addLab.textColor = CFontColor1;
addLab.font = [UIFont systemFontOfSize:13 weight:UIFontWeightRegular];
self.pointsAddLabel = addLab;
[self addSubview:addLab];
[addLab mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(haveLab.mas_right).offset(81);
make.top.mas_equalTo(haveLab.mas_bottom).offset(11);
}];
self.exchangeLabel = [[UILabel alloc] init];
self.exchangeLabel.text = @"累计兑换:";
self.exchangeLabel.textColor = CFontColor1;
self.exchangeLabel.font = [UIFont systemFontOfSize:13 weight:UIFontWeightRegular];
[self addSubview:self.exchangeLabel];
[self.exchangeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(haveLab.mas_right).offset(81);
make.top.mas_equalTo(addLab.mas_bottom).offset(11);
}];
UIView *dashedView = [[UIView alloc] init];
[self addSubview:dashedView];
// Masonry 布局
[dashedView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(20);
make.right.mas_equalTo(-20);
make.top.mas_equalTo(self.pointsDataLabel.mas_bottom).offset(10);
make.height.mas_equalTo(1); // 高度可以随意
make.bottom.mas_equalTo(-10);
}];
//虚线
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.strokeColor = [UIColor lightGrayColor].CGColor; // 线颜色
shapeLayer.lineWidth = 1; // 线宽
shapeLayer.lineDashPattern = @[@4, @2]; // 虚线:4pt 实线,2pt 空白
// 创建路径
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, 0, 0); // 起点
CGPathAddLineToPoint(path, NULL, [UIScreen mainScreen].bounds.size.width - 40, 0); // 终点
shapeLayer.path = path;
CGPathRelease(path);
// 添加到 view
[dashedView.layer addSublayer:shapeLayer];
}
-(void)setModel:(PointsBankHModel *)model {
_model = model;
self.pointsDataLabel.text = [NSString stringWithFormat:@"%.0f",_model.points];
self.pointsAddLabel.text = [NSString stringWithFormat:@"累计积分:%.0f",_model.addPointsSum];
self.exchangeLabel.text = [NSString stringWithFormat:@"累计兑换%.0f",_model.exchangePointsSum];
}
@end
@@ -0,0 +1,16 @@
//
// myPointsBankHomeViewController.h
// XinjiangProject
//
// Created by Apple on 2026/2/6.
//
#import "XJBaseViewController.h"
NS_ASSUME_NONNULL_BEGIN
@interface myPointsBankHomeViewController : XJBaseViewController
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,439 @@
//
// myPointsBankHomeViewController.m
// XinjiangProject
//
// Created by Apple on 2026/2/6.
//
#import "myPointsBankHomeViewController.h"
#import "PointsBankHModel.h"
#import "PointsBankHomeTopView.h"
@interface myPointsBankHomeViewController ()<UITableViewDelegate,UITableViewDataSource>
@property (nonatomic, strong) UITableView * homeTable;
@property (nonatomic, assign) NSInteger pageNo;
@property (nonatomic, strong) NSMutableArray * dataArray;
@property (nonatomic, strong) NSMutableArray * buttonArray;
@property (nonatomic, strong) PointsBankHomeTopView * topView;
@property (nonatomic, strong) UIView * lineView;
@end
@implementation myPointsBankHomeViewController
- (NSMutableArray *)dataArray {
if (!_dataArray ) {
_dataArray = [[NSMutableArray alloc] init];
}
return _dataArray;
}
- (NSMutableArray *)buttonArray {
if (!_buttonArray ) {
_buttonArray = [[NSMutableArray alloc] init];
}
return _buttonArray;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.isHidenNaviBar = false;
self.navigationItem.title = @"我的积分银行";
[self createData];
//默认总榜单
[self creeateRankDataWithTyep:@"0"];
[self createUI];
}
- (void)createUI {
//首页
self.topView = [[PointsBankHomeTopView alloc] init];
[self.view addSubview:self.topView];
[self.topView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.top.mas_offset(0);
// make.height.mas_offset(185);
}];
//功能栏
NSArray * toolsArray = @[@[@"积分兑换",@"img1"],@[@"积分明细",@"img2"],@[@"兑换记录",@"img3"]];
CGFloat itemWidth = 60;
CGFloat itemHeight = 110;
NSInteger count = toolsArray.count;
for (int i = 0; i < count; i++) {
NSArray *item = toolsArray[i];
// 1️⃣ 容器 view
UIView *itemView = [[UIView alloc] init];
itemView.tag = i;
itemView.userInteractionEnabled = YES;
[self.view addSubview:itemView];
// 2️⃣ 点击手势
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(itemTap:)];
[itemView addGestureRecognizer:tap];
// 3️⃣ 布局 container(每个 item 占 1/3 屏幕宽)
CGFloat thirdWidth = UIScreen.mainScreen.bounds.size.width / count;
[itemView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(self.topView.mas_bottom).offset(20);
make.width.mas_equalTo(itemWidth);
make.height.mas_equalTo(itemHeight);
make.centerX.mas_equalTo(self.view.mas_left).offset(thirdWidth * i + thirdWidth / 2);
}];
// 4️⃣ 图片
UIImageView *icon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:item[1]]];
icon.contentMode = UIViewContentModeScaleAspectFit;
[itemView addSubview:icon];
[icon mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(0);
make.centerX.equalTo(itemView);
make.width.height.mas_equalTo(40);
}];
// 5️⃣ 文字
UILabel *label = [[UILabel alloc] init];
label.text = item[0];
label.font = [UIFont systemFontOfSize:14];
label.textAlignment = NSTextAlignmentCenter;
[itemView addSubview:label];
[label mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(icon.mas_bottom).offset(8);
make.left.right.equalTo(itemView);
make.height.mas_equalTo(20);
}];
}
//排行
UIView * rankView = [[UIView alloc] init];
rankView.backgroundColor = KWhiteColor;
[self.view addSubview:rankView];
UILabel * rankTitleLab = [[UILabel alloc] init];
rankTitleLab.text = @"积分排行(单位)";
rankTitleLab.textColor = CFontColor1;
[rankView addSubview:rankTitleLab];
[rankTitleLab mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_offset(15);
make.top.mas_offset(15);
}];
UILabel * detailLab = [[UILabel alloc] init];
detailLab.text = @"以员工累计获得积分进行排名";
detailLab.textColor = CFontColor1;
[rankView addSubview:detailLab];
[detailLab mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_offset(15);
make.top.mas_equalTo(rankTitleLab.mas_bottom).offset(8);
}];
//周排名 月排名 年排名
UIView * lineView = [[UIView alloc] init];
lineView.backgroundColor = UIColor.blueColor;
self.lineView = lineView;
[rankView addSubview:lineView];
[lineView mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.mas_offset(80);
make.height.mas_offset(2);
}];
NSArray * array = @[@"周排名",@"月排名",@"年排名"];
UIButton * lastBtn = nil;
for (int i= 0; i < 3; i ++) {
UIButton * btn = [[UIButton alloc] init];
[btn setTitle:array[i] forState:UIControlStateNormal];
[btn setTitleColor:UIColor.blueColor forState:UIControlStateSelected];
[btn setTitleColor:UIColor.blackColor forState:UIControlStateNormal];
btn.titleLabel.font = MEDIUMFONT(13);
btn.tag = i;
[btn addTarget:self action:@selector(chageDataType:) forControlEvents:UIControlEventTouchUpInside];
btn.selected = false;
if (i == 2) {
btn.selected = true;
lastBtn = btn;
}
[rankView addSubview:btn];
[btn mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.mas_offset(80);
make.height.mas_offset(32);
make.top.mas_equalTo(detailLab.mas_bottom).offset(10);
if (i == 0) {
make.left.mas_offset(82);
}
if (i == 1) {
make.centerX.mas_equalTo(rankView);
}
if (i == 2) {
make.right.mas_offset(-82);
}
}];
[self.buttonArray addObject:btn];
}
if (lastBtn) {
[lineView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.mas_equalTo(lastBtn);
make.top.mas_equalTo(lastBtn.mas_bottom).offset(5);
}];
}
[rankView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.mas_offset(0);
make.top.mas_equalTo(self.topView.mas_bottom).offset(15);
make.bottom.mas_equalTo(lastBtn.mas_bottom).offset(20);
}];
self.homeTable = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
if ([[UIDevice currentDevice].systemVersion floatValue] >= 11) {
self.homeTable.estimatedRowHeight = 60;
if (@available(iOS 15.0, *)) {
self.homeTable.sectionHeaderTopPadding = 0;
} else {
// Fallback on earlier versions
}
self.homeTable.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
self.homeTable.delegate = self;
self.homeTable.dataSource = self;
self.homeTable.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
self.homeTable.showsVerticalScrollIndicator = NO;
self.homeTable.backgroundColor = KClearColor;
self.homeTable.rowHeight = UITableViewAutomaticDimension;
self.homeTable.estimatedRowHeight = 80;
[self.view addSubview:self.homeTable];
[self.homeTable mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(rankView.mas_bottom);
make.left.bottom.right.mas_offset(0);
}];
__weak __typeof(self) weakSelf = self;
self.homeTable.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
weakSelf.pageNo = 1;
[weakSelf.dataArray removeAllObjects];
[weakSelf createData];
}];
self.homeTable.mj_footer = [MJRefreshBackNormalFooter footerWithRefreshingBlock:^{
weakSelf.pageNo++;
[weakSelf createData];
}];
LYEmptyView *emptyView = [LYEmptyView emptyViewWithImageStr:@"noDataBox" titleStr:@"暂无数据" detailStr:@""];
//元素竖直方向的间距
emptyView.subViewMargin = 20.f;
//标题颜色
emptyView.titleLabTextColor = [UIColor blackColor];
//描述字体
emptyView.detailLabFont = [UIFont systemFontOfSize:17];
//按钮背景色
emptyView.actionBtnBackGroundColor = KWhiteColor;
emptyView.actionBtnWidth = CGFLOAT_MIN;
emptyView.actionBtnHeight = CGFLOAT_MIN;
//设置空内容占位图
self.homeTable.ly_emptyView = emptyView;
}
- (void)createData {
[self showMBProgressHUDWithString:@"加载中,请稍候..." autoHidden:false];
NSMutableDictionary * parmDic = [[NSMutableDictionary alloc] init];
XJPNetAPI * listApi = [[XJPNetAPI alloc] init:self tag:@"HEARD" NeedToken:@""];
[listApi getPointsBankHeard:parmDic];
}
#pragma mark - DataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.dataArray.count;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCell.new;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
- (CGFloat )tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return CGFLOAT_MIN;
}
- (CGFloat )tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
return CGFLOAT_MIN;
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
return UIView.new;
}
- (void)chageDataType:(UIButton *)typeBtn {
for (UIButton * seleBtn in self.buttonArray) {
if (seleBtn == typeBtn) {
seleBtn.selected = true;
[self.lineView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.left.right.mas_equalTo(typeBtn);
make.bottom.mas_equalTo(typeBtn.mas_bottom).offset(8);
make.height.mas_offset(1);
make.centerX.mas_equalTo(typeBtn);
}];
}else
{
seleBtn.selected = false;
}
}
//请求接口
if (typeBtn.tag == 0) {
[self creeateRankDataWithTyep:@"1"];
}
if (typeBtn.tag == 1) {
[self creeateRankDataWithTyep:@"2"];
}
if (typeBtn.tag == 2) {
[self creeateRankDataWithTyep:@"0"];
}
}
- (void)creeateRankDataWithTyep:(NSString *)type {
//rankType(榜单类型,0总榜,1周榜,2月榜)
[self showMBProgressHUDWithString:@"加载中,请稍候..." autoHidden:false];
NSMutableDictionary * parmDic = [[NSMutableDictionary alloc] init];
[parmDic setObject:@(self.pageNo) forKey:@"pageNo"];
[parmDic setObject:@"10" forKey:@"pageSize"];
[parmDic setObject:type forKey:@"rankType"];
XJPNetAPI * listApi = [[XJPNetAPI alloc] init:self tag:@"RANK" NeedToken:@""];
[listApi postPointsBankRankData:parmDic];
}
- (void)Failed:(NSString*)message tag:(NSString*)tag
{
[self.homeTable.mj_header endRefreshing];
[self.homeTable.mj_footer endRefreshing];
[self hiddenAllMBProgressHUD];
}
- (void)Sucess:(id)response tag:(NSString*)tag
{
[self.homeTable.mj_header endRefreshing];
[self.homeTable.mj_footer endRefreshing];
if ([tag isEqualToString:@"HEARD"]) {
[self hiddenAllMBProgressHUD];
NSDictionary * responseDic = response;
PointsBankHModel * model = [PointsBankHModel modelWithDictionary:responseDic];
//points 可用积分 addPointsSum 累计积分 exchangePointsSum 累计兑换
self.topView.model = model;
}
if ([tag isEqualToString:@"RANK"]) {
NSDictionary * dic = response;
if ([dic.allKeys containsObject:@"page"]) {
NSDictionary * pageDic = [dic objectForKey:@"page"];
//取到排名
if ([pageDic.allKeys containsObject:@"records"]) {
NSArray * array = [pageDic objectForKey:@"records"];
for (NSDictionary * rankDic in array) {
PointsBankHModel * mdoel = [PointsBankHModel modelWithDictionary:rankDic];
[self.dataArray addObject:mdoel];
}
//处理结束 给数据
[self.homeTable reloadData];
}
}
}
//
}
- (void)itemTap:(UITapGestureRecognizer *)tap {
NSInteger index = tap.view.tag;
NSLog(@"点击了第 %ld 个", index);
if(index == 1 || index == 2) {
[EasyTextView showInfoText:@"开发者,敬请期待!"];
return;
}
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end
@@ -1,249 +0,0 @@
//
// BaseWebViewVC.m
// ScarHousekeeper
//
// Created by 张小万 on 2021/1/21.
//
#import "BaseWebViewVC.h"
@interface BaseWebViewVC ()<UINavigationControllerDelegate, UIImagePickerControllerDelegate>
@property (nonatomic, strong)NSURL *originalUrl;
@property (nonatomic, copy)NSString *videoUrl;
@property (nonatomic, copy)NSString *messageType;
@end
@implementation BaseWebViewVC
#pragma mark - LifeCycle
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.isHidenNaviBar = false;
[self addNavigationItemWithImageNames:@[@"whiteBack_icon"] isLeft:YES target:self action:@selector(backVC) tags:@[@""]];
[self addSubviews];
if (self.webTitle) {
self.navigationItem.title = self.webTitle;
}
}
- (void)backVC {
[self.navigationController popViewControllerAnimated:YES];
}
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
if (_wkWebView) {
_wkWebView.navigationDelegate = self;
_wkWebView.UIDelegate = self;
_wkWebView.allowsBackForwardNavigationGestures = true;
}
}
- (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
_wkWebView.navigationDelegate = nil;
_wkWebView.UIDelegate = nil;
//清除cookies
NSHTTPCookie *cookie;
NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (cookie in [storage cookies]) {
[storage deleteCookie:cookie];
}
[[NSURLCache sharedURLCache] removeAllCachedResponses];
[self clearWebViewCache];
}
#pragma mark - Create UI
- (void)addSubviews{
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
WKPreferences *preferences = [[WKPreferences alloc]init];
preferences.javaScriptEnabled = YES;
preferences.javaScriptCanOpenWindowsAutomatically = YES;
preferences.minimumFontSize = 10;
configuration.preferences = preferences;
[configuration.userContentController addScriptMessageHandler:self name:@"JSCallback"];
[configuration.userContentController addScriptMessageHandler:self name:@"htmlBack"];
//防止搜索框自动放大 注入js代码
WKUserContentController *userController = [WKUserContentController new];
NSString *jScript = @"var script = document.createElement('meta');script.name = 'viewport';script.content='width=device-width,user-scalable=no';document.getElementsByTagName('head')[0].appendChild(script);";
WKUserScript *wkUScript = [[WKUserScript alloc] initWithSource:jScript injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
WKUserContentController * wkUController = [[WKUserContentController alloc] init];
[wkUController addScriptMessageHandler: self name: @"finishActivity"];//不带参数的调用
[wkUController addUserScript:wkUScript];
configuration.userContentController= wkUController;
self.wkWebView = [[WKWebView alloc]initWithFrame:CGRectMake(0, 0, WIDTH, MyViewHEIGHT) configuration:configuration];
self.wkWebView.navigationDelegate = self;
self.wkWebView.UIDelegate = self;
if (@available(iOS 11.0, *)) {
self.wkWebView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
[self.view addSubview:self.wkWebView];
self.wkWebView.scrollView.bounces = false;//禁止滑动
[self webViewRequest];
/*
[self.wkWebView evaluateJavaScript:@"htmlBack" completionHandler:^(id _Nullable response, NSError * _Nullable error) {
NSLog(@"response: %@ error: %@", response, error);
if (response) {
[self back];
}
}];
*/
}
- (void)finishActivity {
}
- (void)webViewRequest{
NSString *urlString = self.webUrl;
[self hiddenAllMBProgressHUD];
if (urlString.length > 0) {
[self showMBProgressHUDOnlyWithString:@"加载中"];
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
if (self.wkWebView) {
[self.wkWebView loadRequest:urlRequest];
}
}
}
#pragma mark - WKNavigationDelegate
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
if ([message.name isEqualToString:@"JSCallback"]) {
if (message.body) {
NSData *jsonData = [message.body dataUsingEncoding:NSUTF8StringEncoding];
NSError *err;
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingMutableContainers
error:&err];
if(err) {
}
WkJSMessageType messageType = [[dic objectForKey:@"messageType"] intValue];
switch (messageType) {
case WkJSMessageTypeBack:{
// [self.navigationController popViewControllerAnimated:YES];
}
break;
default:
break;
}
}
} else if ([message.name isEqualToString:@"htmlBack"]) {
[[NSNotificationCenter defaultCenter] postNotificationName:@"fromWebToReloadData" object:nil];
}
}
#pragma mark - WKScriptMessageHandler
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {
[self hiddenAllMBProgressHUD];
if (!navigationAction.targetFrame.isMainFrame) {
[webView loadRequest:navigationAction.request];
}
return nil;
}
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{
if (!self.webTitle) {
self.title = @"加载中...";
}
}
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation{
[self hiddenAllMBProgressHUD];
if (!self.webTitle) {
self.title = webView.title;
}
}
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(nonnull NSError *)error{
[self hiddenAllMBProgressHUD];
}
#pragma mark - ACTION
- (void)ToClickNavRight:(UIButton *)button{
}
#pragma mark - 自定义
- (void)onBackClicked{
if ( self.wkWebView.canGoBack){
[self.wkWebView goBack];
} else {
[self clearWebViewCache];
}
}
- (void)clearWebViewCache{
if (iOS9Later) {
NSSet *websiteDataTypes = [WKWebsiteDataStore allWebsiteDataTypes];
NSDate *dateFrom = [NSDate dateWithTimeIntervalSince1970:0];
[[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:websiteDataTypes modifiedSince:dateFrom completionHandler:^{
NSLog(@"-----clear webView cache success------");
}];
} else {
NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *cookiesFolderPath = [libraryPath stringByAppendingString:@"/Cookies"];
NSError *errors;
[[NSFileManager defaultManager] removeItemAtPath:cookiesFolderPath error:&errors];
if (!errors) {
NSLog(@"-----clear wkWebView cache success------");
}
}
}
- (NSString *)URLEncodedString:(NSString *)urlString{
NSString *encodePath ;
if (!IOS7) {
encodePath = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
}else{
encodePath = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
}return encodePath;
}
#pragma mark - SETTER
- (void)setRightType:(RightNavType)rightType{
_rightType = rightType;
}
- (void)setWebUrl:(NSString *)webUrl{
_webUrl = webUrl;
[self webViewRequest];
}
@end
@@ -1,18 +0,0 @@
//
// DownPDFFileVC.h
// EscortProject
//
// Created by 仁康信息 on 2023/12/1.
//
#import "HQBaseViewController.h"
NS_ASSUME_NONNULL_BEGIN
@interface DownPDFFileVC : HQBaseViewController
@property (nonatomic, strong) NSString * PDFUrl;
@end
NS_ASSUME_NONNULL_END
@@ -1,5 +1,5 @@
//
// HQBaseNavigationController.h
// XJBaseNavigationController.h
// healthQuestion
//
// Created by xulei on 2022/8/12.
@@ -9,7 +9,7 @@
NS_ASSUME_NONNULL_BEGIN
@interface HQBaseNavigationController : UINavigationController
@interface XJBaseNavigationController : UINavigationController
/*!
*
@@ -1,15 +1,15 @@
//
// HQBaseNavigationController.m
// XJBaseNavigationController.m
// healthQuestion
//
// Created by xulei on 2022/8/12.
//
#import "HQBaseNavigationController.h"
#import "XJBaseNavigationController.h"
#import "XYTransitionProtocol.h"
#import "XYTransition.h"
@interface HQBaseNavigationController ()<UINavigationControllerDelegate,UIGestureRecognizerDelegate>
@interface XJBaseNavigationController ()<UINavigationControllerDelegate,UIGestureRecognizerDelegate>
@property (nonatomic, weak) id popDelegate;
@property (nonatomic,strong) UIPercentDrivenInteractiveTransition *interactivePopTransition;
@@ -18,7 +18,7 @@
@end
@implementation HQBaseNavigationController
@implementation XJBaseNavigationController
//APP生命周期中
+ (void)initialize
@@ -124,8 +124,8 @@
-(void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
if ([viewController isKindOfClass:[HQBaseViewController class]]) {
HQBaseViewController * vc = (HQBaseViewController *)viewController;
if ([viewController isKindOfClass:[XJBaseViewController class]]) {
XJBaseViewController * vc = (XJBaseViewController *)viewController;
if (vc.isHidenNaviBar) {
vc.view.top = 0;
[vc.navigationController setNavigationBarHidden:YES animated:animated];
@@ -1,5 +1,5 @@
//
// HQBaseTabBarController.h
// XJBaseTabBarController.h
// healthQuestion
//
// Created by xulei on 2022/8/12.
@@ -9,7 +9,7 @@
NS_ASSUME_NONNULL_BEGIN
@interface HQBaseTabBarController : UITabBarController
@interface XJBaseTabBarController : UITabBarController
/**
@@ -1,23 +1,24 @@
//
// HQBaseTabBarController.m
// XJBaseTabBarController.m
// healthQuestion
//
// Created by xulei on 2022/8/12.
//
#import "HQBaseTabBarController.h"
#import "XJBaseTabBarController.h"
#import "HQTabBar.h"
#import "MyCenterViewController.h"
#import "XJMyCenterViewController.h"
#import "ChatListViewController.h"
//
#import "QuestionViewController.h"
#import "MyCenterViewController.h"
#import "SosCenterViewController.h"
#import "HeartBadViewController.h"
#import "XJSosCenterViewController.h"
#import "MonitoringWarchViewController.h"
//
//
#import "XJHomePageV2ViewController.h"
@interface HQBaseTabBarController ()<UITabBarControllerDelegate>
@interface XJBaseTabBarController ()<UITabBarControllerDelegate>
@property (nonatomic,strong) NSMutableArray * VCS;//tabbar root VC
@@ -34,14 +35,12 @@
@end
@implementation HQBaseTabBarController
@implementation XJBaseTabBarController
- (void)viewDidLoad {
[super viewDidLoad];
self.delegate = self;
//tabbar
[self setUpTabBar];
//
@@ -74,19 +73,24 @@
-(void)setUpAllChildViewController{
_VCS = @[].mutableCopy;
//
XJHomePageV2ViewController * homeVC = [[XJHomePageV2ViewController alloc]init];
[self setupChildViewController:homeVC title:@"首页" imageName:@"xjHomeTabBar_nomal" seleceImageName:@"xjHomeTabBar_selected"];
QuestionViewController * questionVC = [[QuestionViewController alloc]init];
[self setupChildViewController:questionVC title:@"咨询" imageName:@"Question_normal_icon" seleceImageName:@"Question_selected_icon"];
[self setupChildViewController:questionVC title:@"咨询" imageName:@"questionTabBar_nomal" seleceImageName:@"questionTabBar_selected"];
SosCenterViewController * sosVC = [[SosCenterViewController alloc]init];
[self setupChildViewController:sosVC title:@"就医" imageName:@"Question_normal_icon" seleceImageName:@"Question_selected_icon"];
XJSosCenterViewController * sosVC = [[XJSosCenterViewController alloc]init];
[self setupChildViewController:sosVC title:@"应急" imageName:@"sosCenterTabBar_nomal" seleceImageName:@"sosCenterTabBar_selected"];
HeartBadViewController * jianceVC = [[HeartBadViewController alloc]init];
[self setupChildViewController:jianceVC title:@"监测" imageName:@"Question_normal_icon" seleceImageName:@"Question_selected_icon"];
MonitoringWarchViewController * jianceVC = [[MonitoringWarchViewController alloc]init];
[self setupChildViewController:jianceVC title:@"监测" imageName:@"monitoringTabBar_nomal" seleceImageName:@"monitoringTabBar_selected"];
MyCenterViewController * centerVC = [[MyCenterViewController alloc] init];
[self setupChildViewController:centerVC title:@"我的" imageName:@"mine_normal" seleceImageName:@"mine_selected"];
XJMyCenterViewController * centerVC = [[XJMyCenterViewController alloc] init];
[self setupChildViewController:centerVC title:@"我的" imageName:@"mineTabBar_nomal" seleceImageName:@"mineTabBar_selected"];
self.viewControllers = _VCS;
@@ -105,7 +109,7 @@
[controller.tabBarItem setTitleTextAttributes:@{NSForegroundColorAttributeName:UIColorHex(#21BEBD),NSFontAttributeName:SYSTEMFONT(10.0f)} forState:UIControlStateSelected];
//
HQBaseNavigationController *nav = [[HQBaseNavigationController alloc]initWithRootViewController:controller];
XJBaseNavigationController *nav = [[XJBaseNavigationController alloc]initWithRootViewController:controller];
[_VCS addObject:nav];
@@ -142,6 +146,10 @@
return [self.selectedViewController supportedInterfaceOrientations];
}
- (void)selectedQuestion {
self.selectedIndex = 1;
}
/*
#pragma mark - Navigation
@@ -1,5 +1,5 @@
//
// HQBaseViewController.h
// XJBaseViewController.h
// healthQuestion
//
// Created by xulei on 2022/8/11.
@@ -10,7 +10,7 @@
NS_ASSUME_NONNULL_BEGIN
@interface HQBaseViewController : UIViewController
@interface XJBaseViewController : UIViewController
/**
*
@@ -5,14 +5,14 @@
// Created by xulei on 2022/8/11.
//
#import "HQBaseViewController.h"
#import "HQLoginViewController.h"
#import "XJBaseViewController.h"
#import "XJLoginViewController.h"
@interface HQBaseViewController ()<MBProgressHUDDelegate>
@interface XJBaseViewController ()<MBProgressHUDDelegate>
@end
@implementation HQBaseViewController
@implementation XJBaseViewController
- (UIStatusBarStyle)preferredStatusBarStyle{
return _StatusBarStyle;
@@ -1,5 +1,5 @@
//
// BaseWebViewVC.h
// XJBaseWebViewVC.h
// ScarHousekeeper
//
// Created by 张小万 on 2021/1/21.
@@ -25,7 +25,7 @@ typedef enum {
- (void)startFunction;
@end
@interface BaseWebViewVC : HQBaseViewController<UIAlertViewDelegate,WKNavigationDelegate, WKUIDelegate, WebJSExport, WKScriptMessageHandler>
@interface XJBaseWebViewVC : XJBaseViewController<UIAlertViewDelegate,WKNavigationDelegate, WKUIDelegate, WebJSExport, WKScriptMessageHandler>
@property (nonatomic, strong) NSString *webUrl;
@property (nonatomic, strong) NSString *webTitle;
@@ -0,0 +1,501 @@
//
// XJBaseWebViewVC.m
// ScarHousekeeper
//
// Created by 张小万 on 2021/1/21.
//
#import "XJBaseWebViewVC.h"
@interface XJBaseWebViewVC ()<UINavigationControllerDelegate, UIImagePickerControllerDelegate>
// 以下三个属性声明后未使用,暂时保留
//@property (nonatomic, strong)NSURL *originalUrl;
//@property (nonatomic, copy)NSString *videoUrl;
//@property (nonatomic, copy)NSString *messageType;
/// 网页加载进度条
@property (nonatomic, strong) UIProgressView *progressView;
/// 加载失败占位视图
@property (nonatomic, strong) UIView *errorView;
@end
// ── 弱引用代理 ──────────────────────────────────────────────────────────────
// WKUserContentController 对 addScriptMessageHandler 的 handler 是强引用。
// 如果直接传 selfself → wkWebView → configuration → userContentController → self
// 形成循环引用,VC 永远无法释放。
// 解决方案:用一个弱引用中间对象转发消息。
@interface XJWeakScriptMessageHandler : NSObject <WKScriptMessageHandler>
@property (nonatomic, weak) id<WKScriptMessageHandler> delegate;
+ (instancetype)handlerWithDelegate:(id<WKScriptMessageHandler>)delegate;
@end
@implementation XJWeakScriptMessageHandler
+ (instancetype)handlerWithDelegate:(id<WKScriptMessageHandler>)delegate {
XJWeakScriptMessageHandler *handler = [[XJWeakScriptMessageHandler alloc] init];
handler.delegate = delegate;
return handler;
}
- (void)userContentController:(WKUserContentController *)userContentController
didReceiveScriptMessage:(WKScriptMessage *)message {
[self.delegate userContentController:userContentController didReceiveScriptMessage:message];
}
@end
// ────────────────────────────────────────────────────────────────────────────
@implementation XJBaseWebViewVC
#pragma mark - LifeCycle
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.isHidenNaviBar = false;
[self addNavigationItemWithImageNames:@[@"whiteBack_icon"] isLeft:YES target:self action:@selector(backVC) tags:@[@""]];
[self addSubviews];
if (self.webTitle) {
self.navigationItem.title = self.webTitle;
}
}
- (void)backVC {
[self.navigationController popViewControllerAnimated:YES];
}
- (void)dealloc {
// 移除进度条 KVO
[self.wkWebView removeObserver:self forKeyPath:@"estimatedProgress"];
// 移除所有 scriptMessageHandler,配合 XJWeakScriptMessageHandler 彻底避免内存泄漏
WKUserContentController *ucc = self.wkWebView.configuration.userContentController;
[ucc removeScriptMessageHandlerForName:@"JSCallback"];
[ucc removeScriptMessageHandlerForName:@"htmlBack"];
[ucc removeScriptMessageHandlerForName:@"finishActivity"];
}
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
if (_wkWebView) {
_wkWebView.navigationDelegate = self;
_wkWebView.UIDelegate = self;
_wkWebView.allowsBackForwardNavigationGestures = true;
}
}
- (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
_wkWebView.navigationDelegate = nil;
_wkWebView.UIDelegate = nil;
// ⚠️ 以下代码会清除整个 App 的所有 Cookie,影响其他模块登录状态,已注释
// NSHTTPCookie *cookie;
// NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
// for (cookie in [storage cookies]) {
// [storage deleteCookie:cookie];
// }
// [[NSURLCache sharedURLCache] removeAllCachedResponses];
// [self clearWebViewCache];
}
#pragma mark - Create UI
- (void)addSubviews{
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
WKPreferences *preferences = [[WKPreferences alloc]init];
// preferences.javaScriptEnabled = YES;
preferences.javaScriptCanOpenWindowsAutomatically = YES;
preferences.minimumFontSize = 10;
configuration.preferences = preferences;
// 允许视频内联播放,避免全屏时布局计算错误导致显示不完整
configuration.allowsInlineMediaPlayback = YES;
// ── 统一使用 configuration 自带的 userContentController ──────────────────
// Bug 修复:原先在下方又新建了 wkUController 并覆盖 configuration.userContentController
// 导致此处注册的 JSCallback / htmlBack 被丢弃,永远收不到 JS 消息。
// Bug 修复:改用 XJWeakScriptMessageHandler 代理,防止循环引用内存泄漏。
XJWeakScriptMessageHandler *weakHandler = [XJWeakScriptMessageHandler handlerWithDelegate:self];
[configuration.userContentController addScriptMessageHandler:weakHandler name:@"JSCallback"];
[configuration.userContentController addScriptMessageHandler:weakHandler name:@"htmlBack"];
[configuration.userContentController addScriptMessageHandler:weakHandler name:@"finishActivity"]; // 不带参数的调用
// 原写法(已废弃):直接传 self 会造成循环引用
// [configuration.userContentController addScriptMessageHandler:self name:@"JSCallback"];
// [configuration.userContentController addScriptMessageHandler:self name:@"htmlBack"];
// ────────────────────────────────────────────────────────────────────────
//防止搜索框自动放大 注入js代码
// 原代码中 userController 声明后从未使用,已移除
// WKUserContentController *userController = [WKUserContentController new];
NSString *jScript = @"var script = document.createElement('meta');script.name = 'viewport';script.content='width=device-width,user-scalable=no';document.getElementsByTagName('head')[0].appendChild(script);";
WKUserScript *wkUScript = [[WKUserScript alloc] initWithSource:jScript injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
// 原写法(已废弃):新建 wkUController 并覆盖 configuration.userContentController
// 导致上方注册的 JSCallback / htmlBack 全部失效
// WKUserContentController * wkUController = [[WKUserContentController alloc] init];
// [wkUController addScriptMessageHandler: self name: @"finishActivity"];
// [wkUController addUserScript:wkUScript];
// configuration.userContentController = wkUController;
[configuration.userContentController addUserScript:wkUScript];
// 禁用网页长按文字选中和复制粘贴菜单
NSString *noSelectJS = @"document.documentElement.style.webkitUserSelect='none';"
"document.documentElement.style.webkitTouchCallout='none';";
WKUserScript *noSelectScript = [[WKUserScript alloc] initWithSource:noSelectJS
injectionTime:WKUserScriptInjectionTimeAtDocumentEnd
forMainFrameOnly:NO];
[configuration.userContentController addUserScript:noSelectScript];
self.wkWebView = [[WKWebView alloc]initWithFrame:CGRectMake(0, 0, WIDTH, MyViewHEIGHT) configuration:configuration];
if (@available(iOS 16.4, *)) {
self.wkWebView.inspectable = YES;
}
// 伪装成 Safari User-Agent,排查 H5 API 请求因 UA 差异被拒的问题
{
NSString *osVer = [UIDevice currentDevice].systemVersion;
NSString *osVerUnder = [osVer stringByReplacingOccurrencesOfString:@"." withString:@"_"];
self.wkWebView.customUserAgent = [NSString stringWithFormat:
@"Mozilla/5.0 (iPhone; CPU iPhone OS %@ like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/%@ Mobile/15E148 Safari/604.1",
osVerUnder, osVer];
}
self.wkWebView.navigationDelegate = self;
self.wkWebView.UIDelegate = self;
if (@available(iOS 11.0, *)) {
self.wkWebView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
[self.view addSubview:self.wkWebView];
self.wkWebView.scrollView.bounces = false;//禁止滑动
// 进度条,居中偏上
self.progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
self.progressView.trackTintColor = [UIColor clearColor];
[self.view addSubview:self.progressView];
[self.progressView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self.wkWebView);
make.centerY.equalTo(self.wkWebView).offset(-60);
make.width.mas_offset(200);
make.height.mas_offset(2);
}];
// KVO 监听加载进度
[self.wkWebView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
// 加载失败占位视图(默认隐藏)
self.errorView = [[UIView alloc] init];
self.errorView.backgroundColor = [UIColor whiteColor];
self.errorView.hidden = YES;
[self.view addSubview:self.errorView];
[self.errorView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.wkWebView);
}];
UILabel *tipLabel = [[UILabel alloc] init];
tipLabel.text = @"网络加载失败\n请检查网络后重试";
tipLabel.textAlignment = NSTextAlignmentCenter;
tipLabel.numberOfLines = 0;
tipLabel.textColor = [UIColor colorWithRed:0.6 green:0.6 blue:0.6 alpha:1.0];
tipLabel.font = [UIFont systemFontOfSize:15];
[self.errorView addSubview:tipLabel];
[tipLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self.errorView);
make.centerY.equalTo(self.errorView).offset(-40);
make.left.greaterThanOrEqualTo(self.errorView).offset(20);
make.right.lessThanOrEqualTo(self.errorView).offset(-20);
}];
UIButton *reloadBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[reloadBtn setTitle:@"重新加载" forState:UIControlStateNormal];
[reloadBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
reloadBtn.titleLabel.font = [UIFont systemFontOfSize:15];
reloadBtn.backgroundColor = [UIColor colorWithRed:0.0 green:0.68 blue:0.41 alpha:1.0];
reloadBtn.layer.cornerRadius = 20;
reloadBtn.layer.masksToBounds = YES;
[reloadBtn addTarget:self action:@selector(reloadWebView) forControlEvents:UIControlEventTouchUpInside];
[self.errorView addSubview:reloadBtn];
[reloadBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(tipLabel.mas_bottom).offset(24);
make.right.equalTo(self.errorView.mas_centerX).offset(-8);
make.width.mas_offset(110);
make.height.mas_offset(40);
}];
UIButton *backBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[backBtn setTitle:@"返回" forState:UIControlStateNormal];
[backBtn setTitleColor:[UIColor colorWithRed:0.0 green:0.68 blue:0.41 alpha:1.0] forState:UIControlStateNormal];
backBtn.titleLabel.font = [UIFont systemFontOfSize:15];
backBtn.backgroundColor = [UIColor whiteColor];
backBtn.layer.cornerRadius = 20;
backBtn.layer.masksToBounds = YES;
backBtn.layer.borderWidth = 1;
backBtn.layer.borderColor = [UIColor colorWithRed:0.0 green:0.68 blue:0.41 alpha:1.0].CGColor;
[backBtn addTarget:self action:@selector(backVC) forControlEvents:UIControlEventTouchUpInside];
[self.errorView addSubview:backBtn];
[backBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(reloadBtn);
make.left.equalTo(self.errorView.mas_centerX).offset(8);
make.width.height.equalTo(reloadBtn);
}];
[self webViewRequest];
}
- (void)finishActivity {
// H5 调用 finishActivity 的默认行为:pop 返回上一页
// 语义等同于 Android 的 finish(),即关闭当前页面
// 子类如需特殊处理(如 dismiss、发通知等),override 此方法即可
[self.navigationController popViewControllerAnimated:YES];
}
- (void)reloadWebView {
self.errorView.hidden = YES;
[self webViewRequest];
}
- (void)webViewRequest{
[self clearWebViewCache];
NSString *urlString = self.webUrl;
DLog(@"[WebView] 请求加载: %@", urlString);
[self hiddenAllMBProgressHUD];
if (urlString.length > 0) {
[self showMBProgressHUDOnlyWithString:@"加载中"];
NSURL *url = [NSURL URLWithString:urlString];
if (!url) {
DLog(@"[WebView] URL 无效: %@", urlString);
}
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
if (self.wkWebView) {
[self.wkWebView loadRequest:urlRequest];
}
}
}
#pragma mark - KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:@"estimatedProgress"]) {
float progress = [change[NSKeyValueChangeNewKey] floatValue];
self.progressView.alpha = 1.0;
[self.progressView setProgress:progress animated:YES];
if (progress >= 1.0) {
// 加载完成后渐隐进度条
[UIView animateWithDuration:0.3 delay:0.2 options:0 animations:^{
self.progressView.alpha = 0;
} completion:^(BOOL finished) {
[self.progressView setProgress:0 animated:NO];
}];
}
}
}
#pragma mark - WKNavigationDelegate
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
if ([message.name isEqualToString:@"JSCallback"]) {
if (message.body) {
NSData *jsonData = [message.body dataUsingEncoding:NSUTF8StringEncoding];
NSError *err;
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingMutableContainers
error:&err];
if(err) {
}
WkJSMessageType messageType = [[dic objectForKey:@"messageType"] intValue];
switch (messageType) {
case WkJSMessageTypeBack:{
[self.navigationController popViewControllerAnimated:YES];
}
break;
default:
break;
}
}
} else if ([message.name isEqualToString:@"htmlBack"]) {
[[NSNotificationCenter defaultCenter] postNotificationName:@"fromWebToReloadData" object:nil];
} else if ([message.name isEqualToString:@"finishActivity"]) {
// JS 调用 window.webkit.messageHandlers.finishActivity.postMessage({}) 时触发
// 调用 finishActivity 方法,子类可 override 实现各自的关闭逻辑
// 基类默认实现为空,不做任何操作
[self finishActivity];
}
}
#pragma mark - WKScriptMessageHandler
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {
[self hiddenAllMBProgressHUD];
if (!navigationAction.targetFrame.isMainFrame) {
[webView loadRequest:navigationAction.request];
}
return nil;
}
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{
DLog(@"[WebView] 开始加载: %@", webView.URL);
self.errorView.hidden = YES;
if (!self.webTitle) {
self.title = @"加载中...";
}
}
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation{
DLog(@"[WebView] 加载完成: %@", webView.URL);
[self hiddenAllMBProgressHUD];
self.errorView.hidden = YES;
if (!self.webTitle) {
self.title = webView.title;
}
}
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(nonnull NSError *)error{
NSLog(@"[WebView] 加载失败 URL=%@ errorCode=%ld domain=%@ desc=%@",
webView.URL, (long)error.code, error.domain, error.localizedDescription);
[self hiddenAllMBProgressHUD];
// NSURLErrorCancelled (-999) 是主动取消导航(如跳转第三方 App),不算真实网络错误
if (error.code != NSURLErrorCancelled) {
self.errorView.hidden = NO;
}
}
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error {
NSLog(@"[WebView] 导航失败 URL=%@ errorCode=%ld domain=%@ desc=%@",
webView.URL, (long)error.code, error.domain, error.localizedDescription);
[self hiddenAllMBProgressHUD];
// NSURLErrorCancelled (-999) 是主动取消导航,不算真实网络错误
if (error.code != NSURLErrorCancelled) {
self.errorView.hidden = NO;
}
}
#pragma mark - 白屏修复
/**
* 拦截所有导航请求,处理非 HTTP/HTTPS scheme。
*
* 问题根源:
* 银行 H5 点击支付/跳转按钮时,会触发 alipay:// weixin:// tel:// 等 URL Scheme。
* WKWebView 默认会尝试自己加载这些 scheme,加载失败后清空页面内容 → 永久白屏。
*
* 解决方案:
* 在此方法中拦截非 HTTP/HTTPS 的请求,交由系统(UIApplication)处理,
* WKWebView 自身取消该次导航,页面内容保持不变。
*/
- (void)webView:(WKWebView *)webView
decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction
decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
NSURL *url = navigationAction.request.URL;
NSString *scheme = url.scheme.lowercaseString;
// HTTP / HTTPS:正常加载,交给 WKWebView 处理
if ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"]) {
decisionHandler(WKNavigationActionPolicyAllow);
return;
}
// about:blankWKWebView 内部使用,直接放行
if ([scheme isEqualToString:@"about"]) {
decisionHandler(WKNavigationActionPolicyAllow);
return;
}
// 其他 schemealipay:// weixin:// tel:// mailto:// 等):
// 交由系统打开对应 App 或拨号,WKWebView 取消此次导航,避免白屏
if ([[UIApplication sharedApplication] canOpenURL:url]) {
[[UIApplication sharedApplication] openURL:url
options:@{}
completionHandler:nil];
}
decisionHandler(WKNavigationActionPolicyCancel);
}
/**
* WebContent 进程被系统终止时的兜底处理。
*
* 触发场景:
* 设备内存严重不足时,系统会强制 kill 掉 WKWebView 的 WebContent 进程。
* 此时 WKWebView 会立即变成空白页,且无法响应任何操作。
* 若不处理,用户只能退出页面重新进入。
*
* 解决方案:
* 检测到进程终止后,重新加载当前 URL,让用户无感知恢复。
*/
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView {
NSLog(@"[XJBaseWebViewVC] WebContent 进程被系统终止,自动 reload");
// 重新加载,恢复页面内容
[webView reload];
}
#pragma mark - ACTION
- (void)ToClickNavRight:(UIButton *)button{
}
#pragma mark - 自定义
- (void)onBackClicked{
if (self.wkWebView.canGoBack) {
[self.wkWebView goBack];
} else {
// 原写法:只清缓存没有 pop,页面会卡住
// [self clearWebViewCache];
[self clearWebViewCache];
[self.navigationController popViewControllerAnimated:YES];
}
}
- (void)clearWebViewCache{
if (iOS9Later) {
NSSet *websiteDataTypes = [WKWebsiteDataStore allWebsiteDataTypes];
NSDate *dateFrom = [NSDate dateWithTimeIntervalSince1970:0];
[[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:websiteDataTypes modifiedSince:dateFrom completionHandler:^{
DLog(@"-----clear webView cache success------");
}];
} else {
NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *cookiesFolderPath = [libraryPath stringByAppendingString:@"/Cookies"];
NSError *errors;
[[NSFileManager defaultManager] removeItemAtPath:cookiesFolderPath error:&errors];
if (!errors) {
DLog(@"-----clear wkWebView cache success------");
}
}
}
- (NSString *)URLEncodedString:(NSString *)urlString{
NSString *encodePath;
encodePath = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
return encodePath;
}
#pragma mark - SETTER
// setRightType: 与自动合成的 setter 完全相同,无需 override,保留注释备查
//- (void)setRightType:(RightNavType)rightType{
// _rightType = rightType;
//}
- (void)setWebUrl:(NSString *)webUrl{
_webUrl = webUrl;
[self webViewRequest];
}
@end
@@ -1,6 +1,6 @@
//
// CustomSystemEvaluateModel.h
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/6/19.
//
@@ -1,6 +1,6 @@
//
// CustomSystemEvaluateModel.m
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/6/19.
//
@@ -1,6 +1,6 @@
//
// CustomTUIHistoryModel.h
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/6/21.
//
@@ -36,6 +36,10 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, copy) NSString * title;
@property (nonatomic, assign) CGFloat systemHeight;
@property (nonatomic, assign) MessageType msgType;
//地图
@property (nonatomic, assign) CGFloat Longitude;
@property (nonatomic, assign) CGFloat Latitude;
@property (nonatomic, copy) NSString * address;//地址描述
@end
@@ -1,6 +1,6 @@
//
// CustomTUIHistoryModel.m
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/6/21.
//
@@ -1,6 +1,6 @@
//
// CustomTextModel.h
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/6/19.
//
@@ -1,6 +1,6 @@
//
// CustomTextModel.m
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/6/19.
//
@@ -1,6 +1,6 @@
//
// CustomTUIModel.h
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/6/17.
//
@@ -1,6 +1,6 @@
//
// CustomTUIModel.m
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/6/17.
//
@@ -1,6 +1,6 @@
//
// CustomTUIBaseMessageController.h
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/6/12.
//
@@ -9,7 +9,7 @@
NS_ASSUME_NONNULL_BEGIN
@interface CustomTUIBaseMessageController : HQBaseViewController
@interface CustomTUIBaseMessageController : XJBaseViewController
@property(nonatomic, strong) NSString * groupID;
@@ -1,6 +1,6 @@
//
// CustomTUIBaseMessageController.m
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/6/12.
//
@@ -84,7 +84,7 @@
[parmDic setObject:self.groupID forKey:@"groupId"];
JKCQAPI * agreeAPI = [[JKCQAPI alloc] init:self tag:@"HISTORYAPI" NeedToken:@""];
XJPNetAPI * agreeAPI = [[XJPNetAPI alloc] init:self tag:@"HISTORYAPI" NeedToken:@""];
[agreeAPI GetAllHistoryChatRecord:nil];
@@ -134,8 +134,8 @@
}
for (MsgBody *msgBody in model.MsgBody) {
NSLog(@"MsgType: %@", msgBody.MsgType);
NSLog(@"MsgContent Data - title: %@", msgBody.MsgContent.Text);
DLog(@"MsgType: %@", msgBody.MsgType);
DLog(@"MsgContent Data - title: %@", msgBody.MsgContent.Text);
if([msgBody.MsgType isEqualToString:@"TIMTextElem"]) //文本消息
{
@@ -1,6 +1,6 @@
//
// CustomTUIHistoryTable.h
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/6/14.
//
@@ -1,6 +1,6 @@
//
// CustomTUIHistoryTable.m
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/6/14.
//
@@ -1,6 +1,6 @@
//
// CustomAudioCell.h
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/6/14.
//
@@ -1,6 +1,6 @@
//
// CustomAudioCell.m
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/6/14.
//
@@ -1,6 +1,6 @@
//
// CustomDoctorIDTableViewCell.h
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/7/5.
//
@@ -1,6 +1,6 @@
//
// CustomDoctorIDTableViewCell.m
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/7/5.
//
@@ -1,6 +1,6 @@
//
// CustomHealthFileVideoCell.h
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/6/14.
//
@@ -1,6 +1,6 @@
//
// CustomHealthFileVideoCell.m
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/6/14.
//
@@ -1,6 +1,6 @@
//
// CustomHealthReportVideoCell.h
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/6/14.
//
@@ -1,6 +1,6 @@
//
// CustomHealthReportVideoCell.m
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/6/14.
//
@@ -1,17 +1,17 @@
//
// CustomMapMessageCell.h
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/6/12.
//
#import <TIMCommon/TUIBubbleMessageCell.h>
#import <TIMCommon/TUIMessageCell.h>
#import "CustomMapMessageCellData.h"
#import "CustomTUIHistoryModel.h"
@interface CustomMapMessageCell : UITableViewCell
@interface CustomMapMessageCell : TUIBubbleMessageCell
@property (nonatomic, strong) CustomTUIHistoryModel * model;
@end
@@ -1,79 +1,257 @@
//
// CustomMapMessageCell.m
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/6/12.
//
#import "CustomMapMessageCell.h"
#import "XJWeChatManager.h"
#import <SDWebImage/SDImageCache.h>
#import<CommonCrypto/CommonDigest.h>
@interface CustomMapMessageCell ()
@property (nonatomic, strong) UIImageView * heardImage;
@property (nonatomic, strong) UILabel * connetLabel;
@property (nonatomic, strong) UILabel * myTextLabel;
@property (nonatomic, strong) UIImageView * mapImage;
@end
@implementation CustomMapMessageCell
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
[self createUI];
[self createMapUI];
}
return self;
}
- (void)createUI {
self.heardImage = [[UIImageView alloc] init];
self.heardImage.backgroundColor = KRedColor;
[self.contentView addSubview:self.heardImage];
self.heardImage.layer.cornerRadius = 15;
self.heardImage.layer.masksToBounds = true;
[self.heardImage mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(@15);
make.top.mas_equalTo(@8);
make.height.width.mas_equalTo(@30);
}];
self.connetLabel = [[UILabel alloc] init];
self.connetLabel.backgroundColor = KRedColor;
[self.contentView addSubview:self.heardImage];
self.connetLabel.layer.cornerRadius = 10;
self.connetLabel.layer.masksToBounds = true;
self.connetLabel.numberOfLines = 0;
[self.connetLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(self.heardImage.right).offset(8);
make.top.mas_equalTo(@10);
make.width.mas_equalTo(@245.0);
}];
[self.connetLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
- (void)createMapUI {
// 隐藏默认气泡图片,改用白色圆角背景
self.bubbleView.image = nil;
self.container.backgroundColor = KWhiteColor;
self.container.layer.cornerRadius = 8;
self.container.layer.masksToBounds = YES;
self.myTextLabel = [[UILabel alloc] init];
self.myTextLabel.font = SYSTEMFONT(15);
self.myTextLabel.textColor = CFontColor1;
self.myTextLabel.numberOfLines = 0;
[self.container addSubview:self.myTextLabel];
[self.myTextLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_offset(10);
make.top.mas_offset(10);
make.right.mas_offset(-10);
}];
self.mapImage = [[UIImageView alloc] init];
self.mapImage.backgroundColor = KRedColor;
[self.container addSubview:self.mapImage];
[self.mapImage mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.bottom.mas_offset(0);
make.top.mas_equalTo(self.myTextLabel.mas_bottom);
}];
// 长按转发到微信
// TUIChat 框架把长按手势注释掉了,这里重新加上。
// 需要让 container 上已有的 tap 手势等 longPress 失败后再触发,否则 tap 会抢走触摸。
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onLongPress:)];
longPress.minimumPressDuration = 0.5;
[self.container addGestureRecognizer:longPress];
for (UIGestureRecognizer *g in self.container.gestureRecognizers) {
if ([g isKindOfClass:[UITapGestureRecognizer class]]) {
[g requireGestureRecognizerToFail:longPress];
}
}
}
#pragma mark - TUIChat 实时聊天回调
- (void)fillWithData:(CustomMapMessageCellData *)data {
// 不显示名字标签,让白色卡片紧贴顶部(父类 layoutSubviews 用 frame 布局,需在 data 层面关闭)
data.showName = NO;
[super fillWithData:data];
// 清掉父类设回来的气泡图,让 container 白底露出来
self.bubbleView.image = nil;
self.myTextLabel.text = data.text.length > 0 ? data.text : @"我的位置";
[self.mapImage sd_setImageWithURL:[NSURL URLWithString:data.MapPictureImg] placeholderImage:nil];
}
#pragma mark - 历史记录回调
- (void)setModel:(CustomTUIHistoryModel *)model {
_model = model;
self.myTextLabel.text = _model.address.length > 0 ? _model.address : @"我的位置";
NSString * MapPictureImg = [self mapLocationImage:_model.Longitude Withlation:_model.Latitude];
[self.mapImage sd_setImageWithURL:[NSURL URLWithString:MapPictureImg] placeholderImage:nil];
// 历史记录:手动设置头像和名字
self.avatarView.image = [UIImage imageNamed:@"heard_man"];
self.nameLabel.text = @"全科医生";
self.nameLabel.hidden = NO;
if (_model.isSelf) {
self.avatarView.hidden = NO;
[self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.height.width.mas_offset(40);
make.top.mas_equalTo(@10);
make.right.mas_equalTo(self.contentView.mas_right).offset(-10);
}];
self.nameLabel.textAlignment = NSTextAlignmentRight;
[self.nameLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
make.right.mas_equalTo(self.avatarView.mas_left).offset(-10);
make.top.mas_equalTo(@10);
make.width.mas_equalTo(@245.0);
make.height.mas_offset(13);
}];
[self.container mas_remakeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(self.nameLabel.mas_bottom).offset(8);
make.width.mas_offset(245);
make.right.mas_equalTo(self.avatarView.mas_left).offset(-10);
make.height.mas_offset(170);
}];
} else {
self.avatarView.hidden = NO;
[self.avatarView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(@15);
make.top.mas_equalTo(@8);
make.height.width.mas_equalTo(@40);
}];
self.nameLabel.textAlignment = NSTextAlignmentLeft;
[self.nameLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(self.avatarView.mas_right).offset(10);
make.top.mas_equalTo(@10);
make.width.mas_equalTo(@300.0);
make.height.mas_offset(13);
}];
[self.container mas_remakeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(self.avatarView.mas_right).offset(10);
make.width.mas_offset(245);
make.top.mas_equalTo(self.nameLabel.mas_bottom).offset(8);
make.height.mas_offset(170);
}];
}
// 加载头像
NSString * photo = [NSString stringWithFormat:@"%@%@", ResourceAddress, _model.avatar];
photo = [photo stringByReplacingOccurrencesOfString:@"\\" withString:@"/"];
NSString *encodedString3 = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)photo, (CFStringRef)@"!$&'()*+,-./:;=?@_~%#[]", NULL, kCFStringEncodingUTF8));
[self.avatarView sd_setImageWithURL:[NSURL URLWithString:encodedString3] placeholderImage:PLACEHOLD_IMG];
}
#pragma mark - 地图静态图
- (NSString *)mapLocationImage:(CGFloat)longLation Withlation:(CGFloat)lation {
NSString * staciUrl = @"https://restapi.amap.com/v3/staticmap?key=e9926badd26aaa766d13439c88a83f2d";
NSString * mapKey = @"e9926badd26aaa766d13439c88a83f2d";
NSString * loctaionUrl = @"https://a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png";
NSString * needMdString = [NSString stringWithFormat:@"key=%@&location=%f,%f&markers=-1,%@,0:%f,%f&size=700*500&zoom=15124d58f7223ac9738312a8d187a21f2b",mapKey,longLation,lation,loctaionUrl,longLation,lation];
NSString * mapUrl = [NSString stringWithFormat:@"%@&location=%f,%f&markers=-1,%@,0:%f,%f&size=700*500&zoom=15&sig=%@",staciUrl,longLation,lation,loctaionUrl,longLation,lation,[self md5:needMdString]];
return mapUrl;
}
- (NSString *)md5:(NSString *)str
{
const char *cStr = [str UTF8String];
unsigned char result[16];
CC_MD5(cStr, strlen(cStr), result);
return [NSString stringWithFormat:
@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
result[0], result[1], result[2], result[3],
result[4], result[5], result[6], result[7],
result[8], result[9], result[10], result[11],
result[12], result[13], result[14], result[15]
];
}
#pragma mark - 长按转发微信
- (void)onLongPress:(UILongPressGestureRecognizer *)gesture {
if (gesture.state != UIGestureRecognizerStateBegan) return;
if (![[XJWeChatManager sharedManager] isWeChatInstalled]) {
[EasyTextView showErrorText:@"未安装微信"];
return;
}
UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
[alert addAction:[UIAlertAction actionWithTitle:@"转发到微信" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[self shareToWeChat];
}]];
[alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]];
UIViewController *topVC = [self topViewController];
[topVC presentViewController:alert animated:YES completion:nil];
}
- (void)shareToWeChat {
NSString *address;
CGFloat lat = 0, lng = 0;
NSString *imageKey;
// 实时聊天数据
CustomMapMessageCellData *data = (CustomMapMessageCellData *)self.messageData;
if ([data isKindOfClass:[CustomMapMessageCellData class]]) {
address = data.text.length > 0 ? data.text : @"我的位置";
lat = data.latitude;
lng = data.longitude;
imageKey = data.MapPictureImg;
}
// 历史记录数据
else if (_model) {
address = _model.address.length > 0 ? _model.address : @"我的位置";
lat = _model.Latitude;
lng = _model.Longitude;
imageKey = [self mapLocationImage:_model.Longitude Withlation:_model.Latitude];
} else {
return;
}
NSString *encodedAddress = [address stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSString *mapUrl = [NSString stringWithFormat:@"https://uri.amap.com/marker?position=%f,%f&name=%@",
lng, lat, encodedAddress ?: @"位置"];
UIImage *thumb = [[SDImageCache sharedImageCache] imageFromCacheForKey:imageKey];
[[XJWeChatManager sharedManager] shareWebpageWithTitle:address
desc:[NSString stringWithFormat:@"经度:%.6f 纬度:%.6f", lng, lat]
webpageUrl:mapUrl
thumbImage:thumb
toScene:0
completion:^(BOOL success, NSString * _Nullable errorMsg) {
if (!success && errorMsg.length > 0) {
[EasyTextView showErrorText:errorMsg];
}
}];
}
- (UIViewController *)topViewController {
UIViewController *rootVC = [UIApplication sharedApplication].keyWindow.rootViewController;
while (rootVC.presentedViewController) {
rootVC = rootVC.presentedViewController;
}
if ([rootVC isKindOfClass:[UINavigationController class]]) {
return [(UINavigationController *)rootVC topViewController];
}
if ([rootVC isKindOfClass:[UITabBarController class]]) {
UIViewController *selected = [(UITabBarController *)rootVC selectedViewController];
if ([selected isKindOfClass:[UINavigationController class]]) {
return [(UINavigationController *)selected topViewController];
}
return selected;
}
return rootVC;
}
@end
@@ -1,6 +1,6 @@
//
// CustomReviceTableViewCell.h
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/7/5.
//
@@ -1,6 +1,6 @@
//
// CustomReviceTableViewCell.m
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/7/5.
//
@@ -1,6 +1,6 @@
//
// CustomSystemImageCell.h
// EscortProject
// XinjiangProject
//
// Created by Apple on 2024/6/14.
//

Some files were not shown because too many files have changed in this diff Show More