需求评审

需求评审

用例评审

技术调研

列出项目中,可能用到的技术点,做好调研工作。

定制相机UI

iOS在切换摄像头时,session可能导致的问题 - 习七

文件上传工具

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//存储本地/上传图片
-(void)upload
{
    UIImage *img = self.photo;
    NSString *path = [NSTemporaryDirectory() stringByAppendingFormat:@"%@.png",[NSString getUniqueStrByUUID]];
       //把图片直接保存到指定的路径(同时应该把图片的路径imagePath存起来,下次就可以直接用来取)
       NSData *photoAddedWatermarkData = UIImageJPEGRepresentation(img, 1);
       [photoAddedWatermarkData writeToFile:path atomically:YES];

    NSString * serverUrl = [JHLiveBaseRequest addUrlProtocolAndEnvWithStr:@"fileserver.iuoooo.com/Jinher.JAP.BaseApp.FileServer.SV.FileSV.svc/UploadMobileFile"];

    NSString* Environment = [JHUrlStringManager netEnvironment];
    if (Environment.length == 0){
        serverUrl = [JHLiveBaseRequest addUrlProtocolAndEnvWithStr:@"upfileserver.iuoooo.com/Jinher.JAP.BaseApp.FileServer.SV.FileSV.svc/UploadMobileFile"];
    }

    NSDictionary *data = @{@"uploadData":img,
                           @"uploadDataName":path.lastPathComponent,
                           //                           @"uploadDataPath":model.photoPath,
                           @"uploadDataType":@"Image",
                           @"uploadDataId":[NSString getUniqueStrByUUID],
                           };
    [MBProgressHUD showHUDText:@"正在上传..." animated:NO];
    [JHRoutingComponent openURL:@"Technology://UploadComponent:(uploadDatas:callBack:)" withParameter:@{@"datasArray":@[data],@"serverUrlStr":serverUrl,@"isSingleReturn": @YES, @"isCallBackSchedule": @YES} callBack:^(NSDictionary *resultDic) {
        ///上传成功
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            [MBProgressHUD hideHUDanimated:YES];
            if ([resultDic.allKeys containsObject:@"returnDicArray"]) {
                NSArray * dicArray = resultDic[@"returnDicArray"];
                for (NSUInteger i = 0; i < dicArray.count; i++) {
                    NSDictionary * dic = dicArray[i];
                    if ([dic.allKeys containsObject:@"FilePath"]) {
                        NSString * urlHost = [JHLiveBaseRequest addUrlProtocolAndEnvWithStr:@"fileserver.iuoooo.com/Jinher.JAP.BaseApp.FileServer.UI/FileManage/GetFile?fileURL="];
                        NSString *imgUrl = [[NSString alloc] initWithFormat:@"%@%@",urlHost,dic[@"FilePath"]];
                        [self submitPhoto:path url:imgUrl];
                    }
                }
            }
        }];
    }];
}

金和浏览器

在流程交互上,需要push方式展示金和浏览器,这样在调用diss之后,就可以将整合导航控制器关闭。

1
2
3
4
5
//TODO: 金和浏览器
NSString *htmlUrl = [NSString stringWithFormat:@"%@%@",baseUrl,mcn];
//    [JHWebviewManager pushWebViewControllerWithURL:htmlUrl isShowReturnButtonAndCloseButton:YES title:nil andParentViewController:self];
UIViewController *web = [JHWebviewManager getWebViewControllerWithURL:htmlUrl isShowReturnButtonAndCloseButton:YES title:nil andHasTabbar:NO];
[self.navigationController pushViewController:web animated:NO];

webCore拦截器

  1. js 调用脚本:

    1
    
       jhoabrowser://sendMorningCheckResults?args=xxx&tag=xxx
    

    JS方法: sendMorningCheckResults

  2. 注册拦截方法

    1
    2
    
       //晨检机
       DECLARE_NODE_MAP(sendMorningCheckResults, WVMornInspecter)
  3. 实现原生响应类: WVMornInspecter

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    
       - (BOOL)webViewShouldStartLoadRequest
       {
           // 获取类名
           id mornCls = NSClassFromString(@"JHMornInspecterController");
           if (mornCls) {
               //初始化
               UIViewController *morn = ((UIViewController * (*)(id, SEL))objc_msgSend)(mornCls,NSSelectorFromString(@"shared"));
               //激活晨检机 ,js 回参:self.businessJson[@"args"]
               NSDictionary *args = self.businessJson[@"args"];
               ((void (*)(id, SEL, id))objc_msgSend)(morn,NSSelectorFromString(@"startMornInspecter:"),args);
           }
    
           return NO;
       }

获取门店Id 和orgId

1
2
NSString *orgId = [storeDic objectForKey:@"orgId"];
NSString *storeId = [storeDic objectForKey:@"storeId"];

业务开发

开发设计

产出时序图,类图,活动图,甘特图

引导页网页

在页面中实现的相关业务。

  • 人脸识别验证
  • 提交手部/着装卫生结果
  • 获取验证配置条件(健康码/答题)
  • 调用h5界面
  • 响应JS原生交互
  • 激活远程晨检机

