实战项目——智慧社区(二)之 物业管理

分页

用于分页封装的实体类

@Data
public class PageVO {
    private Long totalCount;
    private Long pageSize;
    private Long totalPage;
    private Long currPage;
    private List list;
}

分页的相关配置 

package com.qcby.community.configuration;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class PageConfiguration {

    @Bean
    public PaginationInterceptor paginationInterceptor(){
        return new PaginationInterceptor();
    }
}

增删改查的实现思路 

对于传入参数,如果有,但是参数不多,只有一个,直接接收;如果参数较多,应将其传入字段封装在一个实体类中。对于get请求,用@PathVariable接收,对于非get请求,用@RequestBody接收。

对于返回参数,如果与数据单表中的字段可以进行一一映射,不需要考虑封装,直接返回;如果无法在单表中进行一一映射,则需要根据返回参数进行实体类封装。

对于单表的增删改查,mybatiaPlus提供了相应的操作,对于多表则需要手写sql语句

1、小区管理

①小区搜索和查询

传入参数

{
    "page": 1,
    "limit": 10,
    "communityId": "",
    "communityName": ""
}

返回参数

{
    "msg": "操作成功",
    "code": 200,
    "data": {
        "totalCount": 8,
        "pageSize": 10,
        "totalPage": 1,
        "currPage": 1,
        "list": [
            {
                "communityId": 19,
                "communityName": "北清云际",
                "termCount": 33,
                "seq": 190,
                "creater": "admin",
                "createTime": "2023-07-18 00:41:20",
                "lng": 116.298904,
                "lat": 40.091644,
                "personCnt": 1
            },
            {
                "communityId": 17,
                "communityName": "天龙苑",
                "termCount": 10,
                "seq": 170,
                "creater": "admin",
                "createTime": "2023-07-18 00:38:06",
                "lng": 116.36206,
                "lat": 40.088108,
                "personCnt": 0
            }
        ]
    }

实现思路:由于返回list中在community表中没有personCnt字段,因此需要封装一个CommunityVO类用于数据的返回。同时由于mybtisPlus中并没有现成的sql用于根据community_id查询相应的居民人数,因此需要编写sql用来查询每个community对于的人数personCnt

CommunityVO类

@Data
public class CommunityVO {
    private Integer communityId;
    private String communityName;
    private Integer termCount;
    private Integer seq;
    private String creater;
    private Date createTime;
    private Float lng;
    private Float lat;
    private Integer personCnt;
}

controller

/**
     * 获取小区的所有信息,分页条件查询
     * @return
     */
    @GetMapping("/list")
    public Result getList(CommunityListForm communityListForm){
        PageVO pageVO = this.communityService.communityList(communityListForm);
        return Result.ok().put("data", pageVO);
    }

service

 @Override
    public PageVO communityList(CommunityListForm communityListForm) {
        Page<Community> page = new Page<>(communityListForm.getPage(), communityListForm.getLimit());
        QueryWrapper<Community> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(communityListForm.getCommunityName()),"community_name", communityListForm.getCommunityName());
        Page<Community> resultPage = this.communityMapper.selectPage(page, queryWrapper);
        PageVO pageVO = new PageVO();
        List<CommunityVO> list = new ArrayList<>();
        for (Community record : resultPage.getRecords()) {
            CommunityVO communityVO = new CommunityVO();
            BeanUtils.copyProperties(record, communityVO);
            communityVO.setPersonCnt(this.personMapper.getCountByCommunityId(record.getCommunityId()));
            list.add(communityVO);
        }
        pageVO.setList(list);
        pageVO.setTotalCount(resultPage.getTotal());
        pageVO.setPageSize(resultPage.getSize());
        pageVO.setCurrPage(resultPage.getCurrent());
        pageVO.setTotalPage(resultPage.getPages());
        return pageVO;
    }

 根据communityId查询居民人数的mapper

@Select({
            "select count(*) from person where community_id = #{communityId} "
    })
    Integer getCountByCommunityId(Integer communityId);

界面

 

②添加小区

传入参数

{
    "communityName": "test"
    "lat": "1"
    "lng": "1"
    "seq": 1
    "termCount": "1"
}

返回参数

 {
    "msg": "操作成功",
    "code": 200
}

 controller

    /**
     * 添加小区
     * @param community
     * @param session
     * @return
     */
    @LogAnnotation("添加小区")
    @PostMapping("/add")
    public Result add(@RequestBody Community community, HttpSession session){
        User user = (User)session.getAttribute("user");
        community.setCreater(user.getUsername());
        boolean save = this.communityService.save(community);
        if(!save) return Result.error("小区添加失败");
        return Result.ok();
    }

界面

 

③通过id查询小区

传入参数

1

返回参数

{
    "msg": "操作成功",
    "code": 200,
    "data": {
        "communityId": 19,
        "communityName": "北清云际",
        "termCount": 33,
        "seq": 190,
        "lng": 116.298904,
        "lat": 40.091644
     }
}

controller

    /**
     * 修改的回显操作
     * @param id
     * @return
     */
    @GetMapping("/info/{id}")
    public Result info(@PathVariable("id") Integer id){
        Community community = this.communityService.getById(id);
        if(community == null) return Result.error("小区不存在");
        return Result.ok().put("data", community);
    }

 ④修改小区

传入参数

{
    "communityId": 21,
    "communityName": "1",
    "termCount": "12",
    "lng": "12",
    "lat": "12",
    "seq": 210
}

返回参数

{
    "msg": "操作成功",
    "code": 200
}

controller

     /**
     * 修改小区信息
     * @param community
     * @return
     */
    @LogAnnotation("编辑小区")
    @PutMapping("/edit")
    public Result edit(@RequestBody Community community){
        boolean updateById = this.communityService.updateById(community);
        if(!updateById) return Result.error("编辑小区失败");
        return Result.ok();
    }