第一步:人脸识别 [2/2]

  • 是否需要采集

    true:人脸识别 — 自查拍照

    false:采集人脸 — 自查拍照 (采集成功之后,直接进入拍照,不做人脸识别操作)

DONE 人脸采集

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
-(void)faceCatch
{
    __weak typeof(self) weakSelf = self;
    [JHFaceRecognition goToFaceCatchPageBlock:^(BOOL success, BOOL backState, NSString *jsonString) {
        NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
        NSError *err;
        NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData
                                                            options:NSJSONReadingMutableContainers
                                                              error:&err];
        if (!backState) {
            if (success) {
                // 采集成功
                NSString *faceUrl = [dic objectForKey:@"faceUrl"];
                [weakSelf startCamera:faceUrl];
            }else{
                // 验证超时
                [MBProgressHUD displayHudError:@"人脸采集失败"];
            }
        }
    } orgID:[JHLiveBaseRequest orgIdInAppInfo]];
}

旧版采集人脸工具没有返回人脸图片,需要扩展人脸采集工具

DONE 获取人脸图片

在联调代码人脸采集的定位到实现类和关键代码

第一步先定位到采集人脸代码实现: FaceActionViewController.m

第二步定位 完成按钮,回调逻辑的实现

1
2
3
4
5
6
7
8
9
-(void)completeClick{
    if (self.vertifySuccess) {
        NSString *json = [self.faceModel toJSONString];
        self.handleFaceBlock(self.faceModel.state,0,json);
        [self.navigationController dismissViewControllerAnimated:YES completion:nil];
    }else{
        //略
    }
}

从第三行知道,API 中回调 json 数据来自在 faceModel 属性,需要在 FaceModel 类中新增想要得到的数据,这里新增人脸图片。

在上面 faceModel 实例的属性 faceUrl 需要在 FaceBaseModel.h 新增:

1
2
3
4
5
@interface FaceModel : JSONModel
@property(nonatomic , assign)   int state;
...
@property (strong, nonatomic)   NSString *faceUrl;
@end

然后,找到给新增属性赋值的地方,即 采集人脸接口 RegisterFaceInfo 回调成功时,将入参: filePath 直接赋值给 faceUrl

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
if (faceModel.IsSuccess) {
    //注册成功
    _wks.vertifySuccess = YES;
    _wks.layer.strokeColor = HEX_COLOR(0x2CD773).CGColor;
    _wks.actionLabel.textColor = HEX_COLOR(0x2CD773);
    _wks.actionLabel.text = @"采集成功";
    [_wks.completeButton setTitle:@"完成" forState:UIControlStateNormal];
    _wks.faceModel.state = 1;
    _wks.faceModel.data = faceModel;
    _wks.faceModel.faceUrl = filePath;
}

这样,在点击完成按钮时,会将新增的人脸图片地址,转为json 数据,回传给人脸采集接口。可以解析拿到 faceUrl

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
if (!backState) {
    if (success) {
        // 采集成功
        NSString *faceUrl = [dic objectForKey:@"faceUrl"];
        [weakSelf startCamera:faceUrl];
    }else{
        // 验证超时
        [MBProgressHUD displayHudError:@"人脸采集失败"];
    }
}

DONE 人脸识别

  • 调用人脸识别
  • 调用晨检步骤

第二步:手部/着装卫生 [3/3]

  • 后置拍照UI
  • 上传图片
  • 提交卫生信息

第三步:晨检 [0/0]

获取晨检配置 [2/2]

  • 读取后端配置
  • 确定验证方案 [3/3]
    • 健康码解锁
    • 答题解锁
    • 健康码+答题解锁

答题+健康码

H5答题/健康码

激活晨检机

通过webCore交互,调用原生方法激活晨检机

智能设备

需求:替换 设备类型设备场景类型 和新接口

功能说明新接口旧接口
UI变更设备场景类型设备类型
设备列表h5页面兼容h5页面
设备场景类型GetIOTDeviceSceneListGetIntelligentDeviceTypeSettingNew
保存设备SaveIntelligentDeviceInfo
更新设备SaveIntelligentDeviceInfo
删除设备DeleteIntelligentDevice

重写设备场景类型

  • 实现接口GetIOTDeviceSceneList
  • 兼容添加设备UI, 删除多余cell

重写保存/更新

  • 实现接口:SaveIntelligentDeviceInfo
  • 兼容更新设备UI, 删除多余cell

删除设备兼容

  • 删除接口实现
  • 实现交互逻辑UI

提测发布

平台设置 [3/3]

  • 依赖库

    智能设备:晨检机分支

    webCore: master 分支

    人脸识别: master 分支

  • 反射类

    晨检自查:JHRefelctMornInspecterController

    1
    2
    3
    4
    
       UIViewController *morn = ((UIViewController * (*)(id, SEL))objc_msgSend)(mornCls,NSSelectorFromString(@"shared"));
                   [self.navigationController presentingViewController];
                   UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:morn];
                   [[UIViewController topMostController] presentViewController:nav animated:YES completion:nil];
  • 配置功能入口(井盖) 5寸晨检自查:JHRefelctMornInspecterController

提测测试

发布