界面

 

⑤删除小区

传入参数

[
    21,
    20
]

返回参数

{
    "msg": "操作成功",
    "code": 200
}

controller

 /**
     * 删除小区,同时删除相关表中的信息
     * @param ids
     * @return
     */
    @LogAnnotation("删除小区")
    @DeleteMapping("/del")
    @Transactional    //事务管理
    public Result del(@RequestBody Integer[] ids){
        try{
            QueryWrapper<Camera> cameraQueryWrapper = new QueryWrapper<>();
            cameraQueryWrapper.in("community_id", ids);
            boolean remove1 = this.cameraService.remove(cameraQueryWrapper);
//            if(!remove1) return Result.error("小区摄像头删除失败");
            QueryWrapper<InOutRecord> inOutRecordQueryWrapper = new QueryWrapper<>();
            inOutRecordQueryWrapper.in("community_id", ids);
            boolean remove2 = this.inOutRecordService.remove(inOutRecordQueryWrapper);
//            if(!remove2) return Result.error("小区出入记录删除失败");
            QueryWrapper<ManualRecord> manualRecordQueryWrapper = new QueryWrapper<>();
            manualRecordQueryWrapper.in("community_id", ids);
            boolean remove3 = this.manualRecordService.remove(manualRecordQueryWrapper);
//            if(!remove3) return Result.error("小区访客记录删除失败");
            QueryWrapper<Person> personQueryWrapper = new QueryWrapper<>();
            personQueryWrapper.in("community_id", ids);
            boolean remove4 = this.personService.remove(personQueryWrapper);
//            if(!remove4) return Result.error("小区居民删除失败");
            boolean remove5 = this.communityService.removeByIds(Arrays.asList(ids));
//            if(!remove5) return Result.error("小区删除失败");
        }catch(Exception e){
            e.printStackTrace();
            return Result.error("小区删除失败");
        }
        return Result.ok();
    }

 ⑥摄像头管理

查询摄像头、添加摄像头、通过id查询摄像头、修改摄像头、删除摄像头,其操作和上述的小区操作相似,这里不再举例

摄像头(camera)表设计

界面

2、居民管理

查询和搜索居民、查询小区列表、添加居民、修改居民、删除居民,其操作和上述的小区操作相似,这里不再详写

①人脸采集

这里选择调用腾讯人脸识别的API接口进行人脸检测与上传,因此在人脸采集之前需要做一些准备工作。

腾讯人脸识别API接口申请

登录腾讯云,搜索访问管理,创建密钥

对应 application.yml 中的

secretId: AKID3CXqCeGxiOE1snomp9ThopkZIyXypZEl
 secretKey: c7awCRbecXL0b9e4Sk2HVyfVONVk4VvF

搜索人脸识别,创建人员库

 

对应 application.yml 中的 

 groupId: 1001

相关配置

引入依赖

         <dependency>
            <groupId>com.tencentcloudapi</groupId>
            <artifactId>tencentcloud-sdk-java</artifactId>
            <version>3.1.62</version>
        </dependency>

配置文件

upload:
  face: D:/community/upload/face/
  excel: D:/community/upload/excel/
  urlPrefix: http://localhost:8282/
plateocr:
  secretId: AKID3CXqCeGxiOE1snomp9ThopkZIyXypZEl
  secretKey: c7awCRbecXL0b9e4Sk2HVyfVONVk4VvF
  serverIp: iai.tencentcloudapi.com
  area: ap-guangzhou
  groupId: 1001
  used: true
  passPercent: 80

serverIp 和 area 不需要修改,used 表示启用,passPercent 表示识别率,比如 80 表示图片相似度 80即认为通过 ;同时配置人脸图片上传的在本地的位置

 人脸识别参数配置

package com.qcby.community.configuration;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@ConfigurationProperties(value="plateocr")
@Component
@Data
@ApiModel(value = "ApiConfiguration",description = "人脸识别参数描述")
public class ApiConfiguration {

    @ApiModelProperty("人脸识别secretId")
    private String secretId;
    @ApiModelProperty("人脸识别secretKey")
    private String secretKey;
    //	服务器ip
    @ApiModelProperty("人脸识别服务器ip")
    private String serverIp;
    //	服务器区域
    @ApiModelProperty("人脸识别服务器区域")
    private String area;
    //	默认分组
    @ApiModelProperty("人脸识别默认分组")
    private String groupId;
    //	用户id前缀
    @ApiModelProperty("人脸识别用户id前缀")
    private String personIdPre;
    //	随机数
    @ApiModelProperty("人脸识别随机数")
    private String nonceStr;
    //	是否使用
    @ApiModelProperty("人脸识别,是否启用人脸识别功能")
    private boolean used = false;
    //	识别准确率
    @ApiModelProperty("人脸识别比对准确度,如符合80%就识别通过")
    private float passPercent;

}
文件映射的配置
package com.qcby.community.configuration;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
    @Value("${upload.face}")
    String face;
    @Value("${upload.excel}")
    String excel;

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/community/upload/face/**").addResourceLocations("file:"+face);
        registry.addResourceHandler("/community/upload/excel/**").addResourceLocations("file:"+excel);
    }
}

传入参数

{
    "personId": 98,
    "extName": "png",
    "fileBase64": "iVBORw0KGgoAAAANSUhEUgAAAJsAAAC4CAYAAAD0WZ4UAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJ8pt02jBn6wUmcy/39/xgi2nSFeQGzAAAAAElFTkSuQmCC"
}

返回参数

{
    "msg": "操作成功",
    "code": 200
}

实现思路

①进行程序严谨性判断:根据personId查询person信息,首先判断居民存在与否,然后判断居民是否已经录入了人脸,最后判断居民上传的图片是否为Base64编码的图片,有一个不符合都不进行人脸的录入

②调用腾讯API接口进行人脸检测,判断上传的图片是否为一张人脸

③将人脸图片上传到服务器,并且更新person表中人脸图片的地址以及识别状态

人脸识别的实现
    @Autowired
    private ApiConfiguration apiConfiguration;
    @Value("${upload.face}")
    private String face;
    @Value("${upload.urlPrefix}")
    private String urlPrefix;

    /**
     * 录入人脸信息
     * @param personFaceForm
     * @return
     */
    @LogAnnotation("人脸采集")
    @PostMapping("/addPerson")
    public Result addPerson(@RequestBody PersonFaceForm personFaceForm){
        Person person = this.personService.getById(personFaceForm.getPersonId());
        //程序严谨性判断
        if(person == null){
            return Result.error("居民不存在");
        }
        if(person.getState() == 2){
            return Result.error("人脸识别已通过,不需要重复识别");
        }
        if(personFaceForm.getFileBase64() == null || personFaceForm.getFileBase64().equals("")){
            return Result.error("请上传Base64编码的图片");
        }
        //人脸检测
        if(apiConfiguration.isUsed()){
            //调用腾讯API人脸识别
            String faceId = newPerson(personFaceForm,person.getUserName());
            if(faceId == null){
                return Result.error("人脸识别失败");
            }
            if (faceId != null) {
                //生成头像访问路径
                String filename = faceId + "." + personFaceForm.getExtName();
                String faceUrl = urlPrefix + "community/upload/face/" + filename;
                person.setFaceUrl(faceUrl);
                person.setState(2);
                //更新人脸识别状态及图片地址
                this.personService.updateById(person);
                return Result.ok();
            }

//            //模拟人脸识别
//            //生成模拟id
//            String faceId = RandomUtil.getBitRandom();
//            String faceBase = personFaceForm.getFileBase64().substring(0, 60);
//            // 如果不是头像
//            if(faceBase.equals("iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAAAXNSR0IArs4c")) {
//                return Result.error("人脸识别失败");
//            }
//            //存储头像
//            String filename = faceId + "." + personFaceForm.getExtName();
//            String savePath = face + filename;
//            try {
//                Base64Util.decoderBase64File(personFaceForm.getFileBase64(), savePath);
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//            //生成头像访问路径
//            String faceUrl = urlPrefix + "community/upload/face/" + filename;
//            person.setFaceUrl(faceUrl);
//            person.setState(2);
//            person.setFaceBase(faceBase);
//            //更新人脸识别状态及图片地址
//            this.personService.updateById(person);
//            return Result.ok();
        }
        return Result.error("未开启人脸识别");
    }

    private String newPerson(PersonFaceForm vo,String personName) {
        String faceId = null;
        String faceBase64 = vo.getFileBase64();
        String extname = vo.getExtName();
        String personId = vo.getPersonId()+"";
        String savePath = face;
        if (faceBase64!=null && !faceBase64.equals("")) {
            FaceApi faceApi = new FaceApi();
            RootResp resp = faceApi.newperson(apiConfiguration, personId, personName, faceBase64);
            if(resp.getRet()==0) {
                JSONObject data = JSON.parseObject(resp.getData().toString());
                faceId = data.getString("FaceId");
                if(faceId!=null) {
                    String filename = faceId + "." + extname;
                    savePath += filename;
                    try {
                        Base64Util.decoderBase64File(faceBase64, savePath);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            else {
                return faceId;
            }
        }
        return faceId;
    }
FaceApi人脸识别工具类
package com.qcby.community.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.qcby.community.configuration.ApiConfiguration;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.iai.v20180301.IaiClient;
import com.tencentcloudapi.iai.v20180301.models.*;
import org.apache.log4j.Logger;

public class FaceApi {

    private Logger logger = Logger.getLogger(FaceApi.class);

    //人脸分析
    public RootResp detectFace(ApiConfiguration config, String url) {
        RootResp result = new RootResp();
        try{
            Credential cred = new Credential(config.getSecretId(), config.getSecretKey());
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint(config.getServerIp());
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            IaiClient client = new IaiClient(cred, config.getArea(), clientProfile);
            JSONObject paramObj = new JSONObject();
            paramObj.put("Url", url);
            paramObj.put("MaxFaceNum",1);
            paramObj.put("MinFaceSize",34);
            paramObj.put("NeedFaceAttributes",0);
            paramObj.put("NeedQualityDetection",1);
            DetectFaceRequest req = DetectFaceRequest.fromJsonString(paramObj.toJSONString(),DetectFaceRequest.class);
            DetectFaceResponse resp = client.DetectFace(req);
            result.setData(DetectFaceResponse.toJsonString(resp));
        } catch (TencentCloudSDKException e) {
            result.setRet(-1);
            result.setMsg(e.toString());
            logger.error(e.toString());
        }
        logger.info(result);
        return result;
    }

    //添加个体
    public RootResp newperson(ApiConfiguration config, String personId, String personName, String image) {
        RootResp result = new RootResp();
        try{
            //设置凭证和连接信息
            // 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密
            Credential cred = new Credential(config.getSecretId(), config.getSecretKey());
            HttpProfile httpProfile = new HttpProfile();
            // 实例化一个http选项,可选的,没有特殊需求可以跳过
            //httpProfile.setEndpoint("iai.tencentcloudapi.com");
            httpProfile.setEndpoint(config.getServerIp());
            // 实例化一个client选项,可选的,没有特殊需求可以跳过
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            // 实例化要请求产品的client对象,clientProfile是可选的
            IaiClient client = new IaiClient(cred, config.getArea(), clientProfile);
            JSONObject paramObj = new JSONObject();
            paramObj.put("GroupId", config.getGroupId());
            paramObj.put("PersonId", config.getPersonIdPre() + personId);
            paramObj.put("PersonName", personName);
            paramObj.put("Image", image);
            //发送请求并获取响应
            CreatePersonRequest req = CreatePersonRequest.fromJsonString(paramObj.toJSONString(), CreatePersonRequest.class);
            CreatePersonResponse resp = client.CreatePerson(req);
            result.setData(CreatePersonResponse.toJsonString(resp));
        } catch (TencentCloudSDKException e) {
            result.setRet(-1);
            result.setMsg(e.toString());
            logger.error(e.toString());
        }
        logger.info(result);
        return result;
    }

    //删除个体
    public RootResp delperson(ApiConfiguration config, String personId) {
        RootResp result = new RootResp();
        try{
            Credential cred = new Credential(config.getSecretId(), config.getSecretKey());
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint(config.getServerIp());
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            IaiClient client = new IaiClient(cred, config.getArea(), clientProfile);
            JSONObject paramObj = new JSONObject();
            paramObj.put("PersonId", config.getPersonIdPre() + personId);
            DeletePersonRequest req = DeletePersonRequest.fromJsonString(paramObj.toJSONString(), DeletePersonRequest.class);
            DeletePersonResponse resp = client.DeletePerson(req);
            result.setData(DeletePersonResponse.toJsonString(resp));
        } catch (TencentCloudSDKException e) {
            result.setRet(-1);
            result.setMsg(e.toString());
            logger.error(e.toString());
        }
        logger.info(result);
        return result;
    }

    //增加人脸
    public RootResp addface(ApiConfiguration config, String personId, String image) {
        RootResp result = new RootResp();
        try{
            Credential cred = new Credential(config.getSecretId(), config.getSecretKey());
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint(config.getServerIp());
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            IaiClient client = new IaiClient(cred, config.getArea(), clientProfile);
            JSONObject paramObj = new JSONObject();
            JSONArray images = new JSONArray();
            images.add(image);
            paramObj.put("PersonId", config.getPersonIdPre() + personId);
            paramObj.put("Images", images);
            CreateFaceRequest req = CreateFaceRequest.fromJsonString(paramObj.toJSONString(), CreateFaceRequest.class);
            CreateFaceResponse resp = client.CreateFace(req);
            result.setData(CreateFaceResponse.toJsonString(resp));
        } catch (TencentCloudSDKException e) {
            result.setRet(-1);
            result.setMsg(e.toString());
            logger.error(e.toString());
        }
        logger.info(result);
        return result;
    }

    //删除人脸
    public RootResp delface(ApiConfiguration config, String personId, String faceId) {
        RootResp result = new RootResp();
        try{
            Credential cred = new Credential(config.getSecretId(), config.getSecretKey());
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint(config.getServerIp());
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            IaiClient client = new IaiClient(cred, config.getArea(), clientProfile);
            JSONObject paramObj = new JSONObject();
            JSONArray faces = new JSONArray();
            faces.add(faceId);
            paramObj.put("PersonId", config.getPersonIdPre() + personId);
            paramObj.put("FaceIds", faces);
            DeleteFaceRequest req = DeleteFaceRequest.fromJsonString(paramObj.toJSONString(), DeleteFaceRequest.class);
            DeleteFaceResponse resp = client.DeleteFace(req);
            result.setData(DeleteFaceResponse.toJsonString(resp));
        } catch (TencentCloudSDKException e) {
            result.setRet(-1);
            result.setMsg(e.toString());
            logger.error(e.toString());
        }
        logger.info(result);
        return result;
    }

    //人脸验证
    public RootResp faceVerify(ApiConfiguration config, String personId, String image) {
        RootResp result = new RootResp();
        try{
            Credential cred = new Credential(config.getSecretId(), config.getSecretKey());
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint(config.getServerIp());
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            IaiClient client = new IaiClient(cred, config.getArea(), clientProfile);
            JSONObject paramObj = new JSONObject();
            paramObj.put("PersonId", config.getPersonIdPre() + personId);
            paramObj.put("Image", image);
            VerifyFaceRequest req = VerifyFaceRequest.fromJsonString(paramObj.toJSONString(), VerifyFaceRequest.class);
            VerifyFaceResponse resp = client.VerifyFace(req);
            result.setData(VerifyFaceResponse.toJsonString(resp));
        } catch (TencentCloudSDKException e) {
            result.setRet(-1);
            result.setMsg(e.toString());
            logger.error(e.toString());
        }
        logger.info(result);
        return result;
    }

    //人员搜索按库返回
    public RootResp searchPersonsReturnsByGroup(ApiConfiguration config, String image) {
        RootResp result = new RootResp();
        try{
            Credential cred = new Credential(config.getSecretId(), config.getSecretKey());
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint(config.getServerIp());
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            IaiClient client = new IaiClient(cred, config.getArea(), clientProfile);
            JSONObject paramObj = new JSONObject();
            paramObj.put("GroupIds", new String[] {config.getGroupId()});
            paramObj.put("Image", image);
            //最多返回的最相似人员数目
            paramObj.put("MaxPersonNumPerGroup", 5);
            //返回人员具体信息
            paramObj.put("NeedPersonInfo", 1);
            //最多识别的人脸数目
            paramObj.put("MaxFaceNum", 1);
            SearchFacesReturnsByGroupRequest req = SearchFacesReturnsByGroupRequest.fromJsonString(paramObj.toJSONString(), SearchFacesReturnsByGroupRequest.class);
            SearchFacesReturnsByGroupResponse resp = client.SearchFacesReturnsByGroup(req);
            result.setData(VerifyFaceResponse.toJsonString(resp));
        } catch (TencentCloudSDKException e) {
            result.setRet(-1);
            result.setMsg(e.toString());
            logger.error(e.toString());
        }
        logger.info(result);
        return result;
    }
}
 RootResp人脸识别响应类
package com.qcby.community.util;

import com.alibaba.fastjson.JSON;

public class RootResp {
    private int ret = 0;

    public int getRet() {
        return this.ret;
    }

    public void setRet(int ret) {
        this.ret = ret;
    }

    private String msg;

    public String getMsg() {
        return this.msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    private Object data;

    public Object getData() {
        return this.data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return JSON.toJSONString(this);
    }
}
Base64Util编码转换工具类
package com.qcby.community.util;

import org.apache.commons.codec.binary.Base64;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

public class Base64Util {
    /**
     * 将二进制数据编码为BASE64字符串
     *
     * @param binaryData
     * @return
     */
    public static String encode(byte[] binaryData) {
        try {
            return new String(Base64.encodeBase64(binaryData), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            return null;
        }
    }

    /**
     * 将BASE64字符串恢复为二进制数据
     *
     * @param base64String
     * @return
     */
    public static byte[] decode(String base64String) {
        try {
            return Base64.decodeBase64(base64String.getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            return null;
        }
    }

    /**
     * 将文件转成base64 字符串
     *
     *  path文件路径
     * @return *
     * @throws Exception
     */

    public static String encodeBase64File(String path) throws Exception {
        File file = new File(path);
        FileInputStream inputFile = new FileInputStream(file);
        byte[] buffer = new byte[(int) file.length()];
        inputFile.read(buffer);
        inputFile.close();
        return encode(buffer);
    }
    //读取网络图片
    public static String encodeBase64URLFile(String path) throws Exception {
        URL url = new URL(path);
        HttpURLConnection conn = (HttpURLConnection)url.openConnection();
        conn.setRequestMethod("GET");
        conn.setConnectTimeout(5*1000);
        InputStream is = conn.getInputStream();
        byte[] data = readInputStream(is);
        is.close();
        conn.disconnect();
        return encode(data);
    }
    public static byte[] readInputStream(InputStream inStream) throws Exception{
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        //创建一个Buffer字符串
        byte[] buffer = new byte[1024];
        //每次读取的字符串长度,如果为-1,代表全部读取完毕
        int len = 0;
        //使用一个输入流从buffer里把数据读取出来
        while( (len=inStream.read(buffer)) != -1 ){
            //用输出流往buffer里写入数据,中间参数代表从哪个位置开始读,len代表读取的长度
            outStream.write(buffer, 0, len);
        }
        //关闭输入流
        inStream.close();
        //把outStream里的数据写入内存
        return outStream.toByteArray();
    }
    /**
     * 将base64字符解码保存文件
     *
     * @param base64Code
     * @param targetPath
     * @throws Exception
     */

    public static void decoderBase64File(String base64Code, String targetPath) throws Exception {
        byte[] buffer = decode(base64Code);
        FileOutputStream out = new FileOutputStream(targetPath);
        out.write(buffer);
        out.close();
    }

    /**
     * 将base64字符保存文本文件
     *
     * @param base64Code
     * @param targetPath
     * @throws Exception
     */

    public static void toFile(String base64Code, String targetPath) throws Exception {

        byte[] buffer = base64Code.getBytes();
        FileOutputStream out = new FileOutputStream(targetPath);
        out.write(buffer);
        out.close();
    }
}

②excel导出

传入参数

{
    "page": 1,
    "limit": 10,
    "userName": "",
    "communityId": "",
    "mobile": ""
}

返回参数

{
    "msg": "操作成功",
    "code": 200,
    "data": "20230719185659.xls"
}

实现思路

①根据传入参数,查询居民信息

②将居民信息写入excel文件,并导出。

具体而言:

  1. 准备Excel模板

    • 创建一个Excel模板文件,该文件包含所需的表头和其他固定内容。
    • 在代码中指定模板文件的路径。
  2. 复制模板文件

    • 为了避免直接修改原始模板文件,先复制一份模板文件。
    • 在复制的文件名中添加时间戳或其他唯一标识,确保每次导出的文件都是新的。
  3. 读取数据

    • 获取需要导出的数据,并将其存储在一个列表中。
  4. 操作Excel文件

    • 使用Apache POI库来操作Excel文件。
    • 读取复制后的Excel文件,获取工作簿和工作表。
  5. 写入数据到Excel

    • 遍历数据列表,为每条数据创建一个新的行。
    • 在每行中创建单元格,并将数据写入到对应的单元格中。
    • 可以根据需要设置单元格的样式、格式等。
  6. 保存Excel文件:将修改后的Excel文件保存到指定的路径。

  7. 将文件名返回

引入依赖

        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-spring-boot-starter</artifactId>
            <version>4.2.0</version>
        </dependency>

controller

     /**
     * 文件导出
     * @param personListForm
     * @return
     */
    @GetMapping("/exportExcel")
    public Result exportExcel(PersonListForm personListForm){
        PageVO pageVO = this.personService.personList(personListForm);
        List list = pageVO.getList();
        String path = excel;
        path = ExcelUtil.ExpPersonInfo(list,path);
        return Result.ok().put("data", path);
    }
ExcelUtil文件导出工具类
package com.qcby.community.util;

import com.qcby.community.vo.PersonVO;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.BorderStyle;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

public class ExcelUtil {

    public static String ExpPersonInfo(List<PersonVO> info, String path){
        POIFSFileSystem fs = null;
        int headRow = 2;
        String descfile = null;
        try {
            //复制文件
            String srcfile = path + "personInfo.xls";
            Date date = new Date();
            SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
            String dateStr = format.format(date);
            descfile = dateStr + ".xls";
            try {
                FileInputStream fis = new FileInputStream(srcfile);
                FileOutputStream fos = new FileOutputStream(path+descfile);
                byte [] buffer = new byte[1024*4];
                while(fis.read(buffer) != -1){
                    fos.write(buffer);
                }
                fis.close();
                fos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            //写数据
            fs = new POIFSFileSystem(new FileInputStream(path + descfile));
            FileOutputStream fos = new FileOutputStream(path + descfile);
            HSSFWorkbook wb1 = new HSSFWorkbook(fs);
            HSSFSheet sheet = wb1.getSheetAt(0);
            int size = info.size();
            int col = 0;
            HSSFCellStyle style = wb1.createCellStyle();
            style.setBorderLeft(BorderStyle.THIN);
            style.setBorderRight(BorderStyle.THIN);
            style.setBorderTop(BorderStyle.THIN);
            style.setBorderBottom(BorderStyle.THIN);
            for(int i = 0;i < size;i++){
                col = 0;
                PersonVO p = info.get(i);
                HSSFRow row = sheet.createRow(i+headRow);
                HSSFCell cell = null;
                cell = row.createCell(col++);
                cell.setCellStyle(style);
                cell.setCellValue(p.getPersonId());

                cell = row.createCell(col++);
                cell.setCellStyle(style);
                cell.setCellValue(p.getCommunityName());

                cell = row.createCell(col++);
                cell.setCellStyle(style);
                cell.setCellValue(p.getTermName());

                cell = row.createCell(col++);
                cell.setCellStyle(style);
                cell.setCellValue(p.getHouseNo());
                cell = row.createCell(col++);
                cell.setCellStyle(style);
                cell.setCellValue(p.getUserName());

                cell = row.createCell(col++);
                cell.setCellStyle(style);
                cell.setCellValue(p.getSex());

                cell = row.createCell(col++);
                cell.setCellStyle(style);
                cell.setCellValue(p.getMobile());

                cell = row.createCell(col++);
                cell.setCellStyle(style);
                cell.setCellValue(p.getPersonType());

                cell = row.createCell(col++);
                cell.setCellStyle(style);
                cell.setCellValue(p.getRemark());

            }
            wb1.write(fos);
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return descfile;
    }

}

③excel上传

实现思路

①指定文件上传位置

②获取上传的文件

③通过UUID生成新的文件名

④文件上传

⑤返回上传的文件名

实现的controller
    /**
     * 数据上传
     * @param file
     * @return
     * @throws Exception
     */
    @PostMapping("/excelUpload")
    public Result excelUpload(@RequestParam("uploadExcel") MultipartFile file) throws Exception {
        if(file.getOriginalFilename().equals("")){
            return Result.error("没有选中要上传的文件");
        }else {
            String picName = UUID.randomUUID().toString();
            String oriName = file.getOriginalFilename();
            String extName = oriName.substring(oriName.lastIndexOf("."));
            String newFileName = picName + extName;
            File targetFile = new File(excel, newFileName);
            // 保存文件
            file.transferTo(targetFile);
            return Result.ok().put("data",newFileName);
        }
    }

④数据导入

实现思路

文件导入的实现思路主要涉及以下几个步骤:

  1. 获取用户信息
    • 通过HttpSession对象从会话中获取当前登录的用户信息,用于存储到数据表person中creater的字段
  2. 读取文件
    • 根据传入的文件名和预设的文件路径,构建完整的文件路径。
    • 使用Apache POI库的POIFSFileSystemHSSFWorkbook类来读取Excel文件。POIFSFileSystem用于处理Office文档的底层文件系统,而HSSFWorkbook则代表一个Excel工作簿。
  3. 处理异常
    • 在读取文件的过程中,可能会遇到文件不存在、文件损坏或读取错误等异常。使用try-catch块来捕获这些异常,并打印堆栈跟踪以便于调试和错误处理。
  4. 获取工作表内容
    • 从工作簿中获取第一个工作表(或根据需求获取特定的工作表)。
    • 获取工作表的总行数和总列数,以确定数据范围。
  5. 数据提取
    • 根据需要,跳过表头行。
    • 遍历工作表的每一行和每一列,使用HSSFRowHSSFCell类获取单元格数据。
    • 使用DataFormatter类将单元格数据格式化为字符串,以便于后续处理。
  6. 存储数据
    • 创建一个二维对象数组,用于存储从Excel文件中提取的数据。
    • 将格式化后的单元格数据按行和列的顺序存入二维数组中。
  7. 写入数据
    • 将二维对象数组中的数据逐条保存到数据库中。
  8. 返回响应
    • 返回响应给前端,前端可以根据响应中的信息进行相应的处理(如显示导入成功提示、刷新页面等)。
实现的controller
/**
     * 数据导入
     * @param fileName
     * @param session
     * @return
     */
    @LogAnnotation("导入数据")
    @PostMapping("/parsefile/{fileName}")
    public Result parsefile(@PathVariable("fileName") String fileName,HttpSession session){
        User user = (User) session.getAttribute("user");
        // POIFSFileSystem是Apache POI库中用于处理Office文档的底层文件系统API。
        // 它代表了一个OLE 2复合文档,这是一个包含多个流(stream)和存储(storage)的单一文件
        POIFSFileSystem fs = null;
        //  HSSFWorkbook类代表一个Excel工作簿,即一个.xls文件。
        // 通过这个类,你可以创建新的Excel文件,或者读取现有的Excel文件。
        // HSSFWorkbook提供了操作工作簿内容的方法,如添加、删除或修改工作表(HSSFSheet),以及设置工作簿的属性等
        HSSFWorkbook wb = null;
        try {
            String basePath = excel + fileName;
            //读取指定路径的Excel文件,放入fs输入流中
            fs = new POIFSFileSystem(new FileInputStream(basePath));
            //wb代表了这个Excel工作簿,你可以使用它来读取或修改Excel文件的内容
            wb = new HSSFWorkbook(fs);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //获取第一个工作表
        HSSFSheet sheet = wb.getSheetAt(0);
        Object[][] data = null;
        //获取总行数
        int r = sheet.getLastRowNum()+1;
        //获取总列数
        int c = sheet.getRow(0).getLastCellNum();
        int headRow = 2;
        //将表格中的数据存入二维对象data中
        data = new Object[r - headRow][c];
        for (int i = headRow; i < r; i++) {
            //获取行
            HSSFRow row = sheet.getRow(i);
            for (int j = 0; j < c; j++) {
                //获取列
                HSSFCell cell = null;
                try {
                    cell = row.getCell(j);
                    try {
                        cell = row.getCell(j);
                        DataFormatter dataFormater = new DataFormatter();
                        String a = dataFormater.formatCellValue(cell);
                        data[i - headRow][j] = a;
                    } catch (Exception e) {
                        data[i-headRow][j] = "";
                        if(j==0){
                            try {
                                double d = cell.getNumericCellValue();
                                data[i - headRow][j] = (int)d + "";
                            }catch(Exception ex){
                                data[i-headRow][j] = "";
                            }
                        }
                    }
                } catch (Exception e) {
                    System.out.println("i="+i+";j="+j+":"+e.getMessage());
                }
            }
        }

        int row = data.length;
        int col = 0;
        String errinfo = "";
        headRow = 3;
        String[] stitle={"ID","小区名称","所属楼栋","房号","姓名","性别","手机号码","居住性质","状态","备注"};
        errinfo = "";
        for (int i = 0; i < row; i++) {
            Person single = new Person();
            single.setPersonId(0);
            single.setState(1);
            single.setFaceUrl("");
            try {
                col=1;
                String communityName = data[i][col++].toString();
                QueryWrapper<Community> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("community_name", communityName);
                Community community = this.communityService.getOne(queryWrapper);
                if( community == null){
                    errinfo += "Excel文件第" + (i + headRow) + "行小区名称不存在!";
                    return Result.ok().put("status", "fail").put("data", errinfo);
                }
                single.setCommunityId(community.getCommunityId());
                single.setTermName(data[i][col++].toString());
                single.setHouseNo(data[i][col++].toString());
                single.setUserName(data[i][col++].toString());
                single.setSex(data[i][col++].toString());
                single.setMobile(data[i][col++].toString());
                single.setPersonType(data[i][col++].toString());
                single.setRemark(data[i][col++].toString());
                single.setCreater(user.getUsername());
                this.personService.save(single);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return Result.ok().put("status", "success").put("data","数据导入完成!");
    }

3、小区地图

获取地图数据

前端

vue安装依赖

cnpm i --save vue-baidu-map

配置申请密钥

Vue.use(BaiduMap, {
  // ak 是在百度地图开发者平台申请的密钥
  ak: '7eTaUxl9NY8RCMxCPm3oc8m2snTBOgbt'
})
后端

传入参数

返回参数

{
    "msg": "操作成功",
    "code": 200,
    "data": [
        {
            "communityId": 2,
            "communityName": "栖海澐颂",
            "termCount": 0,
            "seq": 0,
            "creater": "",
            "createTime": "",
            "lng": 116.2524,
            "lat": 40.0961,
        }
    ]
}

实现controller

    /**
     * 获取小区地图
     * @return
     */
    @GetMapping("/getCommunityMap")
    public Result getCommunityMap(){
        List<Community> data = communityService.list();
        if(data == null) return Result.error("没有小区数据");
        return Result.ok().put("data", data);
    }
界面

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/533189.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

乡村智慧化升级:数字乡村打造农村生活新品质

目录 一、乡村智慧化升级的内涵与意义 二、乡村智慧化升级的具体实践 1、加强农村信息基础设施建设 2、推广智慧农业应用 3、提升乡村治理智慧化水平 4、丰富智慧乡村生活内容 三、数字乡村打造农村生活新品质的成果展现 1、农业生产效率与质量双提升 2、农民收入与消…

OSCP靶场--Peppo

OSCP靶场–Peppo 考点(ident枚举服务用户名ssh登陆rbash绕过 docker提权) 1.nmap扫描 ## ┌──(root㉿kali)-[~/Desktop] └─# nmap 192.168.158.60 -sV -sC -Pn --min-rate 2500 -p- Starting Nmap 7.92 ( https://nmap.org ) at 2024-04-10 09:32 EDT Nmap scan report…

SQLite数据库在Linux系统上的使用

SQLite是一个轻量级的数据库解决方案&#xff0c;它是一个嵌入式的数据库管理系统。SQLite的特点是无需独立的服务器进程&#xff0c;可以直接嵌入到使用它的应用程序中。由于其配置简单、支持跨平台、服务器零管理&#xff0c;以及不需要复杂的设置和操作&#xff0c;SQLite非…

进程控制(一)

文章目录 1. 进程创建1.1 fork函数初识1.2 fork函数返回值 2. 写时拷贝3. 进程终止3.1 进程退出场景3.2 进程常见退出方法3.3 exit函数3.4 return退出 4. 进程等待4.1 进程等待必要性4.2 进程等待的方法4.2.1 wait方法4.2.2 waitpid方法4.2.3 获取子进程status 1. 进程创建 1.…

MySQL8.0的下载、安装配置教程、连接数据可视图形化界面和卸载及MySQL基本使用教程

文章目录 MySQL8.0下载安装MySQL卸载常见问题解决方式MySQL基本使用教程&#xff08;使用MySQLworkbench&#xff09; 1、创建数据库2、创建表、删除表3、修改表的名字4、为数据表增加、修改、删除字段5、关于修改数据库名字6、拓展&#xff1a;pycharm操作MySQL 首先&#…

uniapp区分app、h5、小程序

APP端 标签内 <!-- #ifdef APP-PLUS --><view> APP端 </view> <!-- #endif --> JSCSS内 /*#ifdef APP-PLUS*/console.log(APP端) /*#endif*/ H5端 标签内 <!-- #ifdef H5 --><view> H5端 </view> <!-- #endif --> JSC…

uniapp中页面滚动锚点位置及滚动到对应高度显示对应按钮

可以把页面代码和组件代码放自己项目里跑一下 页面代码 <template><view class"Tracing-detail"><view class"title" v-for"i in 30">顶部信息</view><!-- tab按钮 --><Tab v-model"activeIndex" …

计算机网络 Telnet远程访问交换机和Console终端连接交换机

一、实验要求和内容 1、配置交换机进入特权模式密文密码为“abcd两位班内学号”&#xff0c;远程登陆密码为“123456” 2、验证PC0通过远程登陆到交换机上&#xff0c;看是否可以进去特权模式 二、实验步骤 1、将一台还没配置的新交换机&#xff0c;利用console线连接设备的…

Vue实现防篡改水印的效果。删除元素无效!更改元素属性无效!支持图片、元素、视频等等。

1、演示 2、水印的目的 版权保护&#xff1a;水印可以在图片、文档或视频中嵌入作者、品牌或版权所有者的信息&#xff0c;以防止未经授权的复制、传播或使用。当其他人使用带有水印的内容时&#xff0c;可以追溯到原始作者或版权所有者&#xff0c;从而加强版权保护。 身份识…

在linux服务器上安装anaconda

遇到问题&#xff1a; 在linux服务器中查看当前有哪些虚拟环境&#xff0c;conda环境用不了&#xff0c;anaconda没有安装&#xff0c;所以要在linux服务器中安装虚拟环境 解决步骤如下&#xff1a; 1.首先下载anaconda的Linux版本的安装包 方法1&#xff1a;官网下载&#…

python如何写入csv

在使用python对文件操作的过程中&#xff0c;你肯定碰到过对csv文件的操作&#xff0c;下面就python对csv文件的操作进行详述。 CSV&#xff08;Comma-Separated Values&#xff09;逗号分隔符&#xff0c;也就是每条记录中的值与值之间是用分号分隔的。 打开CSV文件并写入一…

卷积通用模型的剪枝、蒸馏---剪枝篇(此处以deeplabv3+为例,可根据模型自行定制剪枝层)

之后的两篇文章是对前段时间工作的一个总结。 一、环境配置 1.1、文章以b导的代码为模板,环境配置比较简单(第二篇蒸馏篇结束后会放置剪枝蒸馏配置好的百度网盘链接),其他算法自行配置,在剪枝之前,需要保证算法能够在本地跑通。 B导链接: https://github.com/bubbliiiin…

2024年 前端JavaScript 进阶 第4天 End 笔记

4.1-内容和浅拷贝 4.2-递归函数 4.3-深拷贝实现 4.4-利用lodash和JSON实现深 4.5-异常处理-throw和try、catch 4.6-普通函数和箭头函数的this 4.7-call方法改变this指向 4.8-apply方法 4.9-bind方法以及总结 4.10-什么是防抖以及底层实现 4.11-什么是节流以及底层实现 4.12-节流…

华为2024年校招实习硬件-结构工程师机试题(四套)

华为2024年校招&实习硬件-结构工程师机试题&#xff08;四套&#xff09; &#xff08;共四套&#xff09;获取&#xff08;WX: didadidadidida313&#xff0c;加我备注&#xff1a;CSDN 华为硬件结构题目&#xff0c;谢绝白嫖哈&#xff09; 结构设计工程师&#xff0c;结…

Shotcut:免费且开源的优质视频剪辑工具

Shotcut&#xff1a;您的专业级免费开源视频编辑利器&#xff0c;助您轻松实现创意无限的剪辑梦想&#xff01;- 精选真开源&#xff0c;释放新价值。 概览 Shotcut&#xff0c;一款广受赞誉的免费、开源跨平台视频编辑软件&#xff0c;以其卓越的功能性和易用性赢得了全球用户…

计算机视觉 | 基于二值图像数字矩阵的距离变换算法

Hi&#xff0c;大家好&#xff0c;我是半亩花海。本实验基于 OpenCV 实现了二值图像数字矩阵的距离变换算法。首先生成一个 480x480 的黑色背景图像&#xff08;定义黑色为0&#xff0c;白色为1&#xff09;&#xff0c;在其中随机选择了三个白色像素点作为距离变换的原点&…

RTSP/Onvif安防视频EasyNVR平台 vs.多协议接入视频汇聚EasyCVR平台:设备分组的区别

EasyNVR安防视频云平台是旭帆科技TSINGSEE青犀旗下支持RTSP/Onvif协议接入的安防监控流媒体视频云平台。平台具备视频实时监控直播、云端录像、云存储、录像检索与回看、告警等视频能力&#xff0c;能对接入的视频流进行处理与多端分发&#xff0c;包括RTSP、RTMP、HTTP-FLV、W…

HWOD:投票统计

一、知识点 1、单词 候选人的英文是Candidate 投票的英文是vote 投票人的英文是voter 2、for循环 如果在for循环内将i置为n&#xff0c;结束该层循环后&#xff0c;for循环会先给i加1,然后再去判读i是否小于n&#xff0c;所以for循环结束后&#xff0c;i的值为n1 3、字符…

LeetCode 239. 滑动窗口最大值

滑动窗口最大值 给你一个整数数组 nums&#xff0c;有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例 1&#xff1a; 输入&#xff1a;nums [1,3,-1,-3,…

用html实现一个动态的文字框

<!DOCTYPE html> <html lang"en" > <head><meta charset"UTF-8"><title>一个动态的文字框动画</title><link rel"stylesheet" href"./style.css"></head> <body> <link rel…