From 728a54cc02ff66e38bc8719ecc0f3155e597084c Mon Sep 17 00:00:00 2001
From: zhangmei <645025773@qq.com>
Date: 星期五, 14 二月 2025 15:27:56 +0800
Subject: [PATCH] Merge branch 'master' of https://gitee.com/xiaochen991015/xizang into xizang-changyun

---
 ruoyi-admin/src/main/resources/application-test.yml                                                 |    6 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TInformationServiceImpl.java               |    9 
 ruoyi-common/src/main/java/com/ruoyi/common/constant/DictConstants.java                             |    4 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TCheckAcceptRecordController.java            |  124 +
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TFaultRepairMessageServiceImpl.java        |   18 
 ruoyi-system/src/main/java/com/ruoyi/system/query/SysUserQuery.java                                 |    8 
 ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/pojo/AppletUserDecodeData.java                 |   52 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBillController.java                         |    3 
 ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TBillController.java                        |   20 
 ruoyi-common/src/main/java/com/ruoyi/common/core/utils/HttpUtils.java                               |  311 +++
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/TCheckAcceptRecordMapper.java                    |   15 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/interceptor/MybatisInterceptor.java              |    4 
 ruoyi-applet/src/main/resources/application-test.yml                                                |   14 
 ruoyi-system/src/main/java/com/ruoyi/system/service/TFaultRepairMessageService.java                 |   16 
 ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/COSController.java                          |   55 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/TFaultRepairMessageMapper.java                   |   21 
 ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WebUtils.java                            |   48 
 ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java                     |  110 +
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TCheckAcceptRecordServiceImpl.java         |   21 
 ruoyi-common/src/main/java/com/ruoyi/common/core/exception/ServiceException.java                    |   74 
 ruoyi-system/src/main/java/com/ruoyi/system/model/TFaultRepairMessage.java                          |   16 
 ruoyi-system/src/main/java/com/ruoyi/system/model/TCheckAcceptRecord.java                           |    2 
 ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml                                     |   15 
 ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TFaultRepairMessageController.java          |  102 +
 ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxCache.java                             |  117 +
 ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/model/WeixinProperties.java                    |   79 
 ruoyi-common/src/main/java/com/ruoyi/common/redis/configure/FastJson2JsonRedisSerializer.java       |   50 
 ruoyi-system/src/main/java/com/ruoyi/system/dto/TFaultRepairMessageDTO.java                         |   10 
 ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java                                 |    8 
 ruoyi-system/src/main/java/com/ruoyi/system/model/TInformation.java                                 |    4 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/TDeptToUserMapper.java                           |    9 
 ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxAppletTools.java                       |  123 +
 ruoyi-system/src/main/java/com/ruoyi/system/vo/SysUserVO.java                                       |    4 
 ruoyi-system/pom.xml                                                                                |    4 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFaultRepairMessageController.java           |   80 
 ruoyi-system/src/main/resources/mapper/system/TItemMapper.xml                                       |    2 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java                           |    3 
 ruoyi-system/src/main/resources/mapper/system/TFaultRepairMessageMapper.xml                         |  103 +
 ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxCacheTemplate.java                     |   34 
 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/TTenantResp.java                     |   70 
 ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/body/resp/AccessTokenRespBody.java             |   28 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java                    |   69 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java                     |  135 +
 ruoyi-system/src/main/java/com/ruoyi/system/query/TFaultRepairMessageQuery.java                     |   27 
 ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/SHA1.java                                |   36 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TContractServiceImpl.java                  |  514 +++++
 ruoyi-system/src/main/java/com/ruoyi/system/model/TTenant.java                                      |    3 
 ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/body/resq/Code2SessionResqBody.java            |   21 
 ruoyi-applet/src/main/resources/mybatis-config.xml                                                  |    2 
 ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/pojo/AppletPhoneEncrypteData.java              |   19 
 ruoyi-system/src/main/java/com/ruoyi/system/vo/TItemTypeVO.java                                     |   18 
 ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java                              |   10 
 ruoyi-system/src/main/java/com/ruoyi/system/vo/TBillVO.java                                         |   16 
 ruoyi-system/src/main/resources/mapper/system/TCheckAcceptRecordMapper.xml                          |   48 
 ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java |   22 
 ruoyi-system/src/main/java/com/ruoyi/system/service/TTenantService.java                             |    5 
 ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxException.java                         |   55 
 ruoyi-system/src/main/java/com/ruoyi/system/vo/TCheckAcceptRecordVO.java                            |   20 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/TaskUtil.java                               |  496 -----
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTenantServiceImpl.java                    |   11 
 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java                         |    5 
 ruoyi-system/src/main/resources/mapper/system/TFaultAreaDicMapper.xml                               |    6 
 ruoyi-system/src/main/java/com/ruoyi/system/service/TFaultAreaDicService.java                       |    6 
 ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TInformationController.java                 |   24 
 ruoyi-system/src/main/java/com/ruoyi/system/service/TCheckAcceptRecordService.java                  |    9 
 ruoyi-common/src/main/java/com/ruoyi/common/core/utils/Constants.java                               |  143 +
 ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/WxLoginController.java                      |  255 ++
 ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxUtils.java                             |  175 ++
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TFaultAreaDicServiceImpl.java              |    6 
 ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml                                 |    6 
 ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/pojo/Watermark.java                            |    9 
 ruoyi-system/src/main/resources/mapper/system/TItemTypeMapper.xml                                   |    7 
 ruoyi-system/src/main/resources/mapper/system/TDeptToUserMapper.xml                                 |    3 
 ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java                        |    1 
 ruoyi-system/src/main/java/com/ruoyi/system/model/TContract.java                                    |   13 
 ruoyi-system/src/main/java/com/ruoyi/system/query/TCheckAcceptRecordQuery.java                      |   22 
 ruoyi-applet/src/main/resources/application-prod.yml                                                |    8 
 ruoyi-applet/src/main/java/com/ruoyi/web/controller/interceptor/MybatisInterceptor.java             |    4 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java                    |  132 -
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFaultAreaDicController.java                 |    1 
 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUserApplet.java                  |  263 +++
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/TFaultAreaDicMapper.java                         |    6 
 ruoyi-system/src/main/java/com/ruoyi/system/service/TItemTypeService.java                           |    5 
 ruoyi-system/src/main/resources/mapper/system/TContractMapper.xml                                   |    2 
 ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/pojo/AppletUserEncrypteData.java               |   20 
 ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/body/resp/RespBody.java                        |   19 
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/TItemTypeMapper.java                             |    5 
 ruoyi-system/src/main/java/com/ruoyi/system/vo/TFaultAreaDicVO.java                                 |   18 
 ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml                                  |   15 
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TItemTypeServiceImpl.java                  |    6 
 ruoyi-system/src/main/java/com/ruoyi/system/vo/TFaultRepairMessageVO.java                           |   22 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TItemTypeController.java                     |    1 
 ruoyi-applet/src/main/java/com/ruoyi/web/controller/tool/TencentCosUtil.java                        |  187 ++
 ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxJsonUtils.java                         |  109 +
 ruoyi-system/src/main/java/com/ruoyi/system/vo/FaultConcatInfoVO.java                               |   17 
 ruoyi-common/src/main/java/com/ruoyi/common/redis/service/RedisService.java                         |  273 +++
 ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/body/resp/Code2SessionRespBody.java            |   29 
 97 files changed, 4,415 insertions(+), 740 deletions(-)

diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBillController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBillController.java
index 4ce9a6b..be95875 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBillController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBillController.java
@@ -34,6 +34,9 @@
     @Autowired
     TBillService tBillService;
 
+
+
+
     @PreAuthorize("@ss.hasPermi('system:bill:list')")
     @PostMapping("list")
     @ApiOperation("分页查询账单列表")
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TCheckAcceptRecordController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TCheckAcceptRecordController.java
index 6cdd012..b6dee08 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TCheckAcceptRecordController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TCheckAcceptRecordController.java
@@ -1,9 +1,28 @@
 package com.ruoyi.web.controller.api;
 
 
-import org.springframework.web.bind.annotation.RequestMapping;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.basic.PageInfo;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.model.TCheckAcceptRecord;
+import com.ruoyi.system.model.TContract;
+import com.ruoyi.system.model.THouse;
+import com.ruoyi.system.query.TCheckAcceptRecordQuery;
+import com.ruoyi.system.service.TCheckAcceptRecordService;
+import com.ruoyi.system.service.TContractService;
+import com.ruoyi.system.service.THouseService;
+import com.ruoyi.system.vo.TCheckAcceptRecordVO;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
 
-import org.springframework.web.bind.annotation.RestController;
+import java.util.List;
 
 /**
  * <p>
@@ -13,9 +32,110 @@
  * @author xiaochen
  * @since 2025-01-17
  */
+@Api(tags = "验收记录管理")
 @RestController
 @RequestMapping("/t-check-accept-record")
 public class TCheckAcceptRecordController {
 
+    private final TCheckAcceptRecordService checkAcceptRecordService;
+    private final TContractService contractService;
+    private final THouseService houseService;
+    @Autowired
+    public TCheckAcceptRecordController(TCheckAcceptRecordService checkAcceptRecordService, TContractService contractService, THouseService houseService) {
+        this.checkAcceptRecordService = checkAcceptRecordService;
+        this.contractService = contractService;
+        this.houseService = houseService;
+    }
+
+    /**
+     * 获取验收记录管理列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:accept:list')")
+    @ApiOperation(value = "获取验收记录分页列表")
+    @PostMapping(value = "/pageList")
+    public R<PageInfo<TCheckAcceptRecordVO>> pageList(@RequestBody TCheckAcceptRecordQuery query) {
+        return R.ok(checkAcceptRecordService.pageList(query));
+    }
+
+    /**
+     * 通过合同id查询房屋信息
+     */
+    @ApiOperation(value = "通过合同id查询房屋信息")
+    @PostMapping(value = "/getHouseByContractId")
+    public R<THouse> getHouseByContractId(@RequestParam String contractId) {
+        TContract contract = contractService.getById(contractId);
+        THouse house = houseService.getById(contract.getHouseId());
+        return R.ok(house);
+    }
+
+    /**
+     * 通过房屋id查询合同信息
+     */
+    @ApiOperation(value = "通过房屋id查询合同信息")
+    @PostMapping(value = "/getContractByHouseId")
+    public R<TContract> getContractByHouseId(@RequestParam String houseId) {
+        TContract contract = contractService.getOne(Wrappers.lambdaQuery(TContract.class)
+                .eq(TContract::getHouseId, houseId)
+                .orderByDesc(TContract::getCreateTime)
+                .in(TContract::getStatus, 4, 6, 7)
+                .last("LIMIT 1"));
+        return R.ok(contract);
+    }
+
+    /**
+     * 添加验收记录管理
+     */
+    @PreAuthorize("@ss.hasPermi('system:accept:add')")
+    @Log(title = "验收记录信息-新增验收记录", businessType = BusinessType.INSERT)
+    @ApiOperation(value = "添加验收记录")
+    @PostMapping(value = "/add")
+    public R<Boolean> add(@Validated @RequestBody TCheckAcceptRecord dto) {
+        // 添加验收记录
+        checkAcceptRecordService.save(dto);
+
+        // TODO 生成结算帐单
+
+        return R.ok();
+    }
+
+    /**
+     * 查看验收记录详情
+     */
+    @PreAuthorize("@ss.hasPermi('system:accept:detail')")
+    @ApiOperation(value = "查看验收记录详情")
+    @GetMapping(value = "/getDetailById")
+    public R<TCheckAcceptRecordVO> getDetailById(@RequestParam String id) {
+        TCheckAcceptRecord checkAcceptRecord = checkAcceptRecordService.getById(id);
+        TCheckAcceptRecordVO checkAcceptRecordVO = new TCheckAcceptRecordVO();
+        BeanUtils.copyProperties(checkAcceptRecord, checkAcceptRecordVO);
+        // 查询合同信息
+        checkAcceptRecordVO.setContract(contractService.getById(checkAcceptRecord.getContractId()));
+        // 查询房屋信息
+        checkAcceptRecordVO.setHouse(houseService.getById(checkAcceptRecord.getHouseId()));
+        return R.ok(checkAcceptRecordVO);
+    }
+
+    /**
+     * 删除验收记录
+     */
+    @PreAuthorize("@ss.hasPermi('system:accept:delete')")
+    @Log(title = "验收记录信息-删除验收记录", businessType = BusinessType.DELETE)
+    @ApiOperation(value = "删除验收记录")
+    @DeleteMapping(value = "/deleteById")
+    public R<Boolean> deleteById(@RequestParam String id) {
+        return R.ok(checkAcceptRecordService.removeById(id));
+    }
+
+    /**
+     * 批量删除验收记录
+     */
+    @PreAuthorize("@ss.hasPermi('system:accept:delete')")
+    @Log(title = "验收记录信息-删除验收记录", businessType = BusinessType.DELETE)
+    @ApiOperation(value = "批量删除验收记录")
+    @DeleteMapping(value = "/deleteByIds")
+    public R<Boolean> deleteByIds(@RequestBody List<String> ids) {
+        return R.ok(checkAcceptRecordService.removeByIds(ids));
+    }
+
 }
 
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java
index e0d70ff..c8a0d28 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TContractController.java
@@ -47,7 +47,9 @@
 import java.io.IOException;
 import java.math.BigDecimal;
 import java.net.URLEncoder;
+import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.temporal.ChronoUnit;
 import java.util.*;
 
 /**
@@ -72,6 +74,109 @@
     private TBillService billService;
     @Autowired
     private TCheckAcceptRecordService checkAcceptRecordService;
+    @ApiOperation(value = "测试生成账单")
+    @PostMapping(value = "/testBill")
+
+    public R testBill(String id) {
+        TContract contract = contractService.getById(id);
+        // 查询所有已签订的合同并且未生成第一笔账单的
+
+        List<TBill> bills = new ArrayList<>();
+        List<TContractRentType> contractRentTypes = contractRentTypeService.list();
+            contract.setFirstPayTime(contract.getStartTime().plusDays(10));
+            // 第一次应缴费日期
+            LocalDateTime firstPayTime = contract.getStartTime().plusDays(10).withHour(0).withMinute(0).withSecond(0);
+            TBill rentBill = new TBill();
+            rentBill.setContractId(contract.getId());
+            rentBill.setContractNumber(contract.getContractNumber());
+            rentBill.setPayableFeesTime(firstPayTime);
+            rentBill.setPayFeesStatus("1");
+            rentBill.setBillType("1");
+            rentBill.setStartTime(contract.getStartPayTime());
+            TContractRentType tContractRentType = contractRentTypes.stream().filter(e -> e.getContractId().equals(contract.getId())).findFirst().orElse(null);
+
+            if (tContractRentType!=null && contract.getStartPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).isAfter(tContractRentType.getChangeTime())){
+                // 计算租金变动的天数
+                long moneyDays = ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), contract.getStartPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12))+1L;
+                contract.setChangeTime(LocalDateTime.now());
+                // 递增递减的租金
+                BigDecimal contractRentTypeMoney = new BigDecimal("0");
+                // 不递增递减的租金
+                BigDecimal originalMoney = new BigDecimal("0");
+                // 原租金
+                switch (tContractRentType.getIncreasingDecreasingType()){
+                    case 1:
+                        switch (tContractRentType.getIncreasingDecreasing()){
+                            case 1:
+                                contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue())).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)));
+                                contract.setChangeRent(contractRentTypeMoney);
+                                break;
+                            case 2:
+                                contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().multiply((new BigDecimal(100).subtract(tContractRentType.getNumericalValue()))).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)).divide(new BigDecimal(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12),2,BigDecimal.ROUND_DOWN));
+                                contract.setChangeRent(contractRentTypeMoney);
+                                break;
+                        }
+                        break;
+                    case 2:
+                        switch (tContractRentType.getIncreasingDecreasing()){
+                            case 1:
+                                contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
+                                contract.setChangeRent(contractRentTypeMoney);
+                                break;
+                            case 2:
+                                contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
+                                contract.setChangeRent(contractRentTypeMoney);
+
+                                break;
+                        }
+                        break;
+                }
+                // 不需要涨租金的时间段
+                if (contract.getFirstPayTime().isBefore(tContractRentType.getChangeTime())){
+                    long originalDays = ChronoUnit.DAYS.between(contract.getFirstPayTime(), tContractRentType.getChangeTime());
+                    originalMoney=originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
+                            .multiply(new BigDecimal(originalDays));
+                    rentBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
+                    rentBill.setOutstandingMoney(rentBill.getPayableFeesMoney());
+                }else{
+                    rentBill.setPayableFeesMoney(contractRentTypeMoney);
+                    rentBill.setOutstandingMoney(rentBill.getPayableFeesMoney());
+                }
+
+                if (contract.getFirstPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).isAfter(contract.getEndTime())){
+                    rentBill.setEndTime(contract.getFirstPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12));
+                }else{
+                    rentBill.setEndTime(contract.getEndTime());
+                }
+            }else{
+                if (contract.getFirstPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).isAfter(contract.getEndTime())){
+                    rentBill.setEndTime(contract.getFirstPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12));
+                }else{
+                    rentBill.setEndTime(contract.getEndTime());
+                }
+                // 不走递增递减
+                long allDays = ChronoUnit.DAYS.between(contract.getFirstPayTime(), rentBill.getEndTime());
+                rentBill.setPayableFeesMoney(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(allDays)));
+                rentBill.setOutstandingMoney(rentBill.getPayableFeesMoney());
+
+            }
+            // 租金账单
+            bills.add(rentBill);
+            // 押金账单
+            TBill depositBill = new TBill();
+            depositBill.setContractId(contract.getId());
+            depositBill.setContractNumber(contract.getContractNumber());
+            depositBill.setPayableFeesMoney(contract.getDeposit());
+            depositBill.setOutstandingMoney(depositBill.getPayableFeesMoney());
+
+            depositBill.setPayableFeesTime(firstPayTime);
+            depositBill.setPayFeesStatus("1");
+            depositBill.setBillType("2");
+        contractService.updateById(contract);
+        billService.save(rentBill);
+        billService.save(depositBill);
+        return R.ok();
+    }
     @ApiOperation(value = "获取合同分页列表")
     @PostMapping(value = "/contractList")
     @PreAuthorize("@ss.hasPermi('system:contract:list')")
@@ -84,6 +189,7 @@
     @PostMapping(value = "/addContract")
     @PreAuthorize("@ss.hasPermi('system:contract:add')")
     public R<Boolean> addContract(@Validated @RequestBody TContractDTO dto) {
+        dto.setChangeRent(dto.getMonthRent());
         contractService.save(dto);
         if (dto.getIsIncreasing()){
             TContractRentType tContractRentType = new TContractRentType();
@@ -100,6 +206,8 @@
     @Log(title = "合同管理-编辑合同", businessType =  BusinessType.UPDATE)
     @ApiOperation(value = "编辑合同")
     @PostMapping(value = "/updateContract")
+    @PreAuthorize("@ss.hasPermi('system:contract:update')")
+
     public R<Boolean> updateContract(@Validated @RequestBody TContractDTO dto) {
         contractService.updateById(dto);
         contractRentTypeService.remove(new LambdaQueryWrapper<TContractRentType>()
@@ -118,6 +226,8 @@
     }
     @Log(title = "合同管理-批量删除合同", businessType = BusinessType.DELETE)
     @ApiOperation(value = "批量删除合同")
+    @PreAuthorize("@ss.hasPermi('system:contract:delete')")
+
     @DeleteMapping(value = "/deleteContractByIds")
     public R<Boolean> deleteContractByIds
             (@RequestParam String ids) {
@@ -129,6 +239,8 @@
 
     @ApiOperation(value = "查询合同信息信息")
     @GetMapping(value = "/getContractById")
+    @PreAuthorize("@ss.hasPermi('system:contract:detail')")
+
     public R<TContractVO> getContractById(@RequestParam String id) {
         TContractVO res = new TContractVO();
         TContract contract = contractService.getById(id);
@@ -158,32 +270,50 @@
             payMoney = payMoney.add(tBill.getPayFeesMoney()).add(tBill.getPayableFeesPenalty());
         }
         TCheckAcceptRecord tCheckAcceptRecord = checkAcceptRecordService.lambdaQuery().eq(TCheckAcceptRecord::getContractId, id).one();
-        res.setCheckResult(tCheckAcceptRecord.getCheckResult());
+        res.setCheckResult(Objects.nonNull(tCheckAcceptRecord)?tCheckAcceptRecord.getCheckResult():false);
         res.setPayMoney(payMoney);
 
         return R.ok(res);
     }
     @Log(title = "合同管理-撤销审批", businessType =  BusinessType.UPDATE)
     @ApiOperation(value = "撤销审批")
+    @PreAuthorize("@ss.hasPermi('system:contract:revoke')")
+
     @GetMapping(value = "/updateContractStatus")
     public R<Boolean> updateContractStatus(String id) {
         TContract contract = contractService.getById(id);
         contract.setStatus("1");
+        contractService.updateById(contract);
+        return R.ok();
+    }
+    @PreAuthorize("@ss.hasPermi('system:contract:confirm')")
+
+    @Log(title = "合同管理-确认结算", businessType =  BusinessType.UPDATE)
+    @ApiOperation(value = "确认结算")
+    @PostMapping(value = "/confirmSettlement")
+
+    public R<Boolean> confirmSettlement(String id) {
+        TContract contract = contractService.getById(id);
+        contract.setStatus("8");
+        contractService.updateById(contract);
         return R.ok();
     }
     @ApiOperation(value = "终止合同剩余未缴费账单列表")
     @PostMapping(value = "/contractBillList")
+    @PreAuthorize("@ss.hasPermi('system:contract:billList')")
     public R<PageInfo<BillVO>> contractBillList(@RequestBody TContractBillQuery query) {
         return R.ok(contractService.contractBillList(query));
     }
     @ApiOperation(value = "终止合同")
     @PostMapping(value = "/terminateContract")
+    @PreAuthorize("@ss.hasPermi('system:contract:terminate')")
     public R terminateContract(@RequestBody TerminateContractDTO dto) {
         contractService.terminateContract(dto);
         return R.ok();
     }
     @ApiOperation(value = "根据合同id查看验收记录")
     @GetMapping(value = "/getCheckByContractId")
+    @PreAuthorize("@ss.hasPermi('system:contract:checkDetail')")
     public R<CheckAcceptRecordVO> getCheckByContractId(String id) {
         return R.ok(contractService.getCheckByContractId(id));
     }
@@ -191,6 +321,8 @@
     private WordUtil wordUtil;
     @ApiOperation(value = "生成合同附件")
     @PostMapping("/set")
+    @Log(title = "生成合同附件", businessType = BusinessType.EXPORT)
+    @PreAuthorize("@ss.hasPermi('system:contract:set')")
     public R<List<String>> set(@RequestBody SetContractDto dto,HttpServletResponse response){
         List<TContract> list = contractService.lambdaQuery().in(TContract::getId, dto.getIds()).list();
         List<String> res = new ArrayList<>();
@@ -228,6 +360,7 @@
      * 导出
      */
     @ApiOperation(value = "导出")
+    @PreAuthorize("@ss.hasPermi('system:contract:export')")
     @Log(title = "导出", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
     public void exportOpticalInspection(@RequestBody TContractQuery query)
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFaultAreaDicController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFaultAreaDicController.java
index 612ca22..928ee34 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFaultAreaDicController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFaultAreaDicController.java
@@ -53,7 +53,6 @@
         return R.ok(faultAreaDicService.pageList(query));
     }
 
-    @PreAuthorize("@ss.hasPermi('system:faultArea:list')")
     @ApiOperation(value = "获取故障区域列表")
     @PostMapping(value = "/list")
     public R<List<TFaultAreaDic>> list() {
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFaultRepairMessageController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFaultRepairMessageController.java
index 963d22b..b5148ff 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFaultRepairMessageController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TFaultRepairMessageController.java
@@ -1,9 +1,22 @@
 package com.ruoyi.web.controller.api;
 
 
-import org.springframework.web.bind.annotation.RequestMapping;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.basic.PageInfo;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.model.TFaultRepairMessage;
+import com.ruoyi.system.query.TFaultRepairMessageQuery;
+import com.ruoyi.system.service.TFaultRepairMessageService;
+import com.ruoyi.system.vo.TFaultRepairMessageVO;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
 
-import org.springframework.web.bind.annotation.RestController;
+import java.util.List;
 
 /**
  * <p>
@@ -13,9 +26,72 @@
  * @author xiaochen
  * @since 2025-01-17
  */
+@Api(tags = "报修管理")
 @RestController
 @RequestMapping("/t-fault-repair-message")
 public class TFaultRepairMessageController {
 
+    private final TFaultRepairMessageService tFaultRepairMessageService;
+
+    @Autowired
+    public TFaultRepairMessageController(TFaultRepairMessageService tFaultRepairMessageService) {
+        this.tFaultRepairMessageService = tFaultRepairMessageService;
+    }
+
+    /**
+     * 获取报修管理列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:fault:list')")
+    @ApiOperation(value = "获取报修分页列表")
+    @PostMapping(value = "/pageList")
+    public R<PageInfo<TFaultRepairMessageVO>> pageList(@RequestBody TFaultRepairMessageQuery query) {
+        return R.ok(tFaultRepairMessageService.pageList(query));
+    }
+
+    /**
+     * 处理维修
+     */
+    @PreAuthorize("@ss.hasPermi('system:fault:update')")
+    @Log(title = "报修信息-处理维修", businessType = BusinessType.UPDATE)
+    @ApiOperation(value = "处理维修")
+    @PostMapping(value = "/update")
+    public R<Boolean> update(@Validated @RequestBody TFaultRepairMessage faultRepairMessage) {
+        faultRepairMessage.setStatus(2);
+        return R.ok(tFaultRepairMessageService.updateById(faultRepairMessage));
+    }
+
+    /**
+     * 查看报修详情
+     */
+    @PreAuthorize("@ss.hasPermi('system:fault:detail')")
+    @ApiOperation(value = "查看报修详情")
+    @GetMapping(value = "/getDetailById")
+    public R<TFaultRepairMessageVO> getDetailById(@RequestParam String id) {
+        TFaultRepairMessageVO faultRepairMessageVO = tFaultRepairMessageService.getDetailById(id);
+        return R.ok(faultRepairMessageVO);
+    }
+
+    /**
+     * 删除报修
+     */
+    @PreAuthorize("@ss.hasPermi('system:fault:delete')")
+    @Log(title = "报修信息-删除报修", businessType = BusinessType.DELETE)
+    @ApiOperation(value = "删除报修")
+    @DeleteMapping(value = "/deleteById")
+    public R<Boolean> deleteById(@RequestParam String id) {
+        return R.ok(tFaultRepairMessageService.removeById(id));
+    }
+
+    /**
+     * 批量删除报修
+     */
+    @PreAuthorize("@ss.hasPermi('system:fault:delete')")
+    @Log(title = "报修信息-删除报修", businessType = BusinessType.DELETE)
+    @ApiOperation(value = "批量删除报修")
+    @DeleteMapping(value = "/deleteByIds")
+    public R<Boolean> deleteByIds(@RequestBody List<String> ids) {
+        return R.ok(tFaultRepairMessageService.removeByIds(ids));
+    }
+
 }
 
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TItemTypeController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TItemTypeController.java
index e35db1f..648c2e8 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TItemTypeController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TItemTypeController.java
@@ -54,7 +54,6 @@
     /**
      * 获取维修物品分类管理列表
      */
-    @PreAuthorize("@ss.hasPermi('system:itemType:list')")
     @ApiOperation(value = "获取维修物品分类列表")
     @PostMapping(value = "/list")
     public R<List<TItemType>> list() {
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/interceptor/MybatisInterceptor.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/interceptor/MybatisInterceptor.java
index d739523..8c232f4 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/interceptor/MybatisInterceptor.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/interceptor/MybatisInterceptor.java
@@ -54,7 +54,7 @@
                     //注入创建时间
                     if ("createTime".equals(field.getName())) {
                         field.setAccessible(true);
-                        field.set(parameter, LocalDateTime.now());
+//                        field.set(parameter, LocalDateTime.now());
                         field.setAccessible(false);
                     } 
                 } catch (Exception e) {
@@ -77,7 +77,7 @@
                     }
                     if ("updateTime".equals(field.getName())) {
                         field.setAccessible(true);
-                        field.set(parameter, LocalDateTime.now());
+//                        field.set(parameter, new Date());
                         field.setAccessible(false);
                     }
                 } catch (Exception e) {
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
index 3475998..27aea74 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
@@ -82,105 +82,6 @@
 //    }
 
     /**
-     * 人员借用列表
-     */
-//    @ApiOperation(value = "人员借用列表")
-//    @GetMapping("/userBorrowList")
-//    public AjaxResult userBorrowList(@RequestParam(required = false) String name,
-//                                     @RequestParam(required = false) Integer type)
-//    {
-//
-//        UserAddListVO userAddListVO = new UserAddListVO();
-//
-//        Long companyId = tokenService.getLoginUser().getUser().getCompanyId();
-//
-//        List<TCompany> companyList = new ArrayList<>();
-//        List<TDept> deptList = new ArrayList<>();
-//        List<SysUser> userList = new ArrayList<>();
-//        // 查询公司
-//        if(Objects.nonNull(type) && type == 1){
-//            companyList = companyService.userAddListByCompanyName(name);
-//        }
-//        // 查询部门
-//        if(Objects.nonNull(type) && type == 2){
-//            deptList = tDeptService.userAddListByDeptName(name);
-//        }
-//        // 查询用户
-//        if(Objects.nonNull(type) && type == 3){
-//            userList = userService.selectListByNamePhone(name);
-//        }
-//
-//        if(Objects.isNull(type)){
-//            companyList = companyService.userAddListByCompanyName(name);
-//            deptList = tDeptService.userAddListByDeptName(name);
-//            userList = userService.selectListByNamePhone(name);
-//        }
-//
-//        List<Long> companyIds = companyList.stream().map(TCompany::getId).collect(Collectors.toList());
-//        List<Long> deptCompanyIds = deptList.stream().map(TDept::getCompanyId).collect(Collectors.toList());
-//        List<Long> userCompanyIds = userList.stream().map(SysUser::getCompanyId).collect(Collectors.toList());
-//        companyIds.addAll(deptCompanyIds);
-//        companyIds.addAll(userCompanyIds);
-//
-//        companyIds = companyIds.stream().distinct().collect(Collectors.toList());
-//
-//        if(CollectionUtils.isEmpty(companyIds)){
-//            return AjaxResult.success(userAddListVO);
-//        }
-//        SysUser user1 = tokenService.getLoginUser().getUser();
-//        if(!user1.isAdmin()){
-//            companyIds = companyIds.stream().filter(e->!e.equals(companyId)).collect(Collectors.toList());
-//        }
-//
-//        // 查询符合要求的公司
-//        List<UserLevelVO> parent = companyService.userAddListByCompanyIds(companyIds);
-//
-//        List<TDept> depts = tDeptService.selectList();
-//
-//        List<SysUser> sysUsers = userService.selectList();
-//
-//        for (UserLevelVO userLevelVO : parent) {
-//
-//            // 找到公司下的部门
-//            List<TDept> tDepts = depts.stream().filter(e -> userLevelVO.getKey().equals(e.getCompanyId())).collect(Collectors.toList());
-//            List<UserLevelVO> children = new ArrayList<>();
-//            // 封装部门
-//            for (TDept dept : tDepts) {
-//                userLevelVO.setChildren(children);
-//                UserLevelVO userLevelVO1 = new UserLevelVO();
-//                userLevelVO1.setKey(dept.getId());
-//                userLevelVO1.setTitle(dept.getDeptName());
-//                // 找到部门下的人员
-//                List<SysUser> users;
-//                if(StringUtils.isNotEmpty(name) && type == 3){
-//                    users = sysUsers.stream().filter(e -> userLevelVO1.getKey().equals(e.getDeptId())
-//                            && ((StringUtils.isNotEmpty(e.getNickName()) && e.getNickName().contains(name)))
-//                            || (StringUtils.isNotEmpty(e.getPhonenumber()) && e.getPhonenumber().contains(name))).collect(Collectors.toList());
-//                }else {
-//                    users = sysUsers.stream().filter(e -> userLevelVO1.getKey().equals(e.getDeptId())).collect(Collectors.toList());
-//                }
-//                List<UserLevelVO> children1 = new ArrayList<>();
-//                // 封装人员
-//                for (SysUser user : users) {
-//                    UserLevelVO userLevelVO2 = new UserLevelVO();
-//                    userLevelVO2.setKey(user.getUserId());
-//                    userLevelVO2.setTitle(user.getNickName());
-//                    userLevelVO2.setAvatar(user.getAvatar());
-//                    userLevelVO2.setFlag(true);
-//                    children1.add(userLevelVO2);
-//                }
-//                userLevelVO1.setChildren(children1);
-//
-//                children.add(userLevelVO1);
-//            }
-//            userLevelVO.setChildren(children);
-//        }
-//        userAddListVO.setUserLevelVOS(parent);
-//        userAddListVO.setUserList(sysUsers);
-//        return AjaxResult.success(userAddListVO);
-//    }
-
-    /**
      * 获取用户详情
      */
     @ApiOperation(value = "获取用户详情")
@@ -245,37 +146,6 @@
         return AjaxResult.success();
     }
 
-
-//    @Log(title = "用户管理", businessType = BusinessType.EXPORT)
-////    // @PreAuthorize("@ss.hasPermi('system:user:export')")
-//    @PostMapping("/export")
-//    public void export(HttpServletResponse response, SysUser user)
-//    {
-//        List<SysUser> list = userService.selectUserList(user);
-//        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
-//        util.exportExcel(response, list, "用户数据");
-//    }
-
-//    @Log(title = "用户管理", businessType = BusinessType.IMPORT)
-////    // @PreAuthorize("@ss.hasPermi('system:user:import')")
-//    @PostMapping("/importData")
-//    public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
-//    {
-//        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
-//        List<SysUser> userList = util.importExcel(file.getInputStream());
-//        String operName = getUsername();
-//        String message = userService.importUser(userList, updateSupport, operName);
-//        return AjaxResult.success(message);
-//    }
-
-//    @PostMapping("/importTemplate")
-//    public void importTemplate(HttpServletResponse response)
-//    {
-//        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
-//        util.importTemplateExcel(response, "用户数据");
-//    }
-
-
     /**
      * 新增用户
      */
@@ -295,7 +165,7 @@
             return error("新增用户'" + user.getUserName() + "'失败,手机号码已存在");
         }
         user.setCreateBy(getUsername());
-        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
+        user.setPassword(SecurityUtils.encryptPassword("123456"));
         userService.insertUser(user);
         return AjaxResult.success();
     }
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/TaskUtil.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/TaskUtil.java
index 05076e9..a878cdb 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/TaskUtil.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/TaskUtil.java
@@ -51,17 +51,16 @@
                 long hours = ChronoUnit.HOURS.between(payableFeesTime, now);
                 long l = hours / 72;
                 if (l>0){
-                    // 计算每天租金
-                    long days = ChronoUnit.DAYS.between(tBill.getStartTime(),tBill.getEndTime());
-                    BigDecimal everyDayMoney = tBill.getPayableFeesMoney().divide(new BigDecimal(days), 2, BigDecimal.ROUND_DOWN);
                     // 违约金比例
                     BigDecimal proportion = contract.getProportion();
-                    // 预期x天后的违约金
-                    BigDecimal money = everyDayMoney.multiply(proportion).multiply(new BigDecimal(l));
-                    tBill.setPayableFeesPenalty(money);
+                    // 应缴违约金
+                    BigDecimal money = tBill.getOutstandingMoney().multiply(proportion);
+                    TBill changeBill = new TBill();
+                    changeBill.setId(tBill.getId());
+                    changeBill.setPayableFeesPenalty(money);
+                    billService.lockAndUpdateInfo(changeBill,2);
                 }
             }
-            billService.updateBatchById(list);
 
         } catch (Exception e) {
             e.printStackTrace();
@@ -69,497 +68,24 @@
     }
 
 
-    // 每天凌晨00点执行的定时任务 用于合同生成第一笔账单
-    @Scheduled(cron = "0 0 0 * * ?")
-    public void dayOfFirstBill() {
-        try {
-            // 查询所有已签订的合同并且未生成第一笔账单的
-            List<TContract> list = contractService.lambdaQuery().eq(TContract::getStatus, 4)
-                    .isNull(TContract::getFirstPayTime).list();
-            List<TBill> bills = new ArrayList<>();
-            List<TContractRentType> contractRentTypes = contractRentTypeService.list();
-            for (TContract contract : list) {
-                contract.setFirstPayTime(contract.getStartTime().plusDays(10));
-                // 第一次应缴费日期
-                LocalDateTime firstPayTime = contract.getStartTime().plusDays(10).withHour(0).withMinute(0).withSecond(0);
-                LocalDate localDate = contract.getStartTime().plusDays(10).toLocalDate();
-                LocalDate now = LocalDate.now();
-                // 如果应缴费日期和当前时间不相同 跳过
-                if (!localDate.equals(now)) {
-                    continue;
-                }
-                TBill rentBill = new TBill();
-                rentBill.setContractId(contract.getId());
-                rentBill.setContractNumber(contract.getContractNumber());
-                LocalDateTime startPayTime = contract.getStartPayTime();
-                LocalDateTime endTime1 = contract.getEndTime();
-//                // 计算两个时间相差多少天
-//                // 如果时间小于30天 需要计算每日租金
-//                if (days<30){
-//                    rentBill.setPayableFeesMoney(contract.getMonthRent().divide(new BigDecimal("30"),2,BigDecimal.ROUND_DOWN).multiply(new BigDecimal(days)));
-//                }else{
-//                    rentBill.setPayableFeesMoney(contract.getPayType().equals("1")?contract.getMonthRent():
-//                            contract.getPayType().equals("2")?contract.getMonthRent().multiply(new BigDecimal("3")):contract.getMonthRent().multiply(new BigDecimal("12")).setScale(2,BigDecimal.ROUND_DOWN));
-//                }
-                rentBill.setPayableFeesTime(firstPayTime);
-                rentBill.setPayFeesStatus("1");
-                rentBill.setBillType("1");
-                rentBill.setStartTime(contract.getStartPayTime());
-                TContractRentType tContractRentType = contractRentTypes.stream().filter(e -> e.getContractId().equals(contract.getId())).findFirst().orElse(null);
 
-                if (tContractRentType!=null && contract.getStartPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).isAfter(tContractRentType.getChangeTime())){
-                    // 计算租金变动的天数
-                    long moneyDays = ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), contract.getStartPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12))+1L;
-                    contract.setChangeTime(LocalDateTime.now());
-                    // 递增递减的租金
-                    BigDecimal contractRentTypeMoney = new BigDecimal("0");
-                    // 不递增递减的租金
-                    BigDecimal originalMoney = new BigDecimal("0");
-                    // 原租金
-                    switch (tContractRentType.getIncreasingDecreasingType()){
-                        case 1:
-                            switch (tContractRentType.getIncreasingDecreasing()){
-                                case 1:
-                                    contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue()).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN)).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)));
-                                    contract.setChangeRent(contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue()).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN))));
-                                    break;
-                                case 2:
-                                    contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).subtract(tContractRentType.getNumericalValue()).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN)).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)));
-                                    contract.setChangeRent(contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).subtract(tContractRentType.getNumericalValue()).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN))));
-                                    break;
-                            }
-                            break;
-                        case 2:
-                            switch (tContractRentType.getIncreasingDecreasing()){
-                                case 1:
-                                    contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                                    contract.setChangeRent(contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())));
-                                    break;
-                                case 2:
-                                    contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                                    contract.setChangeRent(contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())));
-
-                                    break;
-                            }
-                            break;
-                    }
-                    // 不需要涨租金的时间段
-                    long originalDays = ChronoUnit.DAYS.between(contract.getFirstPayTime(), tContractRentType.getChangeTime());
-                    originalMoney=originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
-                            .multiply(new BigDecimal(originalDays));
-                    rentBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
-                    if (contract.getFirstPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).isAfter(contract.getEndTime())){
-                        rentBill.setEndTime(contract.getFirstPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12));
-                    }else{
-                        rentBill.setEndTime(contract.getEndTime());
-                    }
-                }else{
-                    if (contract.getFirstPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).isAfter(contract.getEndTime())){
-                        rentBill.setEndTime(contract.getFirstPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12));
-                    }else{
-                        rentBill.setEndTime(contract.getEndTime());
-                    }
-                    // 不走递增递减
-                    long allDays = ChronoUnit.DAYS.between(contract.getFirstPayTime(), rentBill.getEndTime());
-                    rentBill.setPayableFeesMoney(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(allDays)));
-                }
-                // 租金账单
-                bills.add(rentBill);
-                // 押金账单
-                TBill depositBill = new TBill();
-                depositBill.setContractId(contract.getId());
-                depositBill.setContractNumber(contract.getContractNumber());
-                depositBill.setPayableFeesMoney(contract.getDeposit());
-                depositBill.setPayableFeesTime(firstPayTime);
-                depositBill.setPayFeesStatus("1");
-                depositBill.setBillType("2");
-                bills.add(depositBill);
-            }
-            contractService.updateBatchById(list);
-            billService.saveBatch(bills);
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-    }
-
-    // 每天凌晨00点执行的定时任务 用于生成合同期最后一笔账单
+    // 每天凌晨00点执行的定时任务 根据应缴费日期修改账单状态
     @Scheduled(cron = "0 0 0 * * ?")
     public void dayOfEndBill() {
         try {
-            // 查询所有已签订的合同并且已经生成第一笔账单的
-            List<TContract> list = contractService.lambdaQuery().eq(TContract::getStatus, 4)
-                    .ge(TContract::getEndTime,LocalDateTime.now())
-                    .isNotNull(TContract::getFirstPayTime).list();
-            List<TContractRentType> contractRentTypes = contractRentTypeService.list();
-            List<TBill> bills = new ArrayList<>();
-            for (TContract contract : list) {
-                TBill beforeBill = billService.lambdaQuery().eq(TBill::getContractId, contract.getId()).eq(TBill::getBillType, 1).orderByDesc(TBill::getCreateTime)
-                        .last("limit 1").one();
-                if (!(beforeBill.getEndTime().toLocalDate().equals(contract.getEndTime().toLocalDate()))
-                    &&
-                        (contract.getPayType().equals("1")?
-                        beforeBill.getEndTime().plusMonths(1):contract.getPayType().equals("2")?
-                        beforeBill.getEndTime().plusMonths(3):beforeBill.getEndTime().plusMonths(12))
-                        .with(TemporalAdjusters.lastDayOfMonth()).isAfter(contract.getEndTime())
-                && beforeBill.getEndTime().isBefore(contract.getEndTime())
-                ){
-                    TBill tBill = new TBill();
-                    tBill.setContractId(contract.getId());
-                    long days = ChronoUnit.DAYS.between((contract.getPayType().equals("1")?
-                            beforeBill.getEndTime().plusMonths(1):contract.getPayType().equals("2")?
-                            beforeBill.getEndTime().plusMonths(3):beforeBill.getEndTime().plusMonths(12)).with(TemporalAdjusters.firstDayOfMonth()), contract.getEndTime())+1L;
-                    if (contract.getIsIncreasing()){
-                        TContractRentType tContractRentType = contractRentTypes.stream().filter(e -> e.getContractId().equals(contract.getId())).findFirst().orElse(null);
-                        if (tContractRentType!=null
-                                && beforeBill.getEndTime().isBefore(tContractRentType.getChangeTime())
-                                && beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).with(TemporalAdjusters.lastDayOfMonth()).isAfter(tContractRentType.getChangeTime())){
-                            // 如果没变过
-                            if (contract.getChangeTime()==null){
-                                contract.setChangeTime(LocalDateTime.now());
-                                // 租金递增递减的时长 天
-                                long moneyDays = ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), contract.getEndTime());
-                                // 递增递减的租金
-                                BigDecimal contractRentTypeMoney = new BigDecimal("0");
-                                // 不递增递减的租金
-                                BigDecimal originalMoney = new BigDecimal("0");
-                                // 原租金
-                                switch (tContractRentType.getIncreasingDecreasingType()){
-                                    case 1:
-                                        switch (tContractRentType.getIncreasingDecreasing()){
-                                            case 1:
-                                                contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue()).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN)).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(days)));
-                                                contract.setChangeRent(contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue()).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN))));
-                                                break;
-                                            case 2:
-                                                contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).subtract(tContractRentType.getNumericalValue()).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN)).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(days)));
-                                                contract.setChangeRent(contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).subtract(tContractRentType.getNumericalValue()).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN))));
-                                                break;
-                                        }
-                                        break;
-                                    case 2:
-                                        switch (tContractRentType.getIncreasingDecreasing()){
-                                            case 1:
-                                                contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                                                contract.setChangeRent(contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())));
-                                                break;
-                                            case 2:
-                                                contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                                                contract.setChangeRent(contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())));
-
-                                                break;
-                                        }
-                                        break;
-                                }
-                                // 不需要涨租金的时间段
-                                long originalDays = ChronoUnit.DAYS.between(beforeBill.getEndTime(), tContractRentType.getChangeTime());
-                                originalMoney=originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
-                                        .multiply(new BigDecimal(originalDays));
-                                tBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
-                            }else{
-                                // 之前已经涨、跌过租金了 需要判断周期是否还需要再涨、跌
-                                if ((LocalDateTime.now().getYear() - contract.getChangeTime().getYear())%tContractRentType.getCycleTime()==0){
-                                    contract.setChangeTime(LocalDateTime.now());
-                                    // 租金递增递减的时长 天
-                                    long moneyDays = ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), contract.getEndTime());
-                                    // 递增递减的租金
-                                    BigDecimal contractRentTypeMoney = new BigDecimal("0");
-                                    // 不递增递减的租金
-                                    BigDecimal originalMoney = new BigDecimal("0");
-                                    // 原租金
-                                    switch (tContractRentType.getIncreasingDecreasingType()){
-                                        case 1:
-                                            switch (tContractRentType.getIncreasingDecreasing()){
-                                                case 1:
-                                                    contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue()).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN)).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(days)));
-                                                    contract.setChangeRent(contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue()).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN))));
-                                                    break;
-                                                case 2:
-                                                    contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).subtract(tContractRentType.getNumericalValue()).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN)).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(days)));
-                                                    contract.setChangeRent(contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).subtract(tContractRentType.getNumericalValue()).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN))));
-                                                    break;
-                                            }
-                                            break;
-                                        case 2:
-                                            switch (tContractRentType.getIncreasingDecreasing()){
-                                                case 1:
-                                                    contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                                                    contract.setChangeRent(contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())));
-                                                    break;
-                                                case 2:
-                                                    contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                                                    contract.setChangeRent(contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())));
-
-                                                    break;
-                                            }
-                                            break;
-                                    }
-                                    // 不需要涨租金的时间段
-                                    long originalDays = ChronoUnit.DAYS.between(beforeBill.getEndTime(), tContractRentType.getChangeTime());
-                                    originalMoney=originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
-                                            .multiply(new BigDecimal(originalDays));
-                                    tBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
-                                }else{
-                                    // 不涨租金 用上次的
-                                    // 租金递增递减的时长 天
-                                    long moneyDays = ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), contract.getEndTime());
-                                    // 递增递减的租金
-                                    BigDecimal contractRentTypeMoney = new BigDecimal("0");
-                                    // 不递增递减的租金
-                                    BigDecimal originalMoney = new BigDecimal("0");
-                                    // 原租金
-                                    switch (tContractRentType.getIncreasingDecreasingType()){
-                                        case 1:
-                                            switch (tContractRentType.getIncreasingDecreasing()){
-                                                case 1:
-                                                    contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(days))) ;
-                                                    break;
-                                                case 2:
-                                                    contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(days)));
-                                                    break;
-                                            }
-                                            break;
-                                        case 2:
-                                            switch (tContractRentType.getIncreasingDecreasing()){
-                                                case 1:
-                                                    contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent()).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                                                    break;
-                                                case 2:
-                                                    contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent()).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                                                    break;
-                                            }
-                                            break;
-                                    }
-                                    // 不需要涨租金的时间段
-                                    long originalDays = ChronoUnit.DAYS.between(beforeBill.getEndTime(), tContractRentType.getChangeTime());
-                                    originalMoney=originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
-                                            .multiply(new BigDecimal(originalDays));
-                                    tBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
-                                }
-                            }
-
-                        }
-                    }else{
-                        long allDays = ChronoUnit.DAYS.between(beforeBill.getEndTime(), contract.getEndTime());
-                        tBill.setPayableFeesMoney(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(allDays)));
-                    }
-                    tBill.setContractNumber(contract.getContractNumber());
-                    if (beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).getDayOfMonth()<=15){
-                        tBill.setPayableFeesTime(contract.getEndTime().withHour(0).withMinute(0).withSecond(0));
-                    }else{
-                        tBill.setPayableFeesTime((contract.getPayType().equals("1")?
-                                beforeBill.getEndTime().plusMonths(1).withDayOfMonth(15):contract.getPayType().equals("2")?
-                                beforeBill.getEndTime().plusMonths(3).withDayOfMonth(15):beforeBill.getEndTime().withDayOfMonth(15).plusMonths(12).withHour(0).withMinute(0).withSecond(0)));
-                    }
+            List<TBill> list = billService.lambdaQuery().eq(TBill::getPayFeesStatus, "2").list();
+            for (TBill tBill : list) {
+                if (tBill.getPayableFeesTime().toLocalDate().equals(LocalDate.now())){
                     tBill.setPayFeesStatus("1");
-                    tBill.setBillType("1");
-                    tBill.setStartTime(beforeBill.getEndTime().plusDays(1));
-                    tBill.setEndTime(beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12));
-                    bills.add(tBill);
                 }
             }
-            billService.saveBatch(bills);
+            billService.updateBatchById(list);
         } catch (Exception e) {
             e.printStackTrace();
         }
     }
 
-    // 每月15号凌晨执行的定时任务 用于生成租金账单
-    @Scheduled(cron = "0 0 0 15 * ?")
-    public void monthOfBill() {
-        try {
-            // 查询所有已签订的合同
-            List<TContract> list = contractService.lambdaQuery().eq(TContract::getStatus, 4)
-                    .isNotNull(TContract::getFirstPayTime)
-                    .ge(TContract::getEndTime, LocalDateTime.now())
-                    .list();
-            List<TContractRentType> contractRentTypes = contractRentTypeService.list();
 
-            List<TBill> bills = new ArrayList<>();
-            for (TContract contract : list) {
-                TBill beforeBill = billService.lambdaQuery().eq(TBill::getContractId, contract.getId()).eq(TBill::getBillType, 1).orderByDesc(TBill::getCreateTime)
-                        .last("limit 1").one();
-                if (beforeBill.getEndTime().toLocalDate().equals(contract.getEndTime().toLocalDate()))continue;
-                if (beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).with(TemporalAdjusters.lastDayOfMonth()).isBefore(contract.getEndTime())){
-                    TBill tBill = new TBill();
-                    tBill.setContractId(contract.getId());
-                    tBill.setContractNumber(contract.getContractNumber());
-                    // 根据支付方式判断需不需要生成订单
-                    if (!(beforeBill.getEndTime().toLocalDate().equals(contract.getEndTime().toLocalDate()))
-                            &&
-                            (contract.getPayType().equals("1")?
-                                    beforeBill.getEndTime().plusMonths(1):contract.getPayType().equals("2")?
-                                    beforeBill.getEndTime().plusMonths(3):beforeBill.getEndTime().plusMonths(12))
-                                    .with(TemporalAdjusters.lastDayOfMonth()).isBefore(contract.getEndTime())
-                            && beforeBill.getEndTime().isBefore(contract.getEndTime())
-                    ){
-                        tBill.setContractId(contract.getId());
-                        long days = ChronoUnit.DAYS.between(beforeBill.getEndTime(), (contract.getPayType().equals("1")?
-                                beforeBill.getEndTime().plusMonths(1):contract.getPayType().equals("2")?
-                                beforeBill.getEndTime().plusMonths(3):beforeBill.getEndTime().plusMonths(12)).with(TemporalAdjusters.lastDayOfMonth()))+1L;
-                        if (contract.getIsIncreasing()){
-                            TContractRentType tContractRentType = contractRentTypes.stream().filter(e -> e.getContractId().equals(contract.getId())).findFirst().orElse(null);
-                            if (tContractRentType!=null
-                                    && beforeBill.getEndTime().isBefore(tContractRentType.getChangeTime())
-                                    && beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).with(TemporalAdjusters.lastDayOfMonth()).isAfter(tContractRentType.getChangeTime())){
-                                // 如果没变过
-                                if (contract.getChangeTime()==null){
-                                    contract.setChangeTime(LocalDateTime.now());
-                                    // 租金递增递减的时长 天
-                                    long moneyDays = ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), contract.getEndTime());
-                                    // 递增递减的租金
-                                    BigDecimal contractRentTypeMoney = new BigDecimal("0");
-                                    // 不递增递减的租金
-                                    BigDecimal originalMoney = new BigDecimal("0");
-                                    // 原租金
-                                    switch (tContractRentType.getIncreasingDecreasingType()){
-                                        case 1:
-                                            switch (tContractRentType.getIncreasingDecreasing()){
-                                                case 1:
-                                                    contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue()).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN)).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(days)));
-                                                    contract.setChangeRent(contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue()).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN))));
-                                                    break;
-                                                case 2:
-                                                    contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).subtract(tContractRentType.getNumericalValue()).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN)).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(days)));
-                                                    contract.setChangeRent(contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).subtract(tContractRentType.getNumericalValue()).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN))));
-                                                    break;
-                                            }
-                                            break;
-                                        case 2:
-                                            switch (tContractRentType.getIncreasingDecreasing()){
-                                                case 1:
-                                                    contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                                                    contract.setChangeRent(contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())));
-                                                    break;
-                                                case 2:
-                                                    contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                                                    contract.setChangeRent(contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())));
-
-                                                    break;
-                                            }
-                                            break;
-                                    }
-                                    // 不需要涨租金的时间段
-                                    long originalDays = ChronoUnit.DAYS.between(beforeBill.getEndTime(), tContractRentType.getChangeTime());
-                                    originalMoney=originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
-                                            .multiply(new BigDecimal(originalDays));
-                                    tBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
-                                }else{
-                                    // 之前已经涨、跌过租金了 需要判断周期是否还需要再涨、跌
-                                    if ((LocalDateTime.now().getYear() - contract.getChangeTime().getYear())%tContractRentType.getCycleTime()==0){
-                                        contract.setChangeTime(LocalDateTime.now());
-                                        // 租金递增递减的时长 天
-                                        long moneyDays = ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), contract.getEndTime());
-                                        // 递增递减的租金
-                                        BigDecimal contractRentTypeMoney = new BigDecimal("0");
-                                        // 不递增递减的租金
-                                        BigDecimal originalMoney = new BigDecimal("0");
-                                        // 原租金
-                                        switch (tContractRentType.getIncreasingDecreasingType()){
-                                            case 1:
-                                                switch (tContractRentType.getIncreasingDecreasing()){
-                                                    case 1:
-                                                        contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue()).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN)).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(days)));
-                                                        contract.setChangeRent(contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue()).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN))));
-                                                        break;
-                                                    case 2:
-                                                        contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).subtract(tContractRentType.getNumericalValue()).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN)).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(days)));
-                                                        contract.setChangeRent(contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).subtract(tContractRentType.getNumericalValue()).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN))));
-                                                        break;
-                                                }
-                                                break;
-                                            case 2:
-                                                switch (tContractRentType.getIncreasingDecreasing()){
-                                                    case 1:
-                                                        contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                                                        contract.setChangeRent(contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())));
-                                                        break;
-                                                    case 2:
-                                                        contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                                                        contract.setChangeRent(contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())));
-
-                                                        break;
-                                                }
-                                                break;
-                                        }
-                                        // 不需要涨租金的时间段
-                                        long originalDays = ChronoUnit.DAYS.between(beforeBill.getEndTime(), tContractRentType.getChangeTime());
-                                        originalMoney=originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
-                                                .multiply(new BigDecimal(originalDays));
-                                        tBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
-                                    }else{
-                                        // 不涨租金 用上次的
-                                        // 租金递增递减的时长 天
-                                        long moneyDays = ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), contract.getEndTime());
-                                        // 递增递减的租金
-                                        BigDecimal contractRentTypeMoney = new BigDecimal("0");
-                                        // 不递增递减的租金
-                                        BigDecimal originalMoney = new BigDecimal("0");
-                                        // 原租金
-                                        switch (tContractRentType.getIncreasingDecreasingType()){
-                                            case 1:
-                                                switch (tContractRentType.getIncreasingDecreasing()){
-                                                    case 1:
-                                                        contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(days))) ;
-                                                        break;
-                                                    case 2:
-                                                        contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(days)));
-                                                        break;
-                                                }
-                                                break;
-                                            case 2:
-                                                switch (tContractRentType.getIncreasingDecreasing()){
-                                                    case 1:
-                                                        contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent()).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                                                        break;
-                                                    case 2:
-                                                        contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent()).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
-                                                        break;
-                                                }
-                                                break;
-                                        }
-                                        // 不需要涨租金的时间段
-                                        long originalDays = ChronoUnit.DAYS.between(beforeBill.getEndTime(), tContractRentType.getChangeTime());
-                                        originalMoney=originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
-                                                .multiply(new BigDecimal(originalDays));
-                                        tBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
-                                    }
-                                }
-
-                            }
-                        }else{
-                            long allDays = ChronoUnit.DAYS.between(beforeBill.getEndTime(), (contract.getPayType().equals("1")?
-                                    beforeBill.getEndTime().plusMonths(1):contract.getPayType().equals("2")?
-                                    beforeBill.getEndTime().plusMonths(3):beforeBill.getEndTime().plusMonths(12)).with(TemporalAdjusters.lastDayOfMonth()));
-                            tBill.setPayableFeesMoney(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(allDays)));
-                        }
-                        tBill.setContractNumber(contract.getContractNumber());
-                        if (beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).getDayOfMonth()<=15){
-                            tBill.setPayableFeesTime(contract.getEndTime());
-                        }else{
-                            tBill.setPayableFeesTime((contract.getPayType().equals("1")?
-                                    beforeBill.getEndTime().plusMonths(1).withDayOfMonth(15):contract.getPayType().equals("2")?
-                                    beforeBill.getEndTime().plusMonths(3).withDayOfMonth(15):beforeBill.getEndTime().withDayOfMonth(15).plusMonths(12)));
-                        }
-                        tBill.setPayFeesStatus("1");
-                        tBill.setBillType("1");
-                        tBill.setStartTime(beforeBill.getEndTime().plusDays(1));
-                        tBill.setEndTime(contract.getEndTime());
-                        bills.add(tBill);
-                    }
-                    tBill.setPayableFeesMoney(contract.getMonthRent().multiply(new BigDecimal("3")));
-                    tBill.setPayableFeesTime(LocalDateTime.now().withHour(0).withMinute(0).withSecond(0));
-                    tBill.setPayFeesStatus("1");
-                    tBill.setBillType("1");
-                    tBill.setStartTime(beforeBill.getEndTime().plusMonths(1).with(TemporalAdjusters.firstDayOfMonth()));
-                    tBill.setEndTime(beforeBill.getEndTime().plusMonths(1).with(TemporalAdjusters.lastDayOfMonth()));
-                    bills.add(tBill);
-                }
-            }
-            billService.saveBatch(bills);
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-    }
 
 
     public static void main(String[] args) {
diff --git a/ruoyi-admin/src/main/resources/application-test.yml b/ruoyi-admin/src/main/resources/application-test.yml
index 4ca4b21..93fd2c2 100644
--- a/ruoyi-admin/src/main/resources/application-test.yml
+++ b/ruoyi-admin/src/main/resources/application-test.yml
@@ -193,9 +193,9 @@
     accessPath: /file/
     allowExt: .jpg|.png|.gif|.jpeg|.doc|.docx|.apk|.MP4|.mp4|.pdf|.PDF
 wx:
-  config:
-    appId: wxc3985a05da7d86dc
-    secret: 5cca42633c25439613b328c08ef20cc9
+  conf:
+    appId: wxe91f1af7638aa5dd
+    secretId: a787e1a462715604e0c9528b6d8960d1
 #OSS及短信配置
 code:
   config:
diff --git a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/COSController.java b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/COSController.java
new file mode 100644
index 0000000..3d7d593
--- /dev/null
+++ b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/COSController.java
@@ -0,0 +1,55 @@
+package com.ruoyi.web.controller.api;
+
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.web.controller.tool.TencentCosUtil;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+
+/**
+ * @author HJL
+ * @version 1.0
+ * @since 2024-05-30 9:27
+ */
+@RestController
+@RequestMapping("/cos")
+@Api(tags = "公共-文件上传")
+public class COSController {
+
+    @Resource
+    private TencentCosUtil tencentCosUtil;
+
+    @PostMapping("/upload")
+    @ApiOperation(value = "文件上传", tags = "公共-文件上传")
+    @ApiImplicitParams({
+            @ApiImplicitParam(value = "文件", name = "file", dataType = "MultipartFile", required = true)
+    })
+    public R<String> upload(@RequestParam("file") MultipartFile file) {
+        String url = tencentCosUtil.upLoadFile(file);
+        return R.ok(url, url);
+    }
+    @PostMapping("/downloadImg")
+    @ApiOperation(value = "文件下载", tags = "公共-文件下载")
+    @ApiImplicitParams({
+            @ApiImplicitParam(value = "文件url", name = "url", dataType = "String", required = true)
+    })
+    public String downloadImg(@RequestParam("url") String url) {
+       return tencentCosUtil.downLoadFileImg(url);
+    }
+    @PostMapping("/download")
+    @ApiOperation(value = "文件下载", tags = "公共-文件下载")
+    @ApiImplicitParams({
+            @ApiImplicitParam(value = "文件url", name = "url", dataType = "String", required = true)
+    })
+    public void download(@RequestParam("url") String url) {
+        tencentCosUtil.downLoadFile(url);
+    }
+}
diff --git a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TBillController.java b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TBillController.java
index 98558e2..c90ea72 100644
--- a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TBillController.java
+++ b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TBillController.java
@@ -55,9 +55,8 @@
     @ApiOperation(value = "缴费账单查询分页列表")
     @PostMapping("list")
     public R<PageInfo<TBillDto>> list(@RequestBody TBillQuery query){
-        if (StringUtils.isEmpty(query.getUserId())){
-            throw new ServiceException("用户ID不能为空");
-        }
+        String userId = tokenService.getLoginUserApplet().getUserId();
+        query.setUserId(userId);
         PageInfo<TBillDto> pageInfo = tBillService.queryPage(query);
         return R.ok(pageInfo);
     }
@@ -65,9 +64,8 @@
     @ApiOperation(value = "缴费账单查询列表")
     @PostMapping("/getBillIds")
     public R<List<String>> getBillIds(@RequestBody TBillQuery query){
-        if (StringUtils.isEmpty(query.getUserId())){
-            throw new ServiceException("用户ID不能为空");
-        }
+        String userId = tokenService.getLoginUserApplet().getUserId();
+        query.setUserId(userId);
         List<String> billIds = tBillService.getBillIds(query);
         return R.ok(billIds);
     }
@@ -90,9 +88,14 @@
             billVO.setHouse(houseService.getById(contract.getHouseId()));
             billVO.setMonthRent(contract.getMonthRent());
             billVO.setPayType(contract.getPayType());
+            billVO.setDeposit(contract.getDeposit());
+            billVO.setPartyOnePerson(contract.getPartyOnePerson());
+            billVO.setPartyOnePhone(contract.getPartyOnePhone());
+            billVO.setConcatStartTime(contract.getStartTime());
+            billVO.setConcatEndTime(contract.getEndTime());
         });
         billVO.setBillType(DictUtils.getDictLabel(DictConstants.DICT_TYPE_BILL_TYPE,billVO.getBillType()));
-        billVO.setPayFeesStatus(DictUtils.getDictLabel(DictConstants.DICT_TYPE_PAY_FEES_STATUS,billVO.getPayFeesStatus()));
+//        billVO.setPayFeesStatus(DictUtils.getDictLabel(DictConstants.DICT_TYPE_PAY_FEES_STATUS,billVO.getPayFeesStatus()));
         return R.ok(billVO);
     }
 
@@ -119,8 +122,7 @@
     @PostMapping(value = "/invoiceList")
     public R<PageInfo<TBillDto>> invoiceList(@RequestBody TBillQuery query) {
 
-//        Long userId = tokenService.getLoginUser().getUserId();
-        String userId = "1881967035070177281";
+        String userId = tokenService.getLoginUserApplet().getUserId();
         query.setUserId(userId);
         PageInfo<TBillDto> pageInfo = tBillService.invoiceList(query);
         return R.ok(pageInfo);
diff --git a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TFaultRepairMessageController.java b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TFaultRepairMessageController.java
index 963d22b..9ea04c2 100644
--- a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TFaultRepairMessageController.java
+++ b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TFaultRepairMessageController.java
@@ -1,9 +1,26 @@
 package com.ruoyi.web.controller.api;
 
 
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.framework.web.service.TokenService;
+import com.ruoyi.system.dto.TFaultRepairMessageDTO;
+import com.ruoyi.system.model.*;
+import com.ruoyi.system.service.*;
+import com.ruoyi.system.vo.TFaultAreaDicVO;
+import com.ruoyi.system.vo.TItemTypeVO;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 
 import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -13,9 +30,94 @@
  * @author xiaochen
  * @since 2025-01-17
  */
+@Api(tags = "报修管理")
 @RestController
 @RequestMapping("/t-fault-repair-message")
 public class TFaultRepairMessageController {
 
+    private final TFaultRepairMessageService tFaultRepairMessageService;
+    private final TItemService itemService;
+    private final TItemTypeService itemTypeService;
+    private final TFaultAreaDicService faultAreaDicService;
+    private final TFaultDescribeDicService faultDescribeDicService;
+    private final TokenService tokenService;
+    private final TContractService contractService;
+    private final THouseService houseService;
+
+    @Autowired
+    public TFaultRepairMessageController(TFaultRepairMessageService tFaultRepairMessageService, TItemService itemService, TItemTypeService itemTypeService, TFaultAreaDicService faultAreaDicService, TFaultDescribeDicService faultDescribeDicService, TokenService tokenService, TContractService contractService, THouseService houseService) {
+        this.tFaultRepairMessageService = tFaultRepairMessageService;
+        this.itemService = itemService;
+        this.itemTypeService = itemTypeService;
+        this.faultAreaDicService = faultAreaDicService;
+        this.faultDescribeDicService = faultDescribeDicService;
+        this.tokenService = tokenService;
+        this.contractService = contractService;
+        this.houseService = houseService;
+    }
+
+    /**
+     * 获取维修物品二级结构
+     */
+    @ApiOperation(value = "获取维修物品二级结构")
+    @PostMapping(value = "/getItemList")
+    public R<List<TItemTypeVO>> getItemList() {
+        List<TItemTypeVO> itemTypes = itemTypeService.getItemList();
+        List<TItem> items = itemService.list();
+        itemTypes.forEach(itemType -> {
+            itemType.setItemList(items.stream().filter(item -> itemType.getId().equals(item.getTypeId())).collect(Collectors.toList()));
+        });
+        return R.ok(itemTypes);
+    }
+
+    /**
+     * 获取故障区域列表
+     */
+    @ApiOperation(value = "获取故障区域二级结构")
+    @PostMapping(value = "/getAreaDicList")
+    public R<List<TFaultAreaDicVO>> getAreaDicList() {
+        List<TFaultAreaDicVO> faultAreaDicVOS = faultAreaDicService.getAreaDicList();
+        List<TFaultDescribeDic> faultDescribeDicList = faultDescribeDicService.list();
+        faultAreaDicVOS.forEach(areaDicVO -> {
+            areaDicVO.setFaultDescribeDicList(faultDescribeDicList.stream().filter(item -> areaDicVO.getId().equals(item.getFaultId())).collect(Collectors.toList()));
+        });
+        return R.ok(faultAreaDicVOS);
+    }
+
+    /**
+     * 通过当前租户查询合同房源信息
+     */
+    @ApiOperation(value = "通过当前租户查询合同房源信息")
+    @PostMapping(value = "/getConcatByTenantId")
+    public R<List<TContract>> getConcatByTenantId() {
+
+//        Long userId = tokenService.getLoginUser().getUserId();
+        String tenantId = "1881967035070177281";
+        // 查询合同信息
+        List<TContract> list = contractService.list(Wrappers.lambdaQuery(TContract.class)
+                .eq(TContract::getTenantId, tenantId)
+                .eq(TContract::getStatus, 4));
+        if(CollectionUtils.isEmpty(list)){
+            return R.ok(list);
+        }
+        List<String> houseIds = list.stream().map(TContract::getHouseId).collect(Collectors.toList());
+        List<THouse> houseList = houseService.list(Wrappers.lambdaQuery(THouse.class)
+                .in(THouse::getId, houseIds));
+        list.forEach(item -> {
+            item.setHouseName(houseList.stream().filter(house -> house.getId().equals(item.getHouseId())).findFirst().orElse(new THouse()).getHouseName());
+        });
+        return R.ok(list);
+    }
+
+    /**
+     * 添加报修信息
+     */
+    @ApiOperation(value = "添加报修信息")
+    @PostMapping(value = "/addFault")
+    public R<String> addFault(@RequestBody TFaultRepairMessageDTO dto) {
+        tFaultRepairMessageService.save(dto);
+        return R.ok();
+    }
+
 }
 
diff --git a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TInformationController.java b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TInformationController.java
index dd18571..a46014a 100644
--- a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TInformationController.java
+++ b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TInformationController.java
@@ -2,19 +2,16 @@
 
 
 import com.ruoyi.common.basic.PageInfo;
+import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.redis.RedisCache;
 import com.ruoyi.system.model.TInformation;
 import com.ruoyi.system.query.TInformationQuery;
 import com.ruoyi.system.service.TInformationService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 /**
  * <p>
@@ -30,9 +27,11 @@
 public class TInformationController {
 
     private final TInformationService informationService;
+    private final RedisCache redisCache;
     @Autowired
-    public TInformationController(TInformationService informationService) {
+    public TInformationController(TInformationService informationService, RedisCache redisCache) {
         this.informationService = informationService;
+        this.redisCache = redisCache;
     }
 
     /**
@@ -44,5 +43,16 @@
         return R.ok(informationService.pageList(query));
     }
 
+    /**
+     * 获取资讯管理详情
+     */
+    @ApiOperation(value = "获取资讯管理详情")
+    @GetMapping(value = "/getDetailById")
+    public R<TInformation> getDetailById(@RequestParam String id) {
+        // 处理查看次数
+        redisCache.increment(Constants.INFORMATION_VIEW + id);
+        return R.ok(informationService.getById(id));
+    }
+
 }
 
diff --git a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/WxLoginController.java b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/WxLoginController.java
new file mode 100644
index 0000000..c784c42
--- /dev/null
+++ b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/WxLoginController.java
@@ -0,0 +1,255 @@
+package com.ruoyi.web.controller.api;
+
+import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.R;
+
+import com.ruoyi.common.core.domain.entity.SysMenu;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.common.core.domain.entity.TTenantResp;
+import com.ruoyi.common.core.domain.model.LoginBody;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.core.domain.model.LoginUserApplet;
+import com.ruoyi.common.core.utils.HttpUtils;
+import com.ruoyi.common.redis.service.RedisService;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.framework.web.service.SysLoginService;
+import com.ruoyi.framework.web.service.TokenService;
+import com.ruoyi.system.model.TTenant;
+import com.ruoyi.system.service.TTenantService;
+import com.ruoyi.system.utils.wx.body.resp.Code2SessionRespBody;
+import com.ruoyi.system.utils.wx.body.resq.Code2SessionResqBody;
+import com.ruoyi.system.utils.wx.model.WeixinProperties;
+import com.ruoyi.system.utils.wx.pojo.AppletUserDecodeData;
+import com.ruoyi.system.utils.wx.pojo.AppletUserEncrypteData;
+import com.ruoyi.system.utils.wx.tools.WxAppletTools;
+import com.ruoyi.system.utils.wx.tools.WxUtils;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.client.RestTemplate;
+
+import javax.annotation.Resource;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ *  微信小程序登录 前端控制器
+ * </p>
+ *
+ * @author xiaochen
+ * @since 2024-08-06
+ */
+@Slf4j
+@RestController
+@RequestMapping("/wxLogin")
+public class WxLoginController {
+
+    @Autowired
+    private WeixinProperties wxConfig;
+    @Autowired
+    private RestTemplate wxRestTemplate;
+    @Resource
+    private RedisService redisService;
+    @Resource
+    private TTenantService tTenantService;
+
+    /**
+     * 上传文件存储在本地的根路径
+     */
+//    @Value("${file.upload.location}")
+//    private String localFilePath;
+
+    @Resource
+    private TokenService tokenService;
+    @Autowired
+    private SysLoginService loginService;
+    /**
+     * 账号密码登录
+     *
+     * @param loginBody 登录信息
+     * @return 结果
+     */
+    @ApiOperation(value = "账号密码登录",notes = "管理员账号密码登录")
+    @PostMapping("/login")
+    public AjaxResult login(@RequestBody LoginBody loginBody)
+    {
+        AjaxResult ajax = AjaxResult.success();
+        // 生成令牌
+        LoginUser loginUser = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
+                loginBody.getUuid());
+        ajax.put(Constants.TOKEN, tokenService.createToken(loginUser));
+        List<SysRole> roles = loginUser.getUser().getRoles();
+        if(CollectionUtils.isEmpty(roles)){
+            return AjaxResult.error("请关联角色!");
+        }
+        if(roles.get(0).getStatus() == 1){
+            return AjaxResult.error("该账号角色已被禁用!");
+        }
+        return ajax;
+    }
+
+    @ApiOperation(value = "通过code获得openid,获取用户信息",tags = {"微信小程序登录"})
+    @PostMapping("/openIdByJsCode")
+    public R<Map<String, Object>> openIdByJsCode(@RequestBody AppletUserEncrypteData data) {
+        log.info("<<<<<<<<换取openid开始<<<<<<<<:{}", data.getCode());
+        WxAppletTools appletTools = new WxAppletTools(wxRestTemplate, wxConfig, redisService);
+        Code2SessionRespBody body = appletTools.getOpenIdByJscode2session(new Code2SessionResqBody().build(data.getCode()));
+        String openid = body.getOpenid();
+        String sessionKey = body.getSessionKey();
+        // 用户信息解密 数据验签
+//        if (StringUtils.isNotBlank(data.getSignature())) {
+//            WxUtils.verifySignature(data.getRawData(), sessionKey, data.getSignature());
+//        }
+        if(StringUtils.isEmpty(data.getEncryptedData()) || StringUtils.isEmpty(data.getIv())){
+            return R.fail("已拒绝授权");
+        }
+        AppletUserDecodeData appletUserDecodeData = WxUtils.encryptedData(data.getEncryptedData(), sessionKey,  data.getIv());
+        appletUserDecodeData.setOpenId(openid);
+        // 先使用openId和当前手机号进行查询
+        TTenant tenant = tTenantService.getOne(Wrappers.lambdaQuery(TTenant.class)
+                .eq(TTenant::getOpenId, appletUserDecodeData.getOpenId())
+                .eq(TTenant::getPhone, appletUserDecodeData.getPhoneNumber()));
+        if (tenant==null){
+//            appUser.setTenantAttributes();
+//            appUser.setTenantType();
+            tenant = new TTenant();
+            tenant.setPhone(appletUserDecodeData.getPhoneNumber());
+            tenant.setAccount(appletUserDecodeData.getPhoneNumber());
+            tenant.setPassword(SecurityUtils.encryptPassword(appletUserDecodeData.getPhoneNumber().substring(5)));
+            tenant.setOpenId(appletUserDecodeData.getOpenId());
+            // 手机号中间四位替换为*
+            tenant.setResidentName(appletUserDecodeData.getPhoneNumber().replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"));
+            tTenantService.save(tenant);
+        }
+        LoginUserApplet loginUserApplet = new LoginUserApplet();
+        TTenantResp tTenantResp = new TTenantResp();
+        BeanUtils.copyProperties(tenant, tTenantResp);
+        loginUserApplet.setUser(tTenantResp);
+        loginUserApplet.setUserId(tenant.getId());
+        Map<String, Object> tokenInfos = new HashMap<>();
+        tokenInfos.put("token",tokenService.createTokenApplet(loginUserApplet));
+        tokenInfos.put("info",loginUserApplet);
+        return R.ok(tokenInfos);
+    }
+    
+    
+
+
+
+//    @ApiOperation(value = "获取微信小程序二维码",tags = {"获取微信小程序二维码"})
+//    @PostMapping("/getQRCode")
+//    public AjaxResult getQRCode() {
+//        InputStream inputStream = null;
+//        OutputStream outputStream = null;
+//        WxAppletTools appletTools = new WxAppletTools(wxRestTemplate, wxConfig, redisService);
+//        String accessToken = appletTools.getAccessToken("");
+//        try {
+//            String url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + accessToken;
+//            Map<String, Object> param = new HashMap<>();
+////            param.put("page", "pageA/houseDetail");
+//            param.put("check_path", false);
+//            param.put("env_version", "trial");
+//            param.put("width", 200); //二维码尺寸
+//            param.put("is_hyaline", true); // 是否需要透明底色, is_hyaline 为true时,生成透明底色的小程序码 参数仅对小程序码生效
+//            param.put("auto_color", true); // 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 参数仅对小程序码生效
+//            Map<String, Object> line_color = new HashMap<>();
+//            line_color.put("r", 0);
+//            line_color.put("g", 0);
+//            line_color.put("b", 0);
+//            param.put("line_color", line_color);
+//            System.err.println("调用生成微信URL接口传参:" + param);
+//            MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
+//            HttpEntity requestEntity = new HttpEntity(param, headers);
+//            ResponseEntity<byte[]> entity = wxRestTemplate.exchange(url, HttpMethod.POST, requestEntity, byte[].class, new Object[0]);
+//            System.err.println("调用小程序生成微信永久小程序码URL接口返回结果:" + entity.getBody());
+//            byte[] result = entity.getBody();
+//            System.err.println(Base64.encodeBase64String(result));
+//            inputStream = new ByteArrayInputStream(result);
+//            String finalFileName = System.currentTimeMillis() + "" + new SecureRandom().nextInt(0x0400) + ".jpeg";
+////            MultipartFile multipartFile = convertInputStreamToMultipartFile(inputStream, finalFileName, "image/jpeg");
+////            String name = FileUploadUtils.upload(localFilePath, multipartFile);
+////            System.err.println(name);
+//            return AjaxResult.success(null);
+//        } catch (Exception e) {
+//            System.err.println("调用小程序生成微信永久小程序码URL接口异常" + e);
+//        } finally {
+//            if (inputStream != null) {
+//                try {
+//                    inputStream.close();
+//                } catch (IOException e) {
+//                    e.printStackTrace();
+//                }
+//            }
+//            if (outputStream != null) {
+//                try {
+//                    outputStream.close();
+//                } catch (IOException e) {
+//                    e.printStackTrace();
+//                }
+//            }
+//        }
+//        return AjaxResult.success();
+//    }
+    
+    
+    /**
+     * 获取微信token
+     * @return
+     */
+    @PostMapping("/getWXToken")
+    public R<String> getWXToken(){
+        WxAppletTools appletTools = new WxAppletTools(wxRestTemplate, wxConfig, redisService);
+        String accessToken = appletTools.getAccessToken("");
+        return R.ok(accessToken);
+    }
+    
+    
+    /**
+     * 敏感词检测
+     * @param content
+     * @param openid
+     * @return
+     */
+    @PostMapping("/sensitiveWordDetection")
+    public R<Boolean> sensitiveWordDetection (@RequestParam("content") String content, @RequestParam("openid") String openid){
+        WxAppletTools appletTools = new WxAppletTools(wxRestTemplate, wxConfig, redisService);
+        String accessToken = appletTools.getAccessToken("");
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.put("content", content);
+        jsonObject.put("version", 2);
+        jsonObject.put("scene", 2);
+        jsonObject.put("openid", openid);
+        String post = HttpUtils.post("https://api.weixin.qq.com/wxa/msg_sec_check?access_token=" + accessToken, jsonObject.toString());
+        JSONObject object = JSONObject.parseObject(post);
+        Integer errcode = object.getInteger("errcode");
+        if(0 != errcode){
+            throw new RuntimeException(object.getString("errmsg"));
+        }
+        JSONArray detail = object.getJSONArray("detail");
+        for (int i = 0; i < detail.size(); i++) {
+            JSONObject jsonObject1 = detail.getJSONObject(i);
+            Integer errcode1 = jsonObject1.getInteger("errcode");
+            if(0 == errcode1){
+                String suggest = jsonObject1.getString("suggest");
+                Integer label = jsonObject1.getInteger("label");
+                String keyword = jsonObject1.getString("keyword");
+                Integer prob = jsonObject1.getInteger("prob");
+                if(("risky".equals(suggest) || "review".equals(suggest)) && 100 != label && com.ruoyi.common.utils.StringUtils.isNotEmpty(keyword) && 80 <= prob){
+                    return R.ok(true);
+                }
+            }
+        }
+        return R.ok(false);
+    }
+}
diff --git a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/interceptor/MybatisInterceptor.java b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/interceptor/MybatisInterceptor.java
index ae4b66e..57a4ff0 100644
--- a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/interceptor/MybatisInterceptor.java
+++ b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/interceptor/MybatisInterceptor.java
@@ -56,7 +56,7 @@
                     //注入创建时间
                     if ("createTime".equals(field.getName())) {
                         field.setAccessible(true);
-                        field.set(parameter, new Date());
+//                        field.set(parameter, new Date());
                         field.setAccessible(false);
                     } 
                 } catch (Exception e) {
@@ -79,7 +79,7 @@
                     }
                     if ("updateTime".equals(field.getName())) {
                         field.setAccessible(true);
-                        field.set(parameter, new Date());
+//                        field.set(parameter, new Date());
                         field.setAccessible(false);
                     }
                 } catch (Exception e) {
diff --git a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/tool/TencentCosUtil.java b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/tool/TencentCosUtil.java
new file mode 100644
index 0000000..f86298b
--- /dev/null
+++ b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/tool/TencentCosUtil.java
@@ -0,0 +1,187 @@
+package com.ruoyi.web.controller.tool;
+
+import com.qcloud.cos.COSClient;
+import com.qcloud.cos.ClientConfig;
+import com.qcloud.cos.auth.BasicCOSCredentials;
+import com.qcloud.cos.auth.COSCredentials;
+import com.qcloud.cos.http.HttpProtocol;
+import com.qcloud.cos.model.ObjectMetadata;
+import com.qcloud.cos.model.PutObjectResult;
+import com.qcloud.cos.region.Region;
+import com.ruoyi.common.utils.WebUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletResponse;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.util.Base64;
+import java.util.UUID;
+
+/**
+ * @author HJL
+ */
+@Component
+public class TencentCosUtil {
+
+    /**
+     * COS的SecretId
+     */
+    @Value("${cos.client.accessKey}")
+    private String secretId;
+    /**
+     * COS的SecretKey
+     */
+    @Value("${cos.client.secretKey}")
+    private String secretKey;
+    /**
+     * 文件上传后访问路径的根路径,后面要最佳文件名字与类型
+     */
+    @Value("${cos.client.rootSrc}")
+    private String rootSrc;
+    /**
+     * 上传的存储桶的地域
+     */
+    @Value("${cos.client.bucketAddr}")
+    private String bucketAddr;
+    /**
+     * 存储桶的名字,是自己在存储空间自己创建的,我创建的名字是:qq-test-1303******
+     */
+    @Value("${cos.client.bucket}")
+    private String bucketName;
+    /**
+     * 文件存放位置
+     */
+    @Value("${cos.client.location}")
+    private String location;
+
+    /**
+     * 1.调用静态方法getCosClient()就会获得COSClient实例
+     * 2.本方法根据永久密钥初始化 COSClient的,官方是不推荐,官方推荐使用临时密钥,是可以限制密钥使用权限,创建cred时有些区别
+     *
+     * @return COSClient实例
+     */
+    private COSClient getCosClient() {
+        // 1 初始化用户身份信息(secretId, secretKey)。
+        COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
+        // 2.1 设置存储桶的地域(上文获得)
+        Region region = new Region(bucketAddr);
+        ClientConfig clientConfig = new ClientConfig(region);
+        // 2.2 使用https协议传输
+        clientConfig.setHttpProtocol(HttpProtocol.https);
+        // 生成 cos 客户端
+        return new COSClient(cred, clientConfig);
+    }
+
+    /**
+     * 只要调用静态方法upLoadFile(MultipartFile multipartFile)就可以获取上传后文件的全路径
+     *
+     * @param file
+     * @return 返回文件的浏览全路径
+     */
+    public String upLoadFile(MultipartFile file) {
+        try {
+            // 获取上传的文件的输入流
+            InputStream inputStream = file.getInputStream();
+            // 避免文件覆盖,获取文件的原始名称,如123.jpg,然后通过截取获得文件的后缀,也就是文件的类型
+            String originalFilename = file.getOriginalFilename();
+            //获取文件的类型
+            String fileType = originalFilename.substring(originalFilename.lastIndexOf("."));
+            //使用UUID工具  创建唯一名称,放置文件重名被覆盖,在拼接上上命令获取的文件类型
+            String fileName = UUID.randomUUID() + fileType;
+            // 指定文件上传到 COS 上的路径,即对象键。最终文件会传到存储桶名字中的images文件夹下的fileName名字
+            String key = location+"/" + fileName;
+            // 创建上传Object的Metadata
+            ObjectMetadata objectMetadata = new ObjectMetadata();
+            // - 使用输入流存储,需要设置请求长度
+            objectMetadata.setContentLength(inputStream.available());
+            // - 设置缓存
+            objectMetadata.setCacheControl("no-cache");
+            // - 设置Content-Type
+            objectMetadata.setContentType(fileType);
+            //上传文件
+            PutObjectResult putResult = getCosClient().putObject(bucketName, key, inputStream, objectMetadata);
+            // 创建文件的网络访问路径
+            String url = rootSrc + key;
+            //关闭 cosClient,并释放 HTTP 连接的后台管理线程
+            getCosClient().shutdown();
+            return url;
+        } catch (Exception e) {
+            e.printStackTrace();
+            // 发生IO异常、COS连接异常等,返回空
+            return null;
+        }
+    }
+
+    /**
+     * 下载文件
+     * @param file
+     * @return
+     */
+    public void downLoadFile(String file) {
+        HttpServletResponse response = WebUtils.response();
+        String replace = file.replace(rootSrc, "");
+        response.setHeader("Access-Control-Expose-Headers","File-Type");
+        COSCredentials cred = new BasicCOSCredentials(
+                secretId,
+                secretKey);
+        // 2.1 设置存储桶的地域(上文获得)
+        Region region = new Region(bucketAddr);
+        ClientConfig clientConfig = new ClientConfig(region);
+        // 2.2 使用https协议传输
+        clientConfig.setHttpProtocol(HttpProtocol.https);
+        COSClient cosClient = new COSClient(cred, clientConfig);
+        try {
+            // 5. 下载文件并获取输入流
+            InputStream inputStream = cosClient.getObject(bucketName, replace).getObjectContent();
+            ServletOutputStream outputStream = response.getOutputStream();
+            // 6. 处理输入流,例如读取内容或保存到本地文件
+            // 这里仅作示例,实际应用中需要根据需求处理输入流
+            byte[] buffer = new byte[1024];
+            int len;
+            while ((len = inputStream.read(buffer)) != -1) {
+                // 处理读取到的数据
+                outputStream.write(buffer, 0, len);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            // 7. 关闭输入流
+            cosClient.shutdown();
+        }
+    }
+    public String downLoadFileImg(String file) {
+        byte[] data = null;
+        String replace = file.replace(rootSrc, "");
+        COSCredentials cred = new BasicCOSCredentials(
+                secretId,
+                secretKey);
+        // 2.1 设置存储桶的地域(上文获得)
+        Region region = new Region(bucketAddr);
+        ClientConfig clientConfig = new ClientConfig(region);
+        // 2.2 使用https协议传输
+        clientConfig.setHttpProtocol(HttpProtocol.https);
+        COSClient cosClient = new COSClient(cred, clientConfig);
+        try {
+            // 5. 下载文件并获取输入流
+            InputStream inputStream = cosClient.getObject(bucketName, replace).getObjectContent();
+            ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
+            // 6. 处理输入流,例如读取内容或保存到本地文件
+            byte[] buffer = new byte[1024];
+            int len;
+            while ((len = inputStream.read(buffer)) != -1) {
+                // 处理读取到的数据
+                swapStream.write(buffer, 0, len);
+            }
+            data = swapStream.toByteArray();
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            // 7. 关闭输入流
+            cosClient.shutdown();
+        }
+        return Base64.getEncoder().encodeToString(data);
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-applet/src/main/resources/application-prod.yml b/ruoyi-applet/src/main/resources/application-prod.yml
index 47a6c8f..b652f22 100644
--- a/ruoyi-applet/src/main/resources/application-prod.yml
+++ b/ruoyi-applet/src/main/resources/application-prod.yml
@@ -206,3 +206,11 @@
     accessKeySecret: 0SRb6XGkciQDPWn2rYqbJtq2qRMDY8
     signName: "四川金达通信工程"
     templateCode: "SMS_293985284"
+cos:
+  client:
+    accessKey: AKIDCF5EF2c0DE1e5JK8r4EGJF4mNsMgp26x
+    secretKey: lLl184rUyFOOE0d5KNGC3kmfNsCWk4GU
+    bucket: xzgttest-1305134071
+    bucketAddr: ap-chengdu
+    rootSrc: https://xzgttest-1305134071.cos.ap-chengdu.myqcloud.com/
+    location: xizang
diff --git a/ruoyi-applet/src/main/resources/application-test.yml b/ruoyi-applet/src/main/resources/application-test.yml
index 355f277..a0e94e7 100644
--- a/ruoyi-applet/src/main/resources/application-test.yml
+++ b/ruoyi-applet/src/main/resources/application-test.yml
@@ -193,9 +193,9 @@
     accessPath: /file/
     allowExt: .jpg|.png|.gif|.jpeg|.doc|.docx|.apk|.MP4|.mp4|.pdf|.PDF
 wx:
-  config:
-    appId: wxc3985a05da7d86dc
-    secret: 5cca42633c25439613b328c08ef20cc9
+  conf:
+    appId: wxe91f1af7638aa5dd
+    secretId: a787e1a462715604e0c9528b6d8960d1
 #OSS及短信配置
 code:
   config:
@@ -205,3 +205,11 @@
     accessKeySecret: 0SRb6XGkciQDPWn2rYqbJtq2qRMDY8
     signName: "四川金达通信工程"
     templateCode: "SMS_293985284"
+cos:
+  client:
+    accessKey: AKIDCF5EF2c0DE1e5JK8r4EGJF4mNsMgp26x
+    secretKey: lLl184rUyFOOE0d5KNGC3kmfNsCWk4GU
+    bucket: xzgttest-1305134071
+    bucketAddr: ap-chengdu
+    rootSrc: https://xzgttest-1305134071.cos.ap-chengdu.myqcloud.com/
+    location: xizang
diff --git a/ruoyi-applet/src/main/resources/mybatis-config.xml b/ruoyi-applet/src/main/resources/mybatis-config.xml
index 7d487eb..53c5587 100644
--- a/ruoyi-applet/src/main/resources/mybatis-config.xml
+++ b/ruoyi-applet/src/main/resources/mybatis-config.xml
@@ -10,7 +10,7 @@
         <setting name="cacheEnabled" value="true"/>
         <!-- 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。默认 false  -->
         <!-- <setting name="lazyLoadingEnabled" value="true"/> -->
-        <setting name="mapUnderscoreToCamelCase" value="false"/><!--是否将map下划线方式转为驼峰式命名-->
+        <setting name="mapUnderscoreToCamelCase" value="true"/><!--是否将map下划线方式转为驼峰式命名-->
         <!-- 当开启时,任何方法的调用都会加载该对象的所有属性。默认 false,可通过select标签的 fetchType来覆盖-->
         <!-- <setting name="aggressiveLazyLoading" value="false"/>-->
         <!--  Mybatis 创建具有延迟加载能力的对象所用到的代理工具,默认JAVASSIST -->
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
index c075328..82b912c 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
@@ -83,6 +83,10 @@
      * 令牌前缀
      */
     public static final String LOGIN_USER_KEY = "login_user_key";
+    /**
+     * 小程序
+     */
+    public static final String LOGIN_USER_APPLET_KEY = "login_user_applet_key";
 
     /**
      * 用户ID
@@ -128,6 +132,10 @@
      * LDAPS 远程方法调用
      */
     public static final String LOOKUP_LDAPS = "ldaps:";
+    /**
+     * LDAPS 远程方法调用
+     */
+    public static final String INFORMATION_VIEW = "information_view:";
 
     /**
      * 自动识别json对象白名单配置(仅允许解析的包名,范围越小越安全)
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/DictConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/DictConstants.java
index 19a3caf..35fdf8f 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/DictConstants.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/DictConstants.java
@@ -43,4 +43,8 @@
      * 账单类型 1=租金 2=押金 3=生活费用
      */
     public static final String DICT_TYPE_BILL_TYPE = "t_bill_type";
+    /**
+     * 验收记录情况 1=良好 2=一般 3=较差
+     */
+    public static final String DICT_TYPE_CHECK_SITUATION = "t_check_situation";
 }
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
index 21ff250..9a6eea2 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
@@ -125,8 +125,11 @@
 
     @TableField(exist = false)
     private String roleName;
-
+    @TableField(exist = false)
     private String deptName;
+    @ApiModelProperty(value = "部门id集合")
+    @TableField(exist = false)
+    private List<String> deptIds;
 
     public String getRoleName() {
         return roleName;
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/TTenantResp.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/TTenantResp.java
new file mode 100644
index 0000000..33b6fec
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/TTenantResp.java
@@ -0,0 +1,70 @@
+package com.ruoyi.common.core.domain.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.common.core.domain.BaseModel;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import javax.validation.constraints.NotBlank;
+import java.time.LocalDate;
+
+/**
+ * <p>
+ * 租户
+ * </p>
+ *
+ * @author xiaochen
+ * @since 2025-01-20
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@ApiModel(value="TTenant对象", description="登录返回")
+public class TTenantResp  {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    private String id;
+
+    @ApiModelProperty(value = "住户名称")
+    private String residentName;
+
+    @ApiModelProperty(value = "入住时间")
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    private LocalDate checkinTime;
+
+    @ApiModelProperty(value = "租户属性")
+    private String tenantAttributes;
+
+    @ApiModelProperty(value = "租户类型")
+    private String tenantType;
+
+    @ApiModelProperty(value = "联系电话")
+    private String phone;
+
+    @ApiModelProperty(value = "证件号码")
+    private String idCard;
+
+    @ApiModelProperty(value = "邮箱")
+    private String email;
+
+    @ApiModelProperty(value = "银行转账专号")
+    private String bankNumber;
+
+    @ApiModelProperty(value = "通讯地址")
+    private String mailAddress;
+
+    @ApiModelProperty(value = "登录账号")
+    private String account;
+
+    @ApiModelProperty(value = "登录密码")
+    private String password;
+    @ApiModelProperty(value = "微信openid")
+    private String openId;
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUserApplet.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUserApplet.java
new file mode 100644
index 0000000..186be08
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUserApplet.java
@@ -0,0 +1,263 @@
+package com.ruoyi.common.core.domain.model;
+
+import com.alibaba.fastjson2.annotation.JSONField;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.domain.entity.TTenantResp;
+import lombok.Data;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * 登录用户身份权限
+ * 
+ * @author ruoyi
+ */
+@Data
+public class LoginUserApplet implements UserDetails
+{
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 用户ID
+     */
+    private String userId;
+
+    /**
+     * 部门ID
+     */
+    private Long deptId;
+
+    /**
+     * 用户唯一标识
+     */
+    private String token;
+
+    /**
+     * 登录时间
+     */
+    private Long loginTime;
+
+    /**
+     * 过期时间
+     */
+    private Long expireTime;
+
+    /**
+     * 登录IP地址
+     */
+    private String ipaddr;
+
+    /**
+     * 登录地点
+     */
+    private String loginLocation;
+
+    /**
+     * 浏览器类型
+     */
+    private String browser;
+
+    /**
+     * 操作系统
+     */
+    private String os;
+
+    /**
+     * 权限列表
+     */
+    private Set<String> permissions;
+
+    /**
+     * 用户信息
+     */
+    private TTenantResp user;
+
+
+    public LoginUserApplet()
+    {
+    }
+
+    public LoginUserApplet(TTenantResp user, Set<String> permissions)
+    {
+        this.user = user;
+        this.permissions = permissions;
+    }
+
+    public LoginUserApplet(String userId, Long deptId, TTenantResp user, Set<String> permissions)
+    {
+        this.userId = userId;
+        this.deptId = deptId;
+        this.user = user;
+        this.permissions = permissions;
+    }
+
+    public String getUserId()
+    {
+        return userId;
+    }
+
+    public void setUserId(String userId)
+    {
+        this.userId = userId;
+    }
+
+    public Long getDeptId()
+    {
+        return deptId;
+    }
+
+    public void setDeptId(Long deptId)
+    {
+        this.deptId = deptId;
+    }
+
+    public String getToken()
+    {
+        return token;
+    }
+
+    public void setToken(String token)
+    {
+        this.token = token;
+    }
+
+    @JSONField(serialize = false)
+    @Override
+    public String getPassword()
+    {
+        return user.getPassword();
+    }
+
+    @Override
+    public String getUsername()
+    {
+        return user.getResidentName();
+    }
+
+    /**
+     * 账户是否未过期,过期无法验证
+     */
+    @JSONField(serialize = false)
+    @Override
+    public boolean isAccountNonExpired()
+    {
+        return true;
+    }
+
+    /**
+     * 指定用户是否解锁,锁定的用户无法进行身份验证
+     * 
+     * @return
+     */
+    @JSONField(serialize = false)
+    @Override
+    public boolean isAccountNonLocked()
+    {
+        return true;
+    }
+
+    /**
+     * 指示是否已过期的用户的凭据(密码),过期的凭据防止认证
+     * 
+     * @return
+     */
+    @JSONField(serialize = false)
+    @Override
+    public boolean isCredentialsNonExpired()
+    {
+        return true;
+    }
+
+    /**
+     * 是否可用 ,禁用的用户不能身份验证
+     * 
+     * @return
+     */
+    @JSONField(serialize = false)
+    @Override
+    public boolean isEnabled()
+    {
+        return true;
+    }
+
+    public Long getLoginTime()
+    {
+        return loginTime;
+    }
+
+    public void setLoginTime(Long loginTime)
+    {
+        this.loginTime = loginTime;
+    }
+
+    public String getIpaddr()
+    {
+        return ipaddr;
+    }
+
+    public void setIpaddr(String ipaddr)
+    {
+        this.ipaddr = ipaddr;
+    }
+
+    public String getLoginLocation()
+    {
+        return loginLocation;
+    }
+
+    public void setLoginLocation(String loginLocation)
+    {
+        this.loginLocation = loginLocation;
+    }
+
+    public String getBrowser()
+    {
+        return browser;
+    }
+
+    public void setBrowser(String browser)
+    {
+        this.browser = browser;
+    }
+
+    public String getOs()
+    {
+        return os;
+    }
+
+    public void setOs(String os)
+    {
+        this.os = os;
+    }
+
+    public Long getExpireTime()
+    {
+        return expireTime;
+    }
+
+    public void setExpireTime(Long expireTime)
+    {
+        this.expireTime = expireTime;
+    }
+
+    public Set<String> getPermissions()
+    {
+        return permissions;
+    }
+
+    public void setPermissions(Set<String> permissions)
+    {
+        this.permissions = permissions;
+    }
+
+
+
+    @Override
+    public Collection<? extends GrantedAuthority> getAuthorities()
+    {
+        return null;
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/exception/ServiceException.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/exception/ServiceException.java
new file mode 100644
index 0000000..4983866
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/exception/ServiceException.java
@@ -0,0 +1,74 @@
+package com.ruoyi.common.core.exception;
+
+/**
+ * 业务异常
+ * 
+ * @author ruoyi
+ */
+public final class ServiceException extends RuntimeException
+{
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 错误码
+     */
+    private Integer code;
+
+    /**
+     * 错误提示
+     */
+    private String message;
+
+    /**
+     * 错误明细,内部调试错误
+     *
+     * 和 {@link CommonResult#getDetailMessage()} 一致的设计
+     */
+    private String detailMessage;
+
+    /**
+     * 空构造方法,避免反序列化问题
+     */
+    public ServiceException()
+    {
+    }
+
+    public ServiceException(String message)
+    {
+        this.message = message;
+    }
+
+    public ServiceException(String message, Integer code)
+    {
+        this.message = message;
+        this.code = code;
+    }
+
+    public String getDetailMessage()
+    {
+        return detailMessage;
+    }
+
+    @Override
+    public String getMessage()
+    {
+        return message;
+    }
+
+    public Integer getCode()
+    {
+        return code;
+    }
+
+    public ServiceException setMessage(String message)
+    {
+        this.message = message;
+        return this;
+    }
+
+    public ServiceException setDetailMessage(String detailMessage)
+    {
+        this.detailMessage = detailMessage;
+        return this;
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java
index f405893..96864ac 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java
@@ -330,4 +330,14 @@
         Long result = (Long) redisTemplate.execute(UNLOCK_SCRIPT, Collections.singletonList(lockKeyWithPrefix), requestId);
         return result != null && result == 1L;
     }
+
+    /**
+     * 自增
+     * @param key 要加一的键
+     */
+    public int increment(String key) {
+        // +1 操作
+        return redisTemplate.opsForValue().increment(key).intValue();
+    }
+
 }
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/utils/Constants.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/utils/Constants.java
new file mode 100644
index 0000000..8144c3a
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/utils/Constants.java
@@ -0,0 +1,143 @@
+package com.ruoyi.common.core.utils;
+
+/**
+ * 通用常量信息
+ * 
+ * @author ruoyi
+ */
+public class Constants
+{
+    /**
+     * UTF-8 字符集
+     */
+    public static final String UTF8 = "UTF-8";
+
+    /**
+     * GBK 字符集
+     */
+    public static final String GBK = "GBK";
+
+    /**
+     * www主域
+     */
+    public static final String WWW = "www.";
+
+    /**
+     * RMI 远程方法调用
+     */
+    public static final String LOOKUP_RMI = "rmi:";
+
+    /**
+     * LDAP 远程方法调用
+     */
+    public static final String LOOKUP_LDAP = "ldap:";
+
+    /**
+     * LDAPS 远程方法调用
+     */
+    public static final String LOOKUP_LDAPS = "ldaps:";
+
+    /**
+     * http请求
+     */
+    public static final String HTTP = "http://";
+
+    /**
+     * https请求
+     */
+    public static final String HTTPS = "https://";
+
+    /**
+     * 成功标记
+     */
+    public static final Integer SUCCESS = 200;
+
+    /**
+     * 失败标记
+     */
+    public static final Integer FAIL = 500;
+
+    /**
+     * 登录成功状态
+     */
+    public static final String LOGIN_SUCCESS_STATUS = "1";
+
+    /**
+     * 登录失败状态
+     */
+    public static final String LOGIN_FAIL_STATUS = "2";
+
+    /**
+     * 登录成功
+     */
+    public static final String LOGIN_SUCCESS = "Success";
+
+    /**
+     * 注销
+     */
+    public static final String LOGOUT = "Logout";
+
+    /**
+     * 注册
+     */
+    public static final String REGISTER = "Register";
+
+    /**
+     * 登录失败
+     */
+    public static final String LOGIN_FAIL = "Error";
+
+    /**
+     * 当前记录起始索引
+     */
+    public static final String PAGE_NUM = "pageNum";
+
+    /**
+     * 每页显示记录数
+     */
+    public static final String PAGE_SIZE = "pageSize";
+
+    /**
+     * 排序列
+     */
+    public static final String ORDER_BY_COLUMN = "orderByColumn";
+
+    /**
+     * 排序的方向 "desc" 或者 "asc".
+     */
+    public static final String IS_ASC = "isAsc";
+
+    /**
+     * 验证码有效期(分钟)
+     */
+    public static final long CAPTCHA_EXPIRATION = 2;
+
+    /**
+     * 资源映射路径 前缀
+     */
+    public static final String RESOURCE_PREFIX = "/profile";
+
+    /**
+     * 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)
+     */
+    public static final String[] JOB_WHITELIST_STR = { "com.ruoyi" };
+
+    /**
+     * 时间格式化
+     */
+    public static final String DATE_FORMATTER_TIME = "yyyy-MM-dd HH:mm:ss";
+    public static final String DATE_FORMATTER_DATE = "yyyy-MM-dd";
+    /**
+     * 修改手机号后缀
+     */
+    public static final String UPDATE_PHONE = "_updatePhone";
+    /**
+     * 申请建桩后缀
+     */
+    public static final String APPLY_CHARGING = "_applyCharging";
+    /**
+     * 定时任务违规的字符
+     */
+    public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
+            "org.springframework", "org.apache", "com.ruoyi.common.core.utils.file" };
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/utils/HttpUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/utils/HttpUtils.java
new file mode 100644
index 0000000..7d25f7a
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/utils/HttpUtils.java
@@ -0,0 +1,311 @@
+package com.ruoyi.common.core.utils;
+
+import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.utils.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.net.ssl.*;
+import java.io.*;
+import java.net.*;
+import java.nio.charset.StandardCharsets;
+import java.security.cert.X509Certificate;
+
+/**
+ * 通用http发送方法
+ * 
+ * @author ruoyi
+ */
+public class HttpUtils
+{
+    private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
+
+    /**
+     * 向指定 URL 发送GET方法的请求
+     *
+     * @param url 发送请求的 URL
+     * @return 所代表远程资源的响应结果
+     */
+    public static String sendGet(String url)
+    {
+        return sendGet(url, StringUtils.EMPTY);
+    }
+
+    /**
+     * 向指定 URL 发送GET方法的请求
+     *
+     * @param url 发送请求的 URL
+     * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
+     * @return 所代表远程资源的响应结果
+     */
+    public static String sendGet(String url, String param)
+    {
+        return sendGet(url, param, Constants.UTF8);
+    }
+
+    /**
+     * 向指定 URL 发送GET方法的请求
+     *
+     * @param url 发送请求的 URL
+     * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
+     * @param contentType 编码类型
+     * @return 所代表远程资源的响应结果
+     */
+    public static String sendGet(String url, String param, String contentType)
+    {
+        StringBuilder result = new StringBuilder();
+        BufferedReader in = null;
+        try
+        {
+            String urlNameString = StringUtils.isNotBlank(param) ? url + "?" + param : url;
+            log.info("sendGet - {}", urlNameString);
+            URL realUrl = new URL(urlNameString);
+            URLConnection connection = realUrl.openConnection();
+            connection.setRequestProperty("accept", "*/*");
+            connection.setRequestProperty("connection", "Keep-Alive");
+            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+            connection.connect();
+            in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));
+            String line;
+            while ((line = in.readLine()) != null)
+            {
+                result.append(line);
+            }
+            log.info("recv - {}", result);
+        }
+        catch (ConnectException e)
+        {
+            log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);
+        }
+        catch (SocketTimeoutException e)
+        {
+            log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);
+        }
+        catch (IOException e)
+        {
+            log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e);
+        }
+        catch (Exception e)
+        {
+            log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e);
+        }
+        finally
+        {
+            try
+            {
+                if (in != null)
+                {
+                    in.close();
+                }
+            }
+            catch (Exception ex)
+            {
+                log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
+            }
+        }
+        return result.toString();
+    }
+
+    /**
+     * 向指定 URL 发送POST方法的请求
+     *
+     * @param url 发送请求的 URL
+     * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
+     * @return 所代表远程资源的响应结果
+     */
+    public static String sendPost(String url, String param)
+    {
+        PrintWriter out = null;
+        BufferedReader in = null;
+        StringBuilder result = new StringBuilder();
+        try
+        {
+            log.info("sendPost - {}", url);
+            URL realUrl = new URL(url);
+            URLConnection conn = realUrl.openConnection();
+            conn.setRequestProperty("accept", "*/*");
+            conn.setRequestProperty("connection", "Keep-Alive");
+            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+            conn.setRequestProperty("Accept-Charset", "utf-8");
+            conn.setRequestProperty("contentType", "utf-8");
+            conn.setDoOutput(true);
+            conn.setDoInput(true);
+            out = new PrintWriter(conn.getOutputStream());
+            out.print(param);
+            out.flush();
+            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
+            String line;
+            while ((line = in.readLine()) != null)
+            {
+                result.append(line);
+            }
+            log.info("recv - {}", result);
+        }
+        catch (ConnectException e)
+        {
+            log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
+        }
+        catch (SocketTimeoutException e)
+        {
+            log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
+        }
+        catch (IOException e)
+        {
+            log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
+        }
+        catch (Exception e)
+        {
+            log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
+        }
+        finally
+        {
+            try
+            {
+                if (out != null)
+                {
+                    out.close();
+                }
+                if (in != null)
+                {
+                    in.close();
+                }
+            }
+            catch (IOException ex)
+            {
+                log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
+            }
+        }
+        return result.toString();
+    }
+
+    public static String sendSSLPost(String url, String param)
+    {
+        StringBuilder result = new StringBuilder();
+        String urlNameString = url + "?" + param;
+        try
+        {
+            log.info("sendSSLPost - {}", urlNameString);
+            SSLContext sc = SSLContext.getInstance("SSL");
+            sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom());
+            URL console = new URL(urlNameString);
+            HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
+            conn.setRequestProperty("accept", "*/*");
+            conn.setRequestProperty("connection", "Keep-Alive");
+            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+            conn.setRequestProperty("Accept-Charset", "utf-8");
+            conn.setRequestProperty("contentType", "utf-8");
+            conn.setDoOutput(true);
+            conn.setDoInput(true);
+
+            conn.setSSLSocketFactory(sc.getSocketFactory());
+            conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
+            conn.connect();
+            InputStream is = conn.getInputStream();
+            BufferedReader br = new BufferedReader(new InputStreamReader(is));
+            String ret = "";
+            while ((ret = br.readLine()) != null)
+            {
+                if (ret != null && !"".equals(ret.trim()))
+                {
+                    result.append(new String(ret.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8));
+                }
+            }
+            log.info("recv - {}", result);
+            conn.disconnect();
+            br.close();
+        }
+        catch (ConnectException e)
+        {
+            log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e);
+        }
+        catch (SocketTimeoutException e)
+        {
+            log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e);
+        }
+        catch (IOException e)
+        {
+            log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e);
+        }
+        catch (Exception e)
+        {
+            log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e);
+        }
+        return result.toString();
+    }
+
+    public static String post(String strURL, String params) {
+        String result = "";
+        BufferedReader reader = null;
+        try {
+            URL url = new URL(strURL);// 创建连接
+            HttpURLConnection connection = (HttpURLConnection) url
+                    .openConnection();
+            connection.setDoOutput(true);
+            connection.setDoInput(true);
+            connection.setUseCaches(false);
+            connection.setInstanceFollowRedirects(true);
+            connection.setRequestMethod("POST"); // 设置请求方式
+            connection.setRequestProperty("Accept", "application/json"); // 设置接收数据的格式
+            connection.setRequestProperty("Content-Type", "application/json"); // 设置发送数据的格式
+            connection.connect();
+            if (params != null && !StringUtils.isEmpty(params)) {
+                byte[] writebytes = params.getBytes();
+                // 设置文件长度
+                //   connection.setRequestProperty("Content-Length", String.valueOf(writebytes.length));
+                OutputStream outwritestream = connection.getOutputStream();
+                outwritestream.write(params.getBytes());
+                outwritestream.flush();
+                outwritestream.close();
+                // Log.d("hlhupload", "doJsonPost: conn"+connection.getResponseCode());
+            }
+            if (connection.getResponseCode() == 200) {
+                log.info("<<<<<<<<<<<<<请求响应:{}", connection.getResponseMessage());
+                reader = new BufferedReader(
+                        new InputStreamReader(connection.getInputStream()));
+                result = reader.readLine();
+                log.info("<<<<<<<<<<<<<请求响应:{}", result);
+            } else {
+                throw new ServiceException(connection.getResponseMessage());
+            }
+        } catch (Exception e) {
+            throw new ServiceException("http的post请求异常!" + e.getMessage());
+        } finally {
+            if (reader != null) {
+                try {
+                    reader.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return result;
+    }
+
+    private static class TrustAnyTrustManager implements X509TrustManager
+    {
+        @Override
+        public void checkClientTrusted(X509Certificate[] chain, String authType)
+        {
+        }
+
+        @Override
+        public void checkServerTrusted(X509Certificate[] chain, String authType)
+        {
+        }
+
+        @Override
+        public X509Certificate[] getAcceptedIssuers()
+        {
+            return new X509Certificate[] {};
+        }
+    }
+
+    private static class TrustAnyHostnameVerifier implements HostnameVerifier
+    {
+        @Override
+        public boolean verify(String hostname, SSLSession session)
+        {
+            return true;
+        }
+    }
+}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/redis/configure/FastJson2JsonRedisSerializer.java b/ruoyi-common/src/main/java/com/ruoyi/common/redis/configure/FastJson2JsonRedisSerializer.java
new file mode 100644
index 0000000..c9f3b66
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/redis/configure/FastJson2JsonRedisSerializer.java
@@ -0,0 +1,50 @@
+package com.ruoyi.common.redis.configure;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONReader;
+import com.alibaba.fastjson2.JSONWriter;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.data.redis.serializer.SerializationException;
+
+import java.nio.charset.Charset;
+
+/**
+ * Redis使用FastJson序列化
+ * 
+ * @author ruoyi
+ */
+public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
+{
+    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
+
+    private Class<T> clazz;
+
+
+    public FastJson2JsonRedisSerializer(Class<T> clazz)
+    {
+        super();
+        this.clazz = clazz;
+    }
+
+    @Override
+    public byte[] serialize(T t) throws SerializationException
+    {
+        if (t == null)
+        {
+            return new byte[0];
+        }
+        return JSON.toJSONString(t, JSONWriter.Feature.WriteClassName).getBytes(DEFAULT_CHARSET);
+    }
+
+    @Override
+    public T deserialize(byte[] bytes) throws SerializationException
+    {
+        if (bytes == null || bytes.length <= 0)
+        {
+            return null;
+        }
+        String str = new String(bytes, DEFAULT_CHARSET);
+
+        return JSON.parseObject(str, clazz, JSONReader.Feature.SupportAutoType);
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/redis/service/RedisService.java b/ruoyi-common/src/main/java/com/ruoyi/common/redis/service/RedisService.java
new file mode 100644
index 0000000..1ae72cd
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/redis/service/RedisService.java
@@ -0,0 +1,273 @@
+package com.ruoyi.common.redis.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.BoundSetOperations;
+import org.springframework.data.redis.core.HashOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.ValueOperations;
+import org.springframework.stereotype.Component;
+
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * spring redis 工具类
+ * 
+ * @author ruoyi
+ **/
+@SuppressWarnings(value = { "unchecked", "rawtypes" })
+@Component
+public class RedisService
+{
+    @Autowired
+    public RedisTemplate redisTemplate;
+
+    /**
+     * 缓存基本的对象,Integer、String、实体类等
+     *
+     * @param key 缓存的键值
+     * @param value 缓存的值
+     */
+    public <T> void setCacheObject(final String key, final T value)
+    {
+        redisTemplate.opsForValue().set(key, value);
+    }
+
+    /**
+     * 缓存基本的对象,Integer、String、实体类等
+     *
+     * @param key 缓存的键值
+     * @param value 缓存的值
+     * @param timeout 时间
+     * @param timeUnit 时间颗粒度
+     */
+    public <T> void setCacheObject(final String key, final T value, final Long timeout, final TimeUnit timeUnit)
+    {
+        redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
+    }
+
+    /**
+     * 设置有效时间
+     *
+     * @param key Redis键
+     * @param timeout 超时时间
+     * @return true=设置成功;false=设置失败
+     */
+    public boolean expire(final String key, final long timeout)
+    {
+        return expire(key, timeout, TimeUnit.SECONDS);
+    }
+
+    /**
+     * 设置有效时间
+     *
+     * @param key Redis键
+     * @param timeout 超时时间
+     * @param unit 时间单位
+     * @return true=设置成功;false=设置失败
+     */
+    public boolean expire(final String key, final long timeout, final TimeUnit unit)
+    {
+        return redisTemplate.expire(key, timeout, unit);
+    }
+
+    /**
+     * 获取有效时间
+     *
+     * @param key Redis键
+     * @return 有效时间
+     */
+    public long getExpire(final String key)
+    {
+        return redisTemplate.getExpire(key);
+    }
+
+    /**
+     * 判断 key是否存在
+     *
+     * @param key 键
+     * @return true 存在 false不存在
+     */
+    public Boolean hasKey(String key)
+    {
+        return redisTemplate.hasKey(key);
+    }
+
+    /**
+     * 获得缓存的基本对象。
+     *
+     * @param key 缓存键值
+     * @return 缓存键值对应的数据
+     */
+    public <T> T getCacheObject(final String key)
+    {
+        ValueOperations<String, T> operation = redisTemplate.opsForValue();
+        return operation.get(key);
+    }
+
+    /**
+     * 删除单个对象
+     *
+     * @param key
+     */
+    public boolean deleteObject(final String key)
+    {
+        return redisTemplate.delete(key);
+    }
+
+    /**
+     * 删除集合对象
+     *
+     * @param collection 多个对象
+     * @return
+     */
+    public boolean deleteObject(final Collection collection)
+    {
+        return redisTemplate.delete(collection) > 0;
+    }
+
+    /**
+     * 缓存List数据
+     *
+     * @param key 缓存的键值
+     * @param dataList 待缓存的List数据
+     * @return 缓存的对象
+     */
+    public <T> long setCacheList(final String key, final List<T> dataList)
+    {
+        Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
+        return count == null ? 0 : count;
+    }
+
+    /**
+     * 获得缓存的list对象
+     *
+     * @param key 缓存的键值
+     * @return 缓存键值对应的数据
+     */
+    public <T> List<T> getCacheList(final String key)
+    {
+        return redisTemplate.opsForList().range(key, 0, -1);
+    }
+
+    /**
+     * 缓存Set
+     *
+     * @param key 缓存键值
+     * @param dataSet 缓存的数据
+     * @return 缓存数据的对象
+     */
+    public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet)
+    {
+        BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
+        Iterator<T> it = dataSet.iterator();
+        while (it.hasNext())
+        {
+            setOperation.add(it.next());
+        }
+        return setOperation;
+    }
+
+    /**
+     * 获得缓存的set
+     *
+     * @param key
+     * @return
+     */
+    public <T> Set<T> getCacheSet(final String key)
+    {
+        return redisTemplate.opsForSet().members(key);
+    }
+
+    /**
+     * 缓存Map
+     *
+     * @param key
+     * @param dataMap
+     */
+    public <T> void setCacheMap(final String key, final Map<String, T> dataMap)
+    {
+        if (dataMap != null) {
+            redisTemplate.opsForHash().putAll(key, dataMap);
+        }
+    }
+
+    public <T> void setCacheMap(final String key, final Map<String, T> dataMap, long timeout)
+    {
+        if (dataMap != null) {
+            redisTemplate.opsForHash().putAll(key, dataMap);
+            redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
+        }
+    }
+
+    /**
+     * 获得缓存的Map
+     *
+     * @param key
+     * @return
+     */
+    public <T> Map<String, T> getCacheMap(final String key)
+    {
+        return redisTemplate.opsForHash().entries(key);
+    }
+
+    /**
+     * 往Hash中存入数据
+     *
+     * @param key Redis键
+     * @param hKey Hash键
+     * @param value 值
+     */
+    public <T> void setCacheMapValue(final String key, final String hKey, final T value)
+    {
+        redisTemplate.opsForHash().put(key, hKey, value);
+    }
+
+    /**
+     * 获取Hash中的数据
+     *
+     * @param key Redis键
+     * @param hKey Hash键
+     * @return Hash中的对象
+     */
+    public <T> T getCacheMapValue(final String key, final String hKey)
+    {
+        HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
+        return opsForHash.get(key, hKey);
+    }
+
+    /**
+     * 获取多个Hash中的数据
+     *
+     * @param key Redis键
+     * @param hKeys Hash键集合
+     * @return Hash对象集合
+     */
+    public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys)
+    {
+        return redisTemplate.opsForHash().multiGet(key, hKeys);
+    }
+
+    /**
+     * 删除Hash中的某条数据
+     *
+     * @param key Redis键
+     * @param hKey Hash键
+     * @return 是否成功
+     */
+    public boolean deleteCacheMapValue(final String key, final String hKey)
+    {
+        return redisTemplate.opsForHash().delete(key, hKey) > 0;
+    }
+
+    /**
+     * 获得缓存的基本对象列表
+     *
+     * @param pattern 字符串前缀
+     * @return 对象列表
+     */
+    public Collection<String> keys(final String pattern)
+    {
+        return redisTemplate.keys(pattern);
+    }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java
index 1a4e0fa..5f90047 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java
@@ -118,6 +118,7 @@
                         "/applet/changepwd", "/captchaImage","/getCode","/loginCode",
                         "/operations/getBySingleNum/**",
                         "/user/getUserInfoByNumber/**",
+                        "/wxLogin/**",
                         "/open/**"
                 ).permitAll()
                 // 静态资源,可匿名访问
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java
index 3eb2495..9015708 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java
@@ -5,6 +5,8 @@
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.common.core.domain.model.LoginUserApplet;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.security.core.context.SecurityContextHolder;
@@ -32,12 +34,22 @@
             throws ServletException, IOException
     {
         LoginUser loginUser = tokenService.getLoginUser(request);
-        if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication()))
+        LoginUserApplet applet = tokenService.getLoginUserApplet(request);
+        if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication())||
+                StringUtils.isNotNull(applet))
         {
-            tokenService.verifyToken(loginUser);
-            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
-            authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
-            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
+            if (StringUtils.isNotNull(loginUser)){
+                tokenService.verifyToken(loginUser);
+                UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
+                authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
+                SecurityContextHolder.getContext().setAuthentication(authenticationToken);
+            }
+            if (StringUtils.isNotNull(applet)){
+                tokenService.verifyTokenApplet(applet);
+                UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(applet, null, applet.getAuthorities());
+                authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
+                SecurityContextHolder.getContext().setAuthentication(authenticationToken);
+            }
         }
         chain.doFilter(request, response);
     }
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java
index d4e744e..a7a640b 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java
@@ -4,6 +4,8 @@
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 import javax.servlet.http.HttpServletRequest;
+
+import com.ruoyi.common.core.domain.model.LoginUserApplet;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -66,6 +68,15 @@
         return getLoginUser(ServletUtils.getRequest());
     }
     /**
+     * 小程序获取用户身份信息
+     *
+     * @return 用户信息
+     */
+    public LoginUserApplet getLoginUserApplet()
+    {
+        return getLoginUserApplet(ServletUtils.getRequest());
+    }
+    /**
      * 获取用户身份信息
      *
      * @return 用户信息
@@ -83,6 +94,33 @@
                 String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
                 String userKey = getTokenKey(uuid);
                 LoginUser user = redisCache.getCacheObject(userKey);
+                return user;
+            }
+            catch (Exception e)
+            {
+                log.error("获取用户信息异常'{}'", e.getMessage());
+            }
+        }
+        return null;
+    }
+    /**
+     * 小程序获取用户身份信息
+     *
+     * @return 用户信息
+     */
+    public LoginUserApplet getLoginUserApplet(HttpServletRequest request)
+    {
+        // 获取请求携带的令牌
+        String token = getToken(request);
+        if (StringUtils.isNotEmpty(token))
+        {
+            try
+            {
+                Claims claims = parseToken(token);
+                // 解析对应的权限以及用户信息
+                String uuid = (String) claims.get(Constants.LOGIN_USER_APPLET_KEY);
+                String userKey = getTokenKey(uuid);
+                LoginUserApplet user = redisCache.getCacheObject(userKey);
                 return user;
             }
             catch (Exception e)
@@ -133,6 +171,23 @@
         claims.put(Constants.LOGIN_USER_KEY, token);
         return createToken(claims);
     }
+    /**
+     * 创建用户小程序令牌
+     *
+     * @param loginUser 用户信息
+     * @return 令牌
+     */
+    public String createTokenApplet(LoginUserApplet loginUser)
+    {
+        String token = IdUtils.fastUUID();
+        loginUser.setToken(token);
+        setUserAgentApplet(loginUser);
+        refreshTokenApplet(loginUser);
+
+        Map<String, Object> claims = new HashMap<>();
+        claims.put(Constants.LOGIN_USER_APPLET_KEY, token);
+        return createTokenApplet(claims);
+    }
 
     /**
      * 验证令牌有效期,相差不足20分钟,自动刷新缓存
@@ -149,6 +204,21 @@
             refreshToken(loginUser);
         }
     }
+    /**
+     * 小程序验证令牌有效期,相差不足20分钟,自动刷新缓存
+     *
+     * @param loginUser
+     * @return 令牌
+     */
+    public void verifyTokenApplet(LoginUserApplet loginUser)
+    {
+        long expireTime = loginUser.getExpireTime();
+        long currentTime = System.currentTimeMillis();
+        if (expireTime - currentTime <= MILLIS_MINUTE_TEN)
+        {
+            refreshTokenApplet(loginUser);
+        }
+    }
 
     /**
      * 刷新令牌有效期
@@ -156,6 +226,19 @@
      * @param loginUser 登录信息
      */
     public void refreshToken(LoginUser loginUser)
+    {
+        loginUser.setLoginTime(System.currentTimeMillis());
+        loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
+        // 根据uuid将loginUser缓存
+        String userKey = getTokenKey(loginUser.getToken());
+        redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
+    }
+    /**
+     * 刷新令牌有效期
+     *
+     * @param loginUser 登录信息
+     */
+    public void refreshTokenApplet(LoginUserApplet loginUser)
     {
         loginUser.setLoginTime(System.currentTimeMillis());
         loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
@@ -178,6 +261,20 @@
         loginUser.setBrowser(userAgent.getBrowser().getName());
         loginUser.setOs(userAgent.getOperatingSystem().getName());
     }
+    /**
+     * 设置用户代理信息
+     *
+     * @param loginUser 登录信息
+     */
+    public void setUserAgentApplet(LoginUserApplet loginUser)
+    {
+        UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
+        String ip = IpUtils.getIpAddr();
+        loginUser.setIpaddr(ip);
+        loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
+        loginUser.setBrowser(userAgent.getBrowser().getName());
+        loginUser.setOs(userAgent.getOperatingSystem().getName());
+    }
 
     /**
      * 从数据声明生成令牌
@@ -192,6 +289,19 @@
                 .signWith(SignatureAlgorithm.HS512, secret).compact();
         return token;
     }
+    /**
+     * 小程序从数据声明生成令牌
+     *
+     * @param claims 数据声明
+     * @return 令牌
+     */
+    private String createTokenApplet(Map<String, Object> claims)
+    {
+        String token = Jwts.builder()
+                .setClaims(claims)
+                .signWith(SignatureAlgorithm.HS512, secret).compact();
+        return token;
+    }
 
     /**
      * 从令牌中获取数据声明
diff --git a/ruoyi-system/pom.xml b/ruoyi-system/pom.xml
index 0747834..80a2359 100644
--- a/ruoyi-system/pom.xml
+++ b/ruoyi-system/pom.xml
@@ -79,6 +79,10 @@
             <artifactId>bankapi</artifactId>
             <version>1.0.0-SNAPSHOT</version>
         </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.datatype</groupId>
+            <artifactId>jackson-datatype-jsr310</artifactId>
+        </dependency>
     </dependencies>
 
 </project>
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/dto/TFaultRepairMessageDTO.java b/ruoyi-system/src/main/java/com/ruoyi/system/dto/TFaultRepairMessageDTO.java
new file mode 100644
index 0000000..e65bec9
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/dto/TFaultRepairMessageDTO.java
@@ -0,0 +1,10 @@
+package com.ruoyi.system.dto;
+
+import com.ruoyi.system.model.TFaultRepairMessage;
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+
+@Data
+@ApiModel(value = "报修dto")
+public class TFaultRepairMessageDTO extends TFaultRepairMessage {
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java
index c98a23f..843a7fc 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java
@@ -2,6 +2,7 @@
 
 import java.util.List;
 
+import com.ruoyi.system.model.TDeptToUser;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 import com.ruoyi.system.domain.SysUserRole;
@@ -70,4 +71,6 @@
      * @return 结果
      */
     public int deleteUserRoleInfos(@Param("roleId") Long roleId, @Param("userIds") Long[] userIds);
+
+    void insertBatchUserDept(List<TDeptToUser> deptToUserList);
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TCheckAcceptRecordMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TCheckAcceptRecordMapper.java
index 2a7f4d6..ee37eff 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TCheckAcceptRecordMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TCheckAcceptRecordMapper.java
@@ -1,7 +1,13 @@
 package com.ruoyi.system.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.common.basic.PageInfo;
 import com.ruoyi.system.model.TCheckAcceptRecord;
+import com.ruoyi.system.query.TCheckAcceptRecordQuery;
+import com.ruoyi.system.vo.TCheckAcceptRecordVO;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
 
 /**
  * <p>
@@ -13,4 +19,13 @@
  */
 public interface TCheckAcceptRecordMapper extends BaseMapper<TCheckAcceptRecord> {
 
+    /**
+     * 分页查询验收记录
+     * @param query
+     * @param pageInfo
+     * @return
+     */
+    List<TCheckAcceptRecordVO> pageList(@Param("query") TCheckAcceptRecordQuery query, @Param("pageInfo")PageInfo<TCheckAcceptRecordVO> pageInfo);
+
+
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TDeptToUserMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TDeptToUserMapper.java
index effd9a5..37dfe49 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TDeptToUserMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TDeptToUserMapper.java
@@ -2,6 +2,7 @@
 
 import com.ruoyi.system.model.TDeptToUser;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
 
 /**
  * <p>
@@ -11,6 +12,14 @@
  * @author xiaochen
  * @since 2025-02-06
  */
+@Mapper
 public interface TDeptToUserMapper extends BaseMapper<TDeptToUser> {
 
+    /**
+     * 根据用户ID删除部门用户中间表
+     *
+     * @param userId 用户ID
+     * @return 删除结果
+     **/
+    int deleteUserDeptByUserId(Long userId);
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TFaultAreaDicMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TFaultAreaDicMapper.java
index a4dcc5e..7879534 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TFaultAreaDicMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TFaultAreaDicMapper.java
@@ -4,6 +4,7 @@
 import com.ruoyi.common.basic.PageInfo;
 import com.ruoyi.system.model.TFaultAreaDic;
 import com.ruoyi.system.query.TFaultAreaDicQuery;
+import com.ruoyi.system.vo.TFaultAreaDicVO;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
@@ -28,4 +29,9 @@
      */
     List<TFaultAreaDic> pageList(@Param("query")TFaultAreaDicQuery query, @Param("pageInfo")PageInfo<TFaultAreaDic> pageInfo);
 
+    /**
+     * 查询列表
+     * @return
+     */
+    List<TFaultAreaDicVO> getAreaDicList();
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TFaultRepairMessageMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TFaultRepairMessageMapper.java
index 66060aa..b9774a9 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TFaultRepairMessageMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TFaultRepairMessageMapper.java
@@ -1,7 +1,13 @@
 package com.ruoyi.system.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.common.basic.PageInfo;
 import com.ruoyi.system.model.TFaultRepairMessage;
+import com.ruoyi.system.query.TFaultRepairMessageQuery;
+import com.ruoyi.system.vo.TFaultRepairMessageVO;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
 
 /**
  * <p>
@@ -13,4 +19,19 @@
  */
 public interface TFaultRepairMessageMapper extends BaseMapper<TFaultRepairMessage> {
 
+    /**
+     * 根据id查询报修管理
+     * @param id
+     * @return
+     */
+    TFaultRepairMessageVO getDetailById(@Param("id") String id);
+
+    /**
+     * 分页查询报修管理
+     * @param query
+     * @param pageInfo
+     * @return
+     */
+    List<TFaultRepairMessageVO> pageList(@Param("query") TFaultRepairMessageQuery query, @Param("pageInfo")PageInfo<TFaultRepairMessageVO> pageInfo);
+
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TItemTypeMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TItemTypeMapper.java
index 8b6aca6..3edc837 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TItemTypeMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TItemTypeMapper.java
@@ -4,6 +4,7 @@
 import com.ruoyi.common.basic.PageInfo;
 import com.ruoyi.system.model.TItemType;
 import com.ruoyi.system.query.TItemTypeQuery;
+import com.ruoyi.system.vo.TItemTypeVO;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
@@ -25,4 +26,8 @@
      * @return
      */
     List<TItemType> pageList(@Param("query") TItemTypeQuery query, @Param("pageInfo")PageInfo<TItemType> pageInfo);
+
+    List<TItemTypeVO> getItemList();
+
+
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/model/TCheckAcceptRecord.java b/ruoyi-system/src/main/java/com/ruoyi/system/model/TCheckAcceptRecord.java
index 4a266e8..6a50c67 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/model/TCheckAcceptRecord.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/model/TCheckAcceptRecord.java
@@ -84,7 +84,7 @@
     @TableField("pictures")
     private String pictures;
 
-    @ApiModelProperty(value = "验收结果 1=合格 2=不合格")
+    @ApiModelProperty(value = "验收结果 1=合格 0=不合格")
     @TableField("check_result")
     private Boolean checkResult;
 
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/model/TContract.java b/ruoyi-system/src/main/java/com/ruoyi/system/model/TContract.java
index 5a87bcd..800f497 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/model/TContract.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/model/TContract.java
@@ -133,6 +133,16 @@
     @TableField("remark")
     private String remark;
 
+    /**
+     * 1	待提交
+     * 2	待审批
+     * 3	未签订
+     * 4	已签订
+     * 5	已驳回
+     * 6	已终止
+     * 7	待结算
+     * 8	已结算
+     */
     @ApiModelProperty(value = "状态 待提交 待审批 未签订 已签订....")
     @TableField("status")
     private String status;
@@ -151,5 +161,8 @@
     @ApiModelProperty(value = "合计年租金")
     @TableField("total_year")
     private BigDecimal totalYear;
+    @ApiModelProperty(value = "房屋名称")
+    @TableField(exist = false)
+    private String houseName;
 
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/model/TFaultRepairMessage.java b/ruoyi-system/src/main/java/com/ruoyi/system/model/TFaultRepairMessage.java
index a0b05ef..c1dec51 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/model/TFaultRepairMessage.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/model/TFaultRepairMessage.java
@@ -34,12 +34,20 @@
     private String id;
 
     @ApiModelProperty(value = "用户id")
-    @TableField("app_user_id")
-    private String appUserId;
+    @TableField("tenant_id")
+    private String tenantId;
+
+    @ApiModelProperty(value = "物品分类id")
+    @TableField("item_type_id")
+    private String itemTypeId;
 
     @ApiModelProperty(value = "物品id")
     @TableField("item_id")
     private String itemId;
+
+    @ApiModelProperty(value = "合同id")
+    @TableField("contract_id")
+    private String contractId;
 
     @ApiModelProperty(value = "故障区域")
     @TableField("fault_area_name")
@@ -99,6 +107,10 @@
     @TableField("attachment")
     private String attachment;
 
+    @ApiModelProperty(value = "附件名称  逗号分割")
+    @TableField("attachment_name")
+    private String attachmentName;
+
     @ApiModelProperty(value = "状态 1=待处理 2=已处理")
     @TableField("status")
     private Integer status;
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/model/TInformation.java b/ruoyi-system/src/main/java/com/ruoyi/system/model/TInformation.java
index 7ebb8ff..10e3f55 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/model/TInformation.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/model/TInformation.java
@@ -67,4 +67,8 @@
     @TableField("attachment_name")
     private String attachmentName;
 
+    @ApiModelProperty(value = "查看次数")
+    @TableField(exist = false)
+    private Integer viewCount;
+
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/model/TTenant.java b/ruoyi-system/src/main/java/com/ruoyi/system/model/TTenant.java
index 92a1d88..cca42c8 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/model/TTenant.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/model/TTenant.java
@@ -88,5 +88,8 @@
     @ApiModelProperty(value = "登录密码")
     @TableField("password")
     private String password;
+    @ApiModelProperty(value = "微信openid")
+    @TableField("open_id")
+    private String openId;
 
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/query/SysUserQuery.java b/ruoyi-system/src/main/java/com/ruoyi/system/query/SysUserQuery.java
index 8609862..3727f0a 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/query/SysUserQuery.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/query/SysUserQuery.java
@@ -5,18 +5,20 @@
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
+import java.util.List;
+
 @Data
 @ApiModel(value = "账户列表query")
 public class SysUserQuery extends BasePage {
 
     @ApiModelProperty(value = "姓名")
-    private String nickName;
+    private String nickNameAndPhone;
 
     @ApiModelProperty(value = "角色id")
     private Integer roleId;
 
-    @ApiModelProperty(value = "手机号")
-    private String phonenumber;
+    @ApiModelProperty(value = "部门id集合")
+    private List<String> deptIds;
 
     @ApiModelProperty(value = "状态  0=正常 1=停用")
     private String status;
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/query/TCheckAcceptRecordQuery.java b/ruoyi-system/src/main/java/com/ruoyi/system/query/TCheckAcceptRecordQuery.java
new file mode 100644
index 0000000..89da8f4
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/query/TCheckAcceptRecordQuery.java
@@ -0,0 +1,22 @@
+package com.ruoyi.system.query;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.ruoyi.common.core.domain.model.TimeRangeQueryBody;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+@ApiModel(value = "验收记录查询对象query")
+public class TCheckAcceptRecordQuery extends TimeRangeQueryBody {
+
+    @ApiModelProperty(value = "房屋名称")
+    private String houseName;
+
+    @ApiModelProperty(value = "合同编号")
+    private String contractNumber;
+
+    @ApiModelProperty(value = "验收结果 1=合格 0=不合格")
+    private Boolean checkResult;
+
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/query/TFaultRepairMessageQuery.java b/ruoyi-system/src/main/java/com/ruoyi/system/query/TFaultRepairMessageQuery.java
new file mode 100644
index 0000000..3aa2f26
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/query/TFaultRepairMessageQuery.java
@@ -0,0 +1,27 @@
+package com.ruoyi.system.query;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.ruoyi.common.core.domain.BasePage;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+@ApiModel(value = "报修列表查询query")
+public class TFaultRepairMessageQuery extends BasePage {
+
+    @ApiModelProperty(value = "用户id")
+    private String tenantId;
+
+    @ApiModelProperty(value = "联系电话")
+    private String contactNumber;
+
+    @ApiModelProperty(value = "状态 1=待处理 2=已处理")
+    private Integer status;
+
+    @ApiModelProperty(value = "报修类型 1=常规维修 2=紧急抢修")
+    private Integer repairType;
+
+    @ApiModelProperty(value = "处理人")
+    private String handlePerson;
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/TCheckAcceptRecordService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/TCheckAcceptRecordService.java
index 4344575..dd07c92 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/TCheckAcceptRecordService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/TCheckAcceptRecordService.java
@@ -1,7 +1,10 @@
 package com.ruoyi.system.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.common.basic.PageInfo;
 import com.ruoyi.system.model.TCheckAcceptRecord;
+import com.ruoyi.system.query.TCheckAcceptRecordQuery;
+import com.ruoyi.system.vo.TCheckAcceptRecordVO;
 
 /**
  * <p>
@@ -13,4 +16,10 @@
  */
 public interface TCheckAcceptRecordService extends IService<TCheckAcceptRecord> {
 
+    /**
+     * 获取验收记录分页列表
+     * @param query
+     * @return
+     */
+    PageInfo<TCheckAcceptRecordVO> pageList(TCheckAcceptRecordQuery query);
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/TFaultAreaDicService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/TFaultAreaDicService.java
index 5ef09fb..721a161 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/TFaultAreaDicService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/TFaultAreaDicService.java
@@ -4,6 +4,9 @@
 import com.ruoyi.common.basic.PageInfo;
 import com.ruoyi.system.model.TFaultAreaDic;
 import com.ruoyi.system.query.TFaultAreaDicQuery;
+import com.ruoyi.system.vo.TFaultAreaDicVO;
+
+import java.util.List;
 
 /**
  * <p>
@@ -28,4 +31,7 @@
      * @return
      */
     boolean isExit(TFaultAreaDic dto);
+
+    List<TFaultAreaDicVO> getAreaDicList();
+
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/TFaultRepairMessageService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/TFaultRepairMessageService.java
index a51a68f..272ec26 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/TFaultRepairMessageService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/TFaultRepairMessageService.java
@@ -1,7 +1,10 @@
 package com.ruoyi.system.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.common.basic.PageInfo;
 import com.ruoyi.system.model.TFaultRepairMessage;
+import com.ruoyi.system.query.TFaultRepairMessageQuery;
+import com.ruoyi.system.vo.TFaultRepairMessageVO;
 
 /**
  * <p>
@@ -13,4 +16,17 @@
  */
 public interface TFaultRepairMessageService extends IService<TFaultRepairMessage> {
 
+    /**
+     * 查看报修详情
+     * @param id
+     * @return
+     */
+    TFaultRepairMessageVO getDetailById(String id);
+
+    /**
+     * 获取报修分页列表
+     * @param query
+     * @return
+     */
+    PageInfo<TFaultRepairMessageVO> pageList(TFaultRepairMessageQuery query);
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/TItemTypeService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/TItemTypeService.java
index d542486..14ee3d1 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/TItemTypeService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/TItemTypeService.java
@@ -4,6 +4,9 @@
 import com.ruoyi.common.basic.PageInfo;
 import com.ruoyi.system.model.TItemType;
 import com.ruoyi.system.query.TItemTypeQuery;
+import com.ruoyi.system.vo.TItemTypeVO;
+
+import java.util.List;
 
 /**
  * <p>
@@ -28,4 +31,6 @@
      * @return
      */
     PageInfo<TItemType> pageList(TItemTypeQuery query);
+
+    List<TItemTypeVO> getItemList();
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/TTenantService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/TTenantService.java
index 0357962..590f644 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/TTenantService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/TTenantService.java
@@ -2,9 +2,12 @@
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ruoyi.common.basic.PageInfo;
+import com.ruoyi.system.utils.wx.pojo.AppletUserDecodeData;
 import com.ruoyi.system.model.TTenant;
 import com.ruoyi.system.query.TTenantQuery;
 import com.ruoyi.system.vo.TenantVO;
+
+import java.util.Map;
 
 /**
  * <p>
@@ -22,4 +25,6 @@
      * @return
      */
     PageInfo<TenantVO> pageList(TTenantQuery query);
+
+
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
index 5fc26a4..ed7ae34 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
@@ -6,8 +6,14 @@
 import java.util.stream.Collectors;
 import javax.validation.Validator;
 
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.ruoyi.common.basic.PageInfo;
+import com.ruoyi.common.core.domain.entity.SysDept;
+import com.ruoyi.system.mapper.*;
+import com.ruoyi.system.model.TDept;
+import com.ruoyi.system.model.TDeptToUser;
 import com.ruoyi.system.query.SysUserQuery;
+import com.ruoyi.system.service.TDeptToUserService;
 import com.ruoyi.system.vo.SysUserVO;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -27,11 +33,6 @@
 import com.ruoyi.system.domain.SysPost;
 import com.ruoyi.system.domain.SysUserPost;
 import com.ruoyi.system.domain.SysUserRole;
-import com.ruoyi.system.mapper.SysPostMapper;
-import com.ruoyi.system.mapper.SysRoleMapper;
-import com.ruoyi.system.mapper.SysUserMapper;
-import com.ruoyi.system.mapper.SysUserPostMapper;
-import com.ruoyi.system.mapper.SysUserRoleMapper;
 import com.ruoyi.system.service.ISysConfigService;
 import com.ruoyi.system.service.ISysUserService;
 
@@ -59,9 +60,13 @@
 
     @Autowired
     private SysUserPostMapper userPostMapper;
+    @Autowired
+    private TDeptToUserMapper deptToUserMapper;
 
     @Autowired
     private ISysConfigService configService;
+    @Autowired
+    private TDeptMapper deptMapper;
 
     @Autowired
     protected Validator validator;
@@ -264,7 +269,7 @@
         // 新增用户信息
         int rows = userMapper.insertUser(user);
         // 新增用户岗位关联
-//        insertUserPost(user);
+        insertUserDept(user);
         // 新增用户与角色管理
         insertUserRoleId(user);
         return rows;
@@ -297,10 +302,10 @@
         userRoleMapper.deleteUserRoleByUserId(userId);
         // 新增用户与角色管理
         insertUserRoleId(user);
-        // 删除用户与岗位关联
-//        userPostMapper.deleteUserPostByUserId(userId);
-        // 新增用户与岗位管理
-//        insertUserPost(user);
+        // 删除用户与部门关联
+        deptToUserMapper.deleteUserDeptByUserId(userId);
+        // 新增用户与部门管理
+        insertUserDept(user);
         return userMapper.updateUser(user);
     }
 
@@ -401,6 +406,17 @@
     }
 
     /**
+     * 新增用户角色信息
+     *
+     * @param user 用户对象
+     */
+    public void insertUserDept(SysUser user)
+    {
+        this.insertUserDept(user.getUserId(), user.getDeptIds());
+    }
+
+
+    /**
      * 新增用户岗位信息
      * 
      * @param user 用户对象
@@ -460,6 +476,26 @@
             ur.setUserId(userId);
             ur.setRoleId(roleId);
             userRoleMapper.insertUserRole(ur);
+        }
+    }
+    /**
+     * 新增用户部门信息
+     *
+     * @param userId 用户ID
+     * @param deptIds 部门id集合
+     */
+    public void insertUserDept(Long userId, List<String> deptIds)
+    {
+        if (Objects.nonNull(userId) && !CollectionUtils.isEmpty(deptIds)){
+            List<TDeptToUser> deptToUserList = new ArrayList<>();
+            for (String deptId : deptIds) {
+                // 新增用户与角色管理
+                TDeptToUser deptToUser = new TDeptToUser();
+                deptToUser.setUserId(userId);
+                deptToUser.setDeptId(deptId);
+                deptToUserList.add(deptToUser);
+            }
+            userRoleMapper.insertBatchUserDept(deptToUserList);
         }
     }
 
@@ -628,6 +664,19 @@
     public PageInfo<SysUserVO> pageList(SysUserQuery query) {
         PageInfo<SysUserVO> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
         List<SysUserVO> list = userMapper.pageList(query,pageInfo);
+        if(CollectionUtils.isEmpty(list)){
+            return pageInfo;
+        }
+        List<Long> userIds = list.stream().map(SysUserVO::getUserId).collect(Collectors.toList());
+        // 查询所有部门
+        List<TDept> depts = deptMapper.selectList(Wrappers.lambdaQuery(TDept.class));
+        List<TDeptToUser> tDeptToUsers = deptToUserMapper.selectList(Wrappers.lambdaQuery(TDeptToUser.class)
+                .in(TDeptToUser::getUserId, userIds));
+        for (SysUserVO sysUserVO : list) {
+            tDeptToUsers.stream().filter(tDeptToUser -> tDeptToUser.getUserId().equals(sysUserVO.getUserId())).forEach(tDeptToUser -> {
+                sysUserVO.setDeptList(depts.stream().filter(tDept -> tDept.getId().equals(tDeptToUser.getDeptId())).map(TDept::getDeptName).collect(Collectors.toList()));
+            });
+        }
         pageInfo.setRecords(list);
         return pageInfo;
     }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TCheckAcceptRecordServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TCheckAcceptRecordServiceImpl.java
index 4181286..48052e2 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TCheckAcceptRecordServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TCheckAcceptRecordServiceImpl.java
@@ -1,10 +1,18 @@
 package com.ruoyi.system.service.impl;
 
+import com.ruoyi.common.basic.PageInfo;
+import com.ruoyi.common.constant.DictConstants;
+import com.ruoyi.common.utils.DictUtils;
 import com.ruoyi.system.mapper.TCheckAcceptRecordMapper;
 import com.ruoyi.system.model.TCheckAcceptRecord;
+import com.ruoyi.system.query.TCheckAcceptRecordQuery;
 import com.ruoyi.system.service.TCheckAcceptRecordService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.system.vo.SysUserVO;
+import com.ruoyi.system.vo.TCheckAcceptRecordVO;
 import org.springframework.stereotype.Service;
+
+import java.util.List;
 
 /**
  * <p>
@@ -17,4 +25,17 @@
 @Service
 public class TCheckAcceptRecordServiceImpl extends ServiceImpl<TCheckAcceptRecordMapper, TCheckAcceptRecord> implements TCheckAcceptRecordService {
 
+    @Override
+    public PageInfo<TCheckAcceptRecordVO> pageList(TCheckAcceptRecordQuery query) {
+        PageInfo<TCheckAcceptRecordVO> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
+        List<TCheckAcceptRecordVO> list = this.baseMapper.pageList(query,pageInfo);
+        list.forEach(item -> {
+            item.setCleanSituation(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION,item.getCleanSituation()));
+            item.setOverallSituation(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION,item.getOverallSituation()));
+            item.setDeviceSituation(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION,item.getDeviceSituation()));
+            item.setFurnitureSituation(DictUtils.getDictLabel(DictConstants.DICT_TYPE_CHECK_SITUATION,item.getFurnitureSituation()));
+        });
+        pageInfo.setRecords(list);
+        return pageInfo;
+    }
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TContractServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TContractServiceImpl.java
index 458ec6c..405a874 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TContractServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TContractServiceImpl.java
@@ -17,16 +17,21 @@
 import com.ruoyi.system.query.TContractBillQuery;
 import com.ruoyi.system.query.TContractQuery;
 import com.ruoyi.system.service.TBillService;
+import com.ruoyi.system.service.TContractRentTypeService;
 import com.ruoyi.system.service.TContractService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.system.vo.BillVO;
 import com.ruoyi.system.vo.CheckAcceptRecordVO;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
 import java.math.BigDecimal;
+import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.temporal.ChronoUnit;
+import java.time.temporal.TemporalAdjusters;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
@@ -118,6 +123,7 @@
         CheckAcceptRecordVO checkAcceptRecordVO = new CheckAcceptRecordVO();
         TCheckAcceptRecord tCheckAcceptRecord = checkAcceptRecordMapper.selectOne(new LambdaQueryWrapper<TCheckAcceptRecord>()
                 .eq(TCheckAcceptRecord::getContractId, id));
+        if (tCheckAcceptRecord==null)return checkAcceptRecordVO;
         BeanUtils.copyProperties(tCheckAcceptRecord,checkAcceptRecordVO);
         THouse tHouse = houseMapper.selectById(tCheckAcceptRecord.getHouseId());
         tHouse.setLeaseStatus(DictUtils.getDictLabel(DictConstants.DICT_TYPE_LEASE_STATUS,tHouse.getLeaseStatus()));
@@ -125,7 +131,8 @@
         checkAcceptRecordVO.setHouse(tHouse);
         return checkAcceptRecordVO;
     }
-
+    @Autowired
+    private TContractRentTypeService contractRentTypeService;
     @Override
     public R signContract(SignContractDTO dto) {
         TContract contract = contractMapper.selectById(dto.getId());
@@ -134,42 +141,475 @@
         contract.setSignature(dto.getSignature());
         contract.setStatus("2");
         contractMapper.updateById(contract);
-        // 用户签订合同后 生成第一批账单包含租金账单和押金账单 后续账单通过定时任务生成
-        TBill rent = new TBill();
-        rent.setContractId(contract.getId());
-        // 应缴费租金
-        BigDecimal payableFeesMoney = new BigDecimal("0");
-        LocalDateTime startTime = contract.getStartTime();
-        LocalDateTime endTime = contract.getEndTime();
-//        // 计算相差多少天
-//        long days = ChronoUnit.DAYS.between(startTime, endTime);
-//        // 计算相差多少个月
-//        long months = ChronoUnit.MONTHS.between(startTime, endTime);
-//        if (months<=31){
-//            // 小于等于一个月 合计租金就是首笔账单金额
-//            payableFeesMoney = contract.getTotalRent();
-//        }else{
-//            switch (contract.getPayType()){
-//                case "1":
-//                    break;
-//                case "2":
-//                    break;
-//                case "3":
-//                    break;
-//            }
-//        }
-//
-//        rent.setPayableFeesMoney(payableFeesMoney);
-//        rent.setPayableFeesTime(contract.getFirstPayTime());
-//        rent.setPayFeesStatus("1");
-//        rent.setBillType("1");
-//
-//        TBill deposit = new TBill();
-//        deposit.setContractId(contract.getId());
-//        deposit.setPayableFeesMoney(contract.getDeposit());
-//        deposit.setPayableFeesTime(contract.getFirstPayTime());
-//        deposit.setPayFeesStatus("1");
-//        deposit.setBillType("2");
+        contract.setFirstPayTime(contract.getStartTime().plusDays(10));
+        List<TBill> bills = new ArrayList<>();
+        List<TContractRentType> contractRentTypes = contractRentTypeService.list();
+        // 生成第一笔账单
+        // 第一次应缴费日期
+        LocalDateTime firstPayTime = contract.getStartTime().plusDays(10).withHour(0).withMinute(0).withSecond(0);
+        TBill rentBill = new TBill();
+        rentBill.setContractId(contract.getId());
+        rentBill.setContractNumber(contract.getContractNumber());
+        rentBill.setPayableFeesTime(firstPayTime);
+        if (firstPayTime.toLocalDate().equals(LocalDate.now())){
+            rentBill.setPayFeesStatus("1");
+        }else {
+            rentBill.setPayFeesStatus("2");
+        }
+        rentBill.setBillType("1");
+        rentBill.setStartTime(contract.getStartPayTime());
+        TContractRentType tContractRentType = contractRentTypes.stream().filter(e -> e.getContractId().equals(contract.getId())).findFirst().orElse(null);
+        if (tContractRentType!=null && contract.getStartPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).isAfter(tContractRentType.getChangeTime())){
+            // 计算租金变动的天数
+            long moneyDays = ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), contract.getStartPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12))+1L;
+            contract.setChangeTime(LocalDateTime.now());
+            // 递增递减的租金
+            BigDecimal contractRentTypeMoney = new BigDecimal("0");
+            // 不递增递减的租金
+            BigDecimal originalMoney = new BigDecimal("0");
+            // 原租金
+            switch (tContractRentType.getIncreasingDecreasingType()){
+                case 1:
+                    switch (tContractRentType.getIncreasingDecreasing()){
+                        case 1:
+                            contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue())).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)));
+                            contract.setChangeRent(contractRentTypeMoney);
+                            break;
+                        case 2:
+                            contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().multiply((new BigDecimal(100).subtract(tContractRentType.getNumericalValue()))).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)).divide(new BigDecimal(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12),2,BigDecimal.ROUND_DOWN));
+                            contract.setChangeRent(contractRentTypeMoney);
+                            break;
+                    }
+                    break;
+                case 2:
+                    switch (tContractRentType.getIncreasingDecreasing()){
+                        case 1:
+                            contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
+                            contract.setChangeRent(contractRentTypeMoney);
+                            break;
+                        case 2:
+                            contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
+                            contract.setChangeRent(contractRentTypeMoney);
+
+                            break;
+                    }
+                    break;
+            }
+            // 不需要涨租金的时间段
+            long originalDays = ChronoUnit.DAYS.between(contract.getFirstPayTime(), tContractRentType.getChangeTime());
+            originalMoney=originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
+                    .multiply(new BigDecimal(originalDays));
+            rentBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
+            rentBill.setOutstandingMoney(rentBill.getPayableFeesMoney());
+            if (contract.getFirstPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).isAfter(contract.getEndTime())){
+                rentBill.setEndTime(contract.getFirstPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12));
+            }else{
+                rentBill.setEndTime(contract.getEndTime());
+            }
+        }else{
+            if (contract.getFirstPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).isAfter(contract.getEndTime())){
+                rentBill.setEndTime(contract.getFirstPayTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12));
+            }else{
+                rentBill.setEndTime(contract.getEndTime());
+            }
+            // 不走递增递减
+            long allDays = ChronoUnit.DAYS.between(contract.getFirstPayTime(), rentBill.getEndTime());
+            rentBill.setPayableFeesMoney(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(allDays)));
+            rentBill.setOutstandingMoney(rentBill.getPayableFeesMoney());
+
+        }
+        // 押金账单
+        TBill depositBill = new TBill();
+        depositBill.setContractId(contract.getId());
+        depositBill.setContractNumber(contract.getContractNumber());
+        depositBill.setPayableFeesMoney(contract.getDeposit());
+        depositBill.setOutstandingMoney(depositBill.getPayableFeesMoney());
+        depositBill.setStartTime(contract.getStartPayTime());
+        depositBill.setEndTime(contract.getEndTime());
+        depositBill.setPayableFeesTime(firstPayTime);
+        if (firstPayTime.toLocalDate().equals(LocalDate.now())){
+            depositBill.setPayFeesStatus("1");
+
+        }else {
+            depositBill.setPayFeesStatus("2");
+
+        }
+        depositBill.setBillType("2");
+        this.updateById(contract);
+        billService.save(rentBill);
+        billService.save(depositBill);
+        // 生成后续账单
+        try {
+            TBill beforeBill = billService.lambdaQuery().eq(TBill::getContractId, contract.getId()).eq(TBill::getBillType, 1).orderByDesc(TBill::getCreateTime)
+                    .last("limit 1").one();
+            if (!beforeBill.getEndTime().toLocalDate().equals(contract.getEndTime().toLocalDate())){
+
+
+            while(beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).isBefore(contract.getEndTime())){
+
+                    TBill tBill = new TBill();
+                    tBill.setContractId(contract.getId());
+                    tBill.setContractNumber(contract.getContractNumber());
+                    // 根据支付方式判断需不需要生成订单
+                    if (!(beforeBill.getEndTime().toLocalDate().equals(contract.getEndTime().toLocalDate()))
+                            &&
+                            (contract.getPayType().equals("1")?
+                                    beforeBill.getEndTime().plusMonths(1):contract.getPayType().equals("2")?
+                                    beforeBill.getEndTime().plusMonths(3):beforeBill.getEndTime().plusMonths(12))
+                                    .with(TemporalAdjusters.lastDayOfMonth()).isBefore(contract.getEndTime())
+                            && beforeBill.getEndTime().isBefore(contract.getEndTime())
+                    ){
+                        tBill.setContractId(contract.getId());
+                        if (contract.getIsIncreasing()){
+                            if (tContractRentType!=null
+                                    && beforeBill.getEndTime().isBefore(tContractRentType.getChangeTime())
+                                    && beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).with(TemporalAdjusters.lastDayOfMonth()).isAfter(tContractRentType.getChangeTime())){
+                                // 如果没变过
+                                if (contract.getChangeTime()==null){
+                                    contract.setChangeTime(LocalDateTime.now());
+                                    // 租金递增递减的时长 天
+                                    long moneyDays = ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), contract.getEndTime());
+                                    // 递增递减的租金
+                                    BigDecimal contractRentTypeMoney = new BigDecimal("0");
+                                    // 不递增递减的租金
+                                    BigDecimal originalMoney = new BigDecimal("0");
+                                    // 原租金
+                                    switch (tContractRentType.getIncreasingDecreasingType()){
+                                        case 1:
+                                            switch (tContractRentType.getIncreasingDecreasing()){
+                                                case 1:
+                                                    contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue())).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)));
+                                                    contract.setChangeRent(contractRentTypeMoney);
+                                                    break;
+                                                case 2:
+                                                    contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().multiply((new BigDecimal(100).subtract(tContractRentType.getNumericalValue()))).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)).divide(new BigDecimal(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12),2,BigDecimal.ROUND_DOWN));
+                                                    contract.setChangeRent(contractRentTypeMoney);
+                                                    break;
+                                            }
+                                            break;
+                                        case 2:
+                                            switch (tContractRentType.getIncreasingDecreasing()){
+                                                case 1:
+                                                    contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
+                                                    contract.setChangeRent(contractRentTypeMoney);
+                                                    break;
+                                                case 2:
+                                                    contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
+                                                    contract.setChangeRent(contractRentTypeMoney);
+
+                                                    break;
+                                            }
+                                            break;
+                                    }
+                                    // 不需要涨租金的时间段
+                                    long originalDays = ChronoUnit.DAYS.between(beforeBill.getEndTime(), tContractRentType.getChangeTime());
+                                    originalMoney=originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
+                                            .multiply(new BigDecimal(originalDays));
+                                    tBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
+                                    tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
+
+                                }else{
+                                    // 之前已经涨、跌过租金了 需要判断周期是否还需要再涨、跌
+                                    if ((LocalDateTime.now().getYear() - contract.getChangeTime().getYear())%tContractRentType.getCycleTime()==0){
+                                        contract.setChangeTime(LocalDateTime.now());
+                                        // 租金递增递减的时长 天
+                                        long moneyDays = ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), contract.getEndTime());
+                                        // 递增递减的租金
+                                        BigDecimal contractRentTypeMoney = new BigDecimal("0");
+                                        // 不递增递减的租金
+                                        BigDecimal originalMoney = new BigDecimal("0");
+                                        // 原租金
+                                        switch (tContractRentType.getIncreasingDecreasingType()){
+                                            case 1:
+                                                switch (tContractRentType.getIncreasingDecreasing()){
+                                                    case 1:
+                                                        contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue())).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)));
+                                                        contract.setChangeRent(contractRentTypeMoney);
+                                                        break;
+                                                    case 2:
+                                                        contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().multiply((new BigDecimal(100).subtract(tContractRentType.getNumericalValue()))).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)).divide(new BigDecimal(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12),2,BigDecimal.ROUND_DOWN));
+                                                        contract.setChangeRent(contractRentTypeMoney);
+                                                        break;
+                                                }
+                                                break;
+                                            case 2:
+                                                switch (tContractRentType.getIncreasingDecreasing()){
+                                                    case 1:
+                                                        contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
+                                                        contract.setChangeRent(contractRentTypeMoney);
+                                                        break;
+                                                    case 2:
+                                                        contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
+                                                        contract.setChangeRent(contractRentTypeMoney);
+
+                                                        break;
+                                                }
+                                                break;
+                                        }
+                                        // 不需要涨租金的时间段
+                                        long originalDays = ChronoUnit.DAYS.between(beforeBill.getEndTime(), tContractRentType.getChangeTime());
+                                        originalMoney=originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
+                                                .multiply(new BigDecimal(originalDays));
+                                        tBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
+                                        tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
+
+                                    }else{
+                                        // 不涨租金 用上次的
+                                        // 租金递增递减的时长 天
+                                        long moneyDays = ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), contract.getEndTime());
+                                        // 递增递减的租金
+                                        BigDecimal contractRentTypeMoney = new BigDecimal("0");
+                                        // 不递增递减的租金
+                                        BigDecimal originalMoney = new BigDecimal("0");
+                                        // 原租金
+                                        switch (tContractRentType.getIncreasingDecreasingType()){
+                                            case 1:
+                                                switch (tContractRentType.getIncreasingDecreasing()){
+                                                    case 1:
+                                                        contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue())).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)));
+                                                        contract.setChangeRent(contractRentTypeMoney);
+                                                        break;
+                                                    case 2:
+                                                        contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().multiply((new BigDecimal(100).subtract(tContractRentType.getNumericalValue()))).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)).divide(new BigDecimal(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12),2,BigDecimal.ROUND_DOWN));
+                                                        contract.setChangeRent(contractRentTypeMoney);
+                                                        break;
+                                                }
+                                                break;
+                                            case 2:
+                                                switch (tContractRentType.getIncreasingDecreasing()){
+                                                    case 1:
+                                                        contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
+                                                        contract.setChangeRent(contractRentTypeMoney);
+                                                        break;
+                                                    case 2:
+                                                        contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
+                                                        contract.setChangeRent(contractRentTypeMoney);
+
+                                                        break;
+                                                }
+                                                break;
+                                        }
+                                        // 不需要涨租金的时间段
+                                        long originalDays = ChronoUnit.DAYS.between(beforeBill.getEndTime(), tContractRentType.getChangeTime());
+                                        originalMoney=originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
+                                                .multiply(new BigDecimal(originalDays));
+                                        tBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
+                                        tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
+
+                                    }
+                                }
+
+                            }
+                        }else{
+                            long allDays = ChronoUnit.DAYS.between(beforeBill.getEndTime(), (contract.getPayType().equals("1")?
+                                    beforeBill.getEndTime().plusMonths(1):contract.getPayType().equals("2")?
+                                    beforeBill.getEndTime().plusMonths(3):beforeBill.getEndTime().plusMonths(12)).with(TemporalAdjusters.lastDayOfMonth()));
+                            tBill.setPayableFeesMoney(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(allDays)));
+                            tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
+
+                        }
+                        tBill.setContractNumber(contract.getContractNumber());
+                        if (beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).getDayOfMonth()<=15){
+                            tBill.setPayableFeesTime(contract.getEndTime());
+                        }else{
+                            tBill.setPayableFeesTime((contract.getPayType().equals("1")?
+                                    beforeBill.getEndTime().plusMonths(1).withDayOfMonth(15):contract.getPayType().equals("2")?
+                                    beforeBill.getEndTime().plusMonths(3).withDayOfMonth(15):beforeBill.getEndTime().withDayOfMonth(15).plusMonths(12)));
+                        }
+                        tBill.setPayFeesStatus("2");
+                        tBill.setBillType("1");
+                        tBill.setStartTime(beforeBill.getEndTime().plusDays(1));
+                        tBill.setEndTime(contract.getEndTime());
+                    }
+                    billMapper.insert(tBill);
+                }
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        TBill beforeBill = billService.lambdaQuery().eq(TBill::getContractId, contract.getId()).eq(TBill::getBillType, 1).orderByDesc(TBill::getCreateTime)
+                .last("limit 1").one();
+        // 生成最后一笔账单
+        if (!(beforeBill.getEndTime().toLocalDate().equals(contract.getEndTime().toLocalDate()))
+                &&
+                (contract.getPayType().equals("1")?
+                        beforeBill.getEndTime().plusMonths(1):contract.getPayType().equals("2")?
+                        beforeBill.getEndTime().plusMonths(3):beforeBill.getEndTime().plusMonths(12))
+                        .with(TemporalAdjusters.lastDayOfMonth()).isAfter(contract.getEndTime())
+                && beforeBill.getEndTime().isBefore(contract.getEndTime())
+        ){
+            TBill tBill = new TBill();
+            tBill.setContractId(contract.getId());
+
+            if (contract.getIsIncreasing()){
+                if (tContractRentType!=null
+                        && beforeBill.getEndTime().isBefore(tContractRentType.getChangeTime())
+                        && beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).with(TemporalAdjusters.lastDayOfMonth()).isAfter(tContractRentType.getChangeTime())){
+                    // 如果没变过
+                    if (contract.getChangeTime()==null){
+                        contract.setChangeTime(LocalDateTime.now());
+                        // 租金递增递减的时长 天
+                        long moneyDays = ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), contract.getEndTime());
+                        // 递增递减的租金
+                        BigDecimal contractRentTypeMoney = new BigDecimal("0");
+                        // 不递增递减的租金
+                        BigDecimal originalMoney = new BigDecimal("0");
+                        // 原租金
+                        switch (tContractRentType.getIncreasingDecreasingType()){
+                            case 1:
+                                switch (tContractRentType.getIncreasingDecreasing()){
+                                    case 1:
+                                        contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue())).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)));
+                                        contract.setChangeRent(contractRentTypeMoney);
+                                        break;
+                                    case 2:
+                                        contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().multiply((new BigDecimal(100).subtract(tContractRentType.getNumericalValue()))).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)).divide(new BigDecimal(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12),2,BigDecimal.ROUND_DOWN));
+                                        contract.setChangeRent(contractRentTypeMoney);
+                                        break;
+                                }
+                                break;
+                            case 2:
+                                switch (tContractRentType.getIncreasingDecreasing()){
+                                    case 1:
+                                        contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
+                                        contract.setChangeRent(contractRentTypeMoney);
+                                        break;
+                                    case 2:
+                                        contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
+                                        contract.setChangeRent(contractRentTypeMoney);
+
+                                        break;
+                                }
+                                break;
+                        }
+                        // 不需要涨租金的时间段
+                        long originalDays = ChronoUnit.DAYS.between(beforeBill.getEndTime(), tContractRentType.getChangeTime());
+
+                        // 不需要涨租金的时间段
+                        if (contract.getFirstPayTime().isBefore(tContractRentType.getChangeTime())){
+                            originalMoney=originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
+                                    .multiply(new BigDecimal(originalDays));
+                            tBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
+                            tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
+                        }else{
+                            tBill.setPayableFeesMoney(contractRentTypeMoney);
+                            tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
+                        }
+
+                    }else{
+                        // 之前已经涨、跌过租金了 需要判断周期是否还需要再涨、跌
+                        if ((LocalDateTime.now().getYear() - contract.getChangeTime().getYear())%tContractRentType.getCycleTime()==0){
+                            contract.setChangeTime(LocalDateTime.now());
+                            // 租金递增递减的时长 天
+                            long moneyDays = ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), contract.getEndTime());
+                            // 递增递减的租金
+                            BigDecimal contractRentTypeMoney = new BigDecimal("0");
+                            // 不递增递减的租金
+                            BigDecimal originalMoney = new BigDecimal("0");
+                            // 原租金
+                            switch (tContractRentType.getIncreasingDecreasingType()){
+                                case 1:
+                                    switch (tContractRentType.getIncreasingDecreasing()){
+                                        case 1:
+                                            contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue())).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)));
+                                            contract.setChangeRent(contractRentTypeMoney);
+                                            break;
+                                        case 2:
+                                            contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().multiply((new BigDecimal(100).subtract(tContractRentType.getNumericalValue()))).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)).divide(new BigDecimal(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12),2,BigDecimal.ROUND_DOWN));
+                                            contract.setChangeRent(contractRentTypeMoney);
+                                            break;
+                                    }
+                                    break;
+                                case 2:
+                                    switch (tContractRentType.getIncreasingDecreasing()){
+                                        case 1:
+                                            contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
+                                            contract.setChangeRent(contractRentTypeMoney);
+                                            break;
+                                        case 2:
+                                            contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
+                                            contract.setChangeRent(contractRentTypeMoney);
+
+                                            break;
+                                    }
+                                    break;
+                            }
+                            // 不需要涨租金的时间段
+                            long originalDays = ChronoUnit.DAYS.between(beforeBill.getEndTime(), tContractRentType.getChangeTime());
+                            originalMoney=originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
+                                    .multiply(new BigDecimal(originalDays));
+                            tBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
+                            tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
+
+                        }else{
+                            // 不涨租金 用上次的
+                            // 租金递增递减的时长 天
+                            long moneyDays = ChronoUnit.DAYS.between(tContractRentType.getChangeTime(), contract.getEndTime());
+                            // 递增递减的租金
+                            BigDecimal contractRentTypeMoney = new BigDecimal("0");
+                            // 不递增递减的租金
+                            BigDecimal originalMoney = new BigDecimal("0");
+                            // 原租金
+                            switch (tContractRentType.getIncreasingDecreasingType()){
+                                case 1:
+                                    switch (tContractRentType.getIncreasingDecreasing()){
+                                        case 1:
+                                            contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().multiply(new BigDecimal(100).add(tContractRentType.getNumericalValue())).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)));
+                                            contract.setChangeRent(contractRentTypeMoney);
+                                            break;
+                                        case 2:
+                                            contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().multiply((new BigDecimal(100).subtract(tContractRentType.getNumericalValue()))).divide(new BigDecimal(100),2,BigDecimal.ROUND_DOWN).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays)).divide(new BigDecimal(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12),2,BigDecimal.ROUND_DOWN));
+                                            contract.setChangeRent(contractRentTypeMoney);
+                                            break;
+                                    }
+                                    break;
+                                case 2:
+                                    switch (tContractRentType.getIncreasingDecreasing()){
+                                        case 1:
+                                            contractRentTypeMoney =contractRentTypeMoney.add(contract.getChangeRent().add(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
+                                            contract.setChangeRent(contractRentTypeMoney);
+                                            break;
+                                        case 2:
+                                            contractRentTypeMoney = contractRentTypeMoney.add(contract.getChangeRent().subtract(tContractRentType.getNumericalValue())).divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(moneyDays));
+                                            contract.setChangeRent(contractRentTypeMoney);
+
+                                            break;
+                                    }
+                                    break;
+                            }
+                            // 不需要涨租金的时间段
+                            long originalDays = ChronoUnit.DAYS.between(beforeBill.getEndTime(), tContractRentType.getChangeTime());
+                            originalMoney=originalMoney.add(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN))
+                                    .multiply(new BigDecimal(originalDays));
+                            tBill.setPayableFeesMoney(contractRentTypeMoney.add(originalMoney));
+                            tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
+
+                        }
+                    }
+
+                }
+            }else{
+                long allDays = ChronoUnit.DAYS.between(beforeBill.getEndTime(), contract.getEndTime());
+                tBill.setPayableFeesMoney(contract.getMonthRent().divide(new BigDecimal(30), 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(allDays)));
+                tBill.setOutstandingMoney(tBill.getPayableFeesMoney());
+
+            }
+            tBill.setContractNumber(contract.getContractNumber());
+            if (beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12).getDayOfMonth()<=15){
+                tBill.setPayableFeesTime(contract.getEndTime().withHour(0).withMinute(0).withSecond(0));
+            }else{
+                tBill.setPayableFeesTime((contract.getPayType().equals("1")?
+                        beforeBill.getEndTime().plusMonths(1).withDayOfMonth(15):contract.getPayType().equals("2")?
+                        beforeBill.getEndTime().plusMonths(3).withDayOfMonth(15):beforeBill.getEndTime().withDayOfMonth(15).plusMonths(12).withHour(0).withMinute(0).withSecond(0)));
+            }
+            tBill.setPayFeesStatus("1");
+            tBill.setBillType("1");
+            tBill.setStartTime(beforeBill.getEndTime().plusDays(1));
+            tBill.setEndTime(beforeBill.getEndTime().plusMonths(contract.getPayType().equals("1")? 1:contract.getPayType().equals("2")? 3:12));
+            billService.save(tBill);
+        }
+
         return R.ok();
     }
 
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TFaultAreaDicServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TFaultAreaDicServiceImpl.java
index 094504b..93d55ba 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TFaultAreaDicServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TFaultAreaDicServiceImpl.java
@@ -11,6 +11,7 @@
 import com.ruoyi.system.query.TFaultAreaDicQuery;
 import com.ruoyi.system.service.TFaultAreaDicService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.system.vo.TFaultAreaDicVO;
 import com.ruoyi.system.vo.TenantVO;
 import org.springframework.stereotype.Service;
 
@@ -45,4 +46,9 @@
             return this.count(Wrappers.lambdaQuery(TFaultAreaDic.class).eq(TFaultAreaDic::getFaultAreaName, dto.getFaultAreaName())) > 0;
         }
     }
+
+    @Override
+    public List<TFaultAreaDicVO> getAreaDicList() {
+        return this.baseMapper.getAreaDicList();
+    }
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TFaultRepairMessageServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TFaultRepairMessageServiceImpl.java
index d406d42..8c3df80 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TFaultRepairMessageServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TFaultRepairMessageServiceImpl.java
@@ -1,10 +1,16 @@
 package com.ruoyi.system.service.impl;
 
+import com.ruoyi.common.basic.PageInfo;
 import com.ruoyi.system.mapper.TFaultRepairMessageMapper;
 import com.ruoyi.system.model.TFaultRepairMessage;
+import com.ruoyi.system.query.TFaultRepairMessageQuery;
 import com.ruoyi.system.service.TFaultRepairMessageService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.system.vo.SysOperLogVO;
+import com.ruoyi.system.vo.TFaultRepairMessageVO;
 import org.springframework.stereotype.Service;
+
+import java.util.List;
 
 /**
  * <p>
@@ -17,4 +23,16 @@
 @Service
 public class TFaultRepairMessageServiceImpl extends ServiceImpl<TFaultRepairMessageMapper, TFaultRepairMessage> implements TFaultRepairMessageService {
 
+    @Override
+    public TFaultRepairMessageVO getDetailById(String id) {
+        return this.baseMapper.getDetailById(id);
+    }
+
+    @Override
+    public PageInfo<TFaultRepairMessageVO> pageList(TFaultRepairMessageQuery query) {
+        PageInfo<TFaultRepairMessageVO> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
+        List<TFaultRepairMessageVO> list = this.baseMapper.pageList(query,pageInfo);
+        pageInfo.setRecords(list);
+        return pageInfo;
+    }
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TInformationServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TInformationServiceImpl.java
index 282470c..103124e 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TInformationServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TInformationServiceImpl.java
@@ -1,12 +1,15 @@
 package com.ruoyi.system.service.impl;
 
 import com.ruoyi.common.basic.PageInfo;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.core.redis.RedisCache;
 import com.ruoyi.system.mapper.TInformationMapper;
 import com.ruoyi.system.model.TInformation;
 import com.ruoyi.system.query.TInformationQuery;
 import com.ruoyi.system.service.TInformationService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.system.vo.HouseVO;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
@@ -22,10 +25,16 @@
 @Service
 public class TInformationServiceImpl extends ServiceImpl<TInformationMapper, TInformation> implements TInformationService {
 
+    @Autowired
+    private RedisCache redisCache;
+
     @Override
     public PageInfo<TInformation> pageList(TInformationQuery query) {
         PageInfo<TInformation> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
         List<TInformation> list = this.baseMapper.pageList(query,pageInfo);
+        list.forEach(item -> {
+            item.setViewCount(redisCache.getCacheObject(Constants.INFORMATION_VIEW + item.getId()));
+        });
         pageInfo.setRecords(list);
         return pageInfo;
     }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TItemTypeServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TItemTypeServiceImpl.java
index 8696828..d579295 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TItemTypeServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TItemTypeServiceImpl.java
@@ -10,6 +10,7 @@
 import com.ruoyi.system.query.TItemTypeQuery;
 import com.ruoyi.system.service.TItemTypeService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.system.vo.TItemTypeVO;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
@@ -43,4 +44,9 @@
         pageInfo.setRecords(list);
         return pageInfo;
     }
+
+    @Override
+    public List<TItemTypeVO> getItemList() {
+        return this.baseMapper.getItemList();
+    }
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTenantServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTenantServiceImpl.java
index c6d65f1..95a8452 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTenantServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTenantServiceImpl.java
@@ -1,18 +1,20 @@
 package com.ruoyi.system.service.impl;
 
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.common.basic.PageInfo;
 import com.ruoyi.common.constant.DictConstants;
 import com.ruoyi.common.utils.DictUtils;
+import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.system.mapper.TTenantMapper;
 import com.ruoyi.system.model.TTenant;
 import com.ruoyi.system.query.TTenantQuery;
 import com.ruoyi.system.service.TTenantService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.system.vo.SysUserVO;
+import com.ruoyi.system.utils.wx.pojo.AppletUserDecodeData;
 import com.ruoyi.system.vo.TenantVO;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * <p>
@@ -30,10 +32,11 @@
         PageInfo<TenantVO> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
         List<TenantVO> list = this.baseMapper.pageList(query,pageInfo);
         for (TenantVO tenantVO : list) {
-            tenantVO.setTenantAttributesName(DictUtils.getDictLabel(DictConstants.DICT_TYPE_TENANT_ATTRIBUTE,tenantVO.getTenantAttributes()));
-            tenantVO.setTenantTypeName(DictUtils.getDictLabel(DictConstants.DICT_TYPE_TENANT_TYPE,tenantVO.getTenantType()));
+            tenantVO.setTenantAttributesName(StringUtils.isNotBlank(tenantVO.getTenantAttributes())?DictUtils.getDictLabel(DictConstants.DICT_TYPE_TENANT_ATTRIBUTE,tenantVO.getTenantAttributes()):"");
+            tenantVO.setTenantTypeName(StringUtils.isNotBlank(tenantVO.getTenantType())?DictUtils.getDictLabel(DictConstants.DICT_TYPE_TENANT_TYPE,tenantVO.getTenantType()):"");
         }
         pageInfo.setRecords(list);
         return pageInfo;
     }
+
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/body/resp/AccessTokenRespBody.java b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/body/resp/AccessTokenRespBody.java
new file mode 100644
index 0000000..db2d1b4
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/body/resp/AccessTokenRespBody.java
@@ -0,0 +1,28 @@
+package com.ruoyi.system.utils.wx.body.resp;
+
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * AccessToken 全局唯一
+ *
+ * @author xiaochen
+ */
+@Data
+public class AccessTokenRespBody extends RespBody implements Serializable {
+
+    /**
+     * 获取到的凭证
+     */
+    @JsonProperty("access_token")
+    private String accessToken;
+    /**
+     * 凭证有效时间,单位:秒
+     */
+    @JsonProperty("expires_in")
+    private int expiresIn;
+
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/body/resp/Code2SessionRespBody.java b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/body/resp/Code2SessionRespBody.java
new file mode 100644
index 0000000..d741edb
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/body/resp/Code2SessionRespBody.java
@@ -0,0 +1,29 @@
+package com.ruoyi.system.utils.wx.body.resp;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+/**
+ * @author xiaochen
+ * @ClassName Code2SessionRespBody
+ * @Description
+ * @date 2021-07-28 12:35
+ */
+@Data
+public class Code2SessionRespBody extends RespBody {
+    /**
+     * 用户唯一标识
+     */
+    @JsonProperty("openid")
+    private String openid;
+    /**
+     * 会话密钥
+     */
+    @JsonProperty("session_key")
+    private String sessionKey;
+    /**
+     * 用户在开放平台的唯一标识符,若当前小程序已绑定到微信开放平台帐号下会返回,详见 UnionID 机制说明。
+     */
+    @JsonProperty("unionid")
+    private String unionid;
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/body/resp/RespBody.java b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/body/resp/RespBody.java
new file mode 100644
index 0000000..ee60ab3
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/body/resp/RespBody.java
@@ -0,0 +1,19 @@
+package com.ruoyi.system.utils.wx.body.resp;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+/**
+ * @author xiaochen
+ * @ClassName RespBody
+ * @Description
+ * @date 2021-07-28 11:44
+ */
+@Data
+public class RespBody {
+    @JsonProperty("errcode")
+    private Integer errorCode;
+
+    @JsonProperty("errmsg")
+    private String errorMsg;
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/body/resq/Code2SessionResqBody.java b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/body/resq/Code2SessionResqBody.java
new file mode 100644
index 0000000..424e376
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/body/resq/Code2SessionResqBody.java
@@ -0,0 +1,21 @@
+package com.ruoyi.system.utils.wx.body.resq;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+/**
+ * @author xiaochen
+ * @ClassName Code2SessionResqBody
+ * @Description
+ * @date 2021-07-28 11:47
+ */
+@Data
+public class Code2SessionResqBody {
+    @JsonProperty("js_code")
+    private String jsCode;
+
+    public Code2SessionResqBody build(String jsCode) {
+        this.jsCode = jsCode;
+        return this;
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/model/WeixinProperties.java b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/model/WeixinProperties.java
new file mode 100644
index 0000000..fdeb5ab
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/model/WeixinProperties.java
@@ -0,0 +1,79 @@
+package com.ruoyi.system.utils.wx.model;
+
+import lombok.ToString;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author xiaochen
+ * @ClassName WeixinProperties
+ * @Description
+ * @date 2024-08-14 13:55
+ */
+@ToString
+@Component
+@ConfigurationProperties(prefix = "wx.conf")
+public class WeixinProperties {
+    /**
+     * 默认开启
+     */
+    private boolean enabled = true;
+    /**
+     * 获取 App ID
+     *
+     * @return App ID
+     */
+    private String appId;
+    /**
+     * 获取 Mch ID
+     *
+     * @return Mch ID
+     */
+    private String mchId;
+
+    /**
+     * 获取 secret ID
+     *
+     * @return secret ID
+     */
+    private String secretId;
+
+    public String getSecretId() {
+        return secretId;
+    }
+
+    public void setSecretId(String secretId) {
+        this.secretId = secretId;
+    }
+
+    /**
+     * HTTP(S) 连接超时时间,单位毫秒
+     *
+     */
+    public int getHttpConnectTimeoutMs() {
+        return 6 * 1000;
+    }
+
+    /**
+     * HTTP(S) 读数据超时时间,单位毫秒
+     */
+    public int getHttpReadTimeoutMs() {
+        return 8 * 1000;
+    }
+
+    public String getAppId() {
+        return appId;
+    }
+
+    public void setAppId(String appId) {
+        this.appId = appId;
+    }
+
+    public String getMchId() {
+        return mchId;
+    }
+
+    public void setMchId(String mchId) {
+        this.mchId = mchId;
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/pojo/AppletPhoneEncrypteData.java b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/pojo/AppletPhoneEncrypteData.java
new file mode 100644
index 0000000..c7f5257
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/pojo/AppletPhoneEncrypteData.java
@@ -0,0 +1,19 @@
+package com.ruoyi.system.utils.wx.pojo;
+
+import lombok.Data;
+
+/**
+ * @author xiaochen
+ * @ClassName AppletUserDecodeData
+ * @Description
+ * @date 2021-08-13 17:46
+ * 小程序加密数据体
+ *
+ */
+@Data
+public class AppletPhoneEncrypteData {
+    private String encryptedData;
+    private String openid;
+    private String unionid;
+    private String iv;
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/pojo/AppletUserDecodeData.java b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/pojo/AppletUserDecodeData.java
new file mode 100644
index 0000000..a3573ad
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/pojo/AppletUserDecodeData.java
@@ -0,0 +1,52 @@
+package com.ruoyi.system.utils.wx.pojo;
+
+import lombok.Data;
+
+/**
+ * @author xiaochen
+ * @ClassName AppletUserDecodeData
+ * @Description
+ * 用户主体信息部分
+ * {
+ *     "openId": "OPENID",
+ *     "nickName": "NICKNAME",
+ *     "gender": GENDER,
+ *     "city": "CITY",
+ *     "province": "PROVINCE",
+ *     "country": "COUNTRY",
+ *     "avatarUrl": "AVATARURL",
+ *     "unionId": "UNIONID",
+ *     "watermark":
+ *     {
+ *         "appid":"APPID",
+ *         "timestamp":TIMESTAMP
+ *     }
+ * }
+ * 电话部分
+ * {
+ *     "phoneNumber": "13580006666",
+ *     "purePhoneNumber": "13580006666",
+ *     "countryCode": "86",
+ *     "watermark":
+ *     {
+ *         "appid":"APPID",
+ *         "timestamp": TIMESTAMP
+ *     }
+ * }
+ *
+ */
+@Data
+public class AppletUserDecodeData {
+    private String openId;
+    private String unionId;
+    private String nickName;
+    private int gender;
+    private String city;
+    private String province;
+    private String country;
+    private String avatarUrl;
+    private Watermark watermark;
+    private String phoneNumber;
+    private String purePhoneNumber;
+    private String countryCode;
+}
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/pojo/AppletUserEncrypteData.java b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/pojo/AppletUserEncrypteData.java
new file mode 100644
index 0000000..16d0057
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/pojo/AppletUserEncrypteData.java
@@ -0,0 +1,20 @@
+package com.ruoyi.system.utils.wx.pojo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * @author xiaochen
+ * @ClassName AppletUserDecodeData
+ * @Description
+ * 小程序加密数据体
+ *
+ */
+@Data
+public class AppletUserEncrypteData extends AppletPhoneEncrypteData {
+    private String rawData;
+    private String signature;
+    private String code;
+    @ApiModelProperty(value = "邀请用户id")
+    private Long inviteUserId;
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/pojo/Watermark.java b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/pojo/Watermark.java
new file mode 100644
index 0000000..16f4f7a
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/pojo/Watermark.java
@@ -0,0 +1,9 @@
+package com.ruoyi.system.utils.wx.pojo;
+
+import lombok.Data;
+
+@Data
+public class Watermark {
+    private String appid;
+    private String timestamp;
+}
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/SHA1.java b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/SHA1.java
new file mode 100644
index 0000000..2b74822
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/SHA1.java
@@ -0,0 +1,36 @@
+package com.ruoyi.system.utils.wx.tools;
+
+import java.security.MessageDigest;
+
+public class SHA1 {
+
+
+    /**
+     * 用SHA1算法生成安全签名
+     *
+     * @param str
+     * @return
+     * @throws WxException
+     */
+    public static String getSHA1(String str) throws WxException {
+        try {
+            // SHA1签名生成
+            MessageDigest md = MessageDigest.getInstance("SHA-1");
+            md.update(str.getBytes());
+            byte[] digest = md.digest();
+            StringBuffer hexstr = new StringBuffer();
+            String shaHex;
+            for (int i = 0; i < digest.length; i++) {
+                shaHex = Integer.toHexString(digest[i] & 0xFF);
+                if (shaHex.length() < 2) {
+                    hexstr.append(0);
+                }
+                hexstr.append(shaHex);
+            }
+            return hexstr.toString();
+        } catch (Exception e) {
+            throw new WxException(WxException.ComputeSignatureError);
+        }
+    }
+
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WebUtils.java b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WebUtils.java
new file mode 100644
index 0000000..c2e15e1
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WebUtils.java
@@ -0,0 +1,48 @@
+package com.ruoyi.system.utils.wx.tools;
+
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+/**
+ * @Author xiaochen
+ * @Date 2019/08/26 10:28 AM
+ * @Description
+ */
+public final class WebUtils {
+
+    private WebUtils() {
+    }
+
+    /**
+     * 当前请求
+     */
+    public static HttpServletRequest request() {
+        return contextHolder() == null ? null : contextHolder().getRequest();
+    }
+
+    /**
+     * 当前响应
+     */
+    public static HttpServletResponse response() {
+        return contextHolder() == null ? null : contextHolder().getResponse();
+    }
+
+    /**
+     * 当前session
+     */
+    public static HttpSession session() {
+        return request() == null ? null : request().getSession();
+    }
+
+    /**
+     * 当前ServletRequest
+     */
+    public static ServletRequestAttributes contextHolder() {
+        return (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+    }
+
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxAppletTools.java b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxAppletTools.java
new file mode 100644
index 0000000..2298a44
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxAppletTools.java
@@ -0,0 +1,123 @@
+package com.ruoyi.system.utils.wx.tools;
+
+
+import com.ruoyi.common.redis.service.RedisService;
+import com.ruoyi.system.utils.wx.body.resp.AccessTokenRespBody;
+import com.ruoyi.system.utils.wx.body.resp.Code2SessionRespBody;
+import com.ruoyi.system.utils.wx.body.resq.Code2SessionResqBody;
+import com.ruoyi.system.utils.wx.model.WeixinProperties;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.util.StringUtils;
+import org.springframework.web.client.RestTemplate;
+
+import java.text.MessageFormat;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author xiaochen
+ * @ClassName WxAppletTools
+ * @Description
+ * @date 2024-8-04 13:55
+ */
+@Slf4j
+public class WxAppletTools {
+    private final static String ACCESSTOKEN_CACHE_KEY = "accessToken";
+    /**
+     * 请求参数
+     * 属性	类型	默认值	必填	说明
+     * appid	string		是	小程序 appId
+     * secret	string		是	小程序 appSecret
+     * js_code	string		是	登录时获取的 code
+     * grant_type	string		是	授权类型,此处只需填写 authorization_cod
+     * <p>
+     * 返回值:
+     * <p>
+     * 属性	类型	说明
+     * openid	string	用户唯一标识
+     * session_key	string	会话密钥
+     * unionid	string	用户在开放平台的唯一标识符,若当前小程序已绑定到微信开放平台帐号下会返回,详见 UnionID 机制说明。
+     * errcode	number	错误码
+     * errmsg	string	错误信息
+     */
+    private static final String JSCODE_2_SESSION_URL = "https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code";
+    /**
+     * 请求参数
+     * 属性	类型	默认值	必填	说明
+     * grant_type	string		是	填写 client_credential
+     * appid	string		是	小程序唯一凭证,即 AppID,可在「微信公众平台 - 设置 - 开发设置」页中获得。(需要已经成为开发者,且帐号没有异常状态)
+     * secret	string		是	小程序唯一凭证密钥,即 AppSecret,获取方式同 appid
+     * 返回值
+     * Object
+     * 返回的 JSON 数据包
+     * <p>
+     * 属性	类型	说明
+     * access_token	string	获取到的凭证
+     * expires_in	number	凭证有效时间,单位:秒。目前是7200秒之内的值。
+     * errcode	number	错误码
+     * errmsg	string	错误信息
+     */
+    public static String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";
+    private WeixinProperties wxConfig;
+    private RestTemplate wxRestTemplate;
+    private RedisService redisService;
+
+    public WxAppletTools(RestTemplate wxRestTemplate, WeixinProperties wxConfig, RedisService redisService) {
+        this.wxRestTemplate = wxRestTemplate;
+        this.wxConfig = wxConfig;
+        this.redisService = redisService;
+    }
+
+    /**
+     * 自定义部分数据
+     *
+     * @param wxConfig
+     * @return
+     */
+    public WxAppletTools build(WeixinProperties wxConfig) {
+        this.wxConfig = wxConfig;
+        return this;
+    }
+
+    /**
+     * @param resqBody
+     * @return
+     */
+    public Code2SessionRespBody getOpenIdByJscode2session(Code2SessionResqBody resqBody) {
+        long start = System.currentTimeMillis();
+        String requestUrl = MessageFormat.format(JSCODE_2_SESSION_URL, wxConfig.getAppId(), wxConfig.getSecretId(), resqBody.getJsCode());
+        long end = System.currentTimeMillis();
+        log.info("code换取sessionKey时间:{}", (end - start));
+        String respBody = wxRestTemplate.getForEntity(requestUrl, String.class).getBody();
+        end = System.currentTimeMillis();
+        log.info("code换取sessionKey时间:{}", (end - start));
+        log.info("Jscode2session:{}", respBody);
+        Code2SessionRespBody code2SessionRespBody = WxJsonUtils.parseObject(respBody, Code2SessionRespBody.class);
+        // 判断有误异常
+        if (StringUtils.hasLength(code2SessionRespBody.getErrorMsg())) {
+            // 抛出错误
+            throw new WxException(code2SessionRespBody.getErrorCode() + ":" + code2SessionRespBody.getErrorMsg());
+        }
+        return code2SessionRespBody;
+    }
+
+    /**
+     * @return
+     */
+    public String getAccessToken(String version) {
+        String accessToken = redisService.getCacheObject(ACCESSTOKEN_CACHE_KEY + version);
+        if (StringUtils.hasLength(accessToken)) {
+            return accessToken;
+        }
+        String requestUrl = MessageFormat.format(ACCESS_TOKEN_URL, wxConfig.getAppId(), wxConfig.getSecretId());
+        String respBody = wxRestTemplate.getForEntity(requestUrl, String.class).getBody();
+        AccessTokenRespBody accessTokenRespBody = WxJsonUtils.parseObject(respBody, AccessTokenRespBody.class);
+        // 判断有误异常
+        if (StringUtils.hasLength(accessTokenRespBody.getErrorMsg())) {
+            // 抛出错误
+            throw new WxException(accessTokenRespBody.getErrorCode() + ":" + accessTokenRespBody.getErrorMsg());
+        }
+        redisService.setCacheObject(ACCESSTOKEN_CACHE_KEY + version, accessTokenRespBody.getAccessToken(), 7200L, TimeUnit.SECONDS);
+        return accessTokenRespBody.getAccessToken();
+    }
+
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxCache.java b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxCache.java
new file mode 100644
index 0000000..fa82920
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxCache.java
@@ -0,0 +1,117 @@
+package com.ruoyi.system.utils.wx.tools;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 缓存
+ *
+ * @author xiaochen
+ */
+class WxCache {
+    /**
+     * 缓存的初始化容量
+     */
+    private int initialCapacity = 50;
+    /**
+     * 缓存最大容量
+     */
+    private long maximumSize = 200L;
+    /**
+     * 缓存时长
+     */
+    private long duration = 7000L;
+    /**
+     * 时长单位,自动转换
+     * 支持:
+     * 时
+     * 分
+     * 秒
+     * 天
+     */
+    private TimeUnit timeunit = TimeUnit.SECONDS;
+
+    public int getInitialCapacity() {
+        return initialCapacity;
+    }
+
+    public void setInitialCapacity(int initialCapacity) {
+        this.initialCapacity = initialCapacity;
+    }
+
+    public long getMaximumSize() {
+        return maximumSize;
+    }
+
+    public void setMaximumSize(long maximumSize) {
+        this.maximumSize = maximumSize;
+    }
+
+
+    public long getDuration() {
+        return duration;
+    }
+
+    public void setDuration(long duration) {
+        this.duration = duration;
+    }
+
+    public TimeUnit getTimeunit() {
+        return timeunit;
+    }
+
+    public void setTimeunit(TimeUnit timeunit) {
+        this.timeunit = timeunit;
+    }
+
+    public static class Builder {
+        private int initialCapacity;
+        private long maximumSize;
+        private long duration;
+        private TimeUnit timeunit;
+
+        public Builder setInitialCapacity(int initialCapacity) {
+            this.initialCapacity = initialCapacity;
+            return this;
+        }
+
+        public Builder setMaximumSize(long maximumSize) {
+            this.maximumSize = maximumSize;
+            return this;
+        }
+
+        public Builder setDuration(long duration) {
+            this.duration = duration;
+            return this;
+        }
+
+        public Builder setTimeUnit(TimeUnit timeunit) {
+            this.timeunit = timeunit;
+            return this;
+        }
+
+        public WxCache build() {
+            return new WxCache(this);
+        }
+    }
+
+    public static Builder options() {
+        return new Builder();
+    }
+
+    private WxCache(Builder builder) {
+        this.initialCapacity = 0 == builder.initialCapacity ? this.initialCapacity : builder.initialCapacity;
+        this.maximumSize = 0L == builder.maximumSize ? this.maximumSize : builder.maximumSize;
+        this.duration = 0L == builder.duration ? this.duration : builder.duration;
+        this.timeunit = null == builder.timeunit ? this.timeunit : builder.timeunit;
+    }
+
+    @Override
+    public String toString() {
+        return "WxCache{" +
+                "initialCapacity=" + initialCapacity +
+                ", maximumSize=" + maximumSize +
+                ", duration=" + duration +
+                ", timeunit=" + timeunit +
+                '}';
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxCacheTemplate.java b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxCacheTemplate.java
new file mode 100644
index 0000000..8640177
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxCacheTemplate.java
@@ -0,0 +1,34 @@
+package com.ruoyi.system.utils.wx.tools;
+
+/**
+ * @author xiaochen
+ * @ClassName WxCacheTemplate
+ * @Description
+ * @date 2021-01-11 11:27
+ */
+public interface WxCacheTemplate<T> {
+    /**
+     * 保存key
+     *
+     * @param key
+     * @param value
+     * @return
+     */
+     boolean setKey(String key, T value);
+
+    /**
+     * 获取缓存
+     *
+     * @param key
+     * @return
+     */
+    T getKey(String key);
+
+    /**
+     * 删除
+     *
+     * @param key
+     * @return
+     */
+    boolean delKey(String key);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxException.java b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxException.java
new file mode 100644
index 0000000..09d46ae
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxException.java
@@ -0,0 +1,55 @@
+package com.ruoyi.system.utils.wx.tools;
+
+/**
+ * @author lihen
+ */
+public class WxException extends RuntimeException {
+
+    private final static int OK = 0;
+    private final static int ValidateSignatureError = -40001;
+    private final static int ParseXmlError = -40002;
+    public final static int ComputeSignatureError = -40003;
+    private final static int IllegalAesKey = -40004;
+    private final static int ValidateAppidError = -40005;
+    private final static int EncryptAESError = -40006;
+    private final static int DecryptAESError = -40007;
+    private final static int IllegalBuffer = -40008;
+
+    private int code;
+
+    private static String getMessage(int code) {
+        switch (code) {
+            case ValidateSignatureError:
+                return "签名验证错误";
+            case ParseXmlError:
+                return "xml解析失败";
+            case ComputeSignatureError:
+                return "sha加密生成签名失败";
+            case IllegalAesKey:
+                return "SymmetricKey非法";
+            case ValidateAppidError:
+                return "appid校验失败";
+            case EncryptAESError:
+                return "aes加密失败";
+            case DecryptAESError:
+                return "aes解密失败";
+            case IllegalBuffer:
+                return "解密后得到的buffer非法";
+            default:
+                return null;
+        }
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    WxException(int code) {
+        super(getMessage(code));
+        this.code = code;
+    }
+
+    public WxException(String message) {
+        super(message);
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxJsonUtils.java b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxJsonUtils.java
new file mode 100644
index 0000000..cc6113e
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxJsonUtils.java
@@ -0,0 +1,109 @@
+package com.ruoyi.system.utils.wx.tools;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.IOException;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Json转换工具类
+ * 参考:https://blog.csdn.net/weixin_38413579/article/details/82562634
+ * @author madman
+ */
+@Slf4j
+public final class WxJsonUtils {
+    public static final String dateFormat = "yyyy-MM-dd";
+    public static final String dateTimeFormat = "yyyy-MM-dd HH:mm:ss";
+    private static final ObjectMapper OM = new ObjectMapper();
+    private static final JavaTimeModule timeModule = new JavaTimeModule();
+
+    /**
+     * 转换LocalDateTime
+     */
+    static class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
+        @Override
+        public void serialize(LocalDateTime localDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
+            jsonGenerator.writeString(localDateTime.format(DateTimeFormatter.ofPattern(dateTimeFormat)));
+        }
+    }
+
+    /**
+     * 转换LocalDate
+     */
+    static class LocalDateSerializer extends JsonSerializer<LocalDate> {
+        @Override
+        public void serialize(LocalDate localDate, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
+            jsonGenerator.writeString(localDate.format(DateTimeFormatter.ofPattern(dateFormat)));
+        }
+    }
+
+    /**
+     * 设置 ObjectMapper
+     *
+     * @return
+     */
+    private static ObjectMapper getObjectMapper() {
+        // 序列化
+        timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
+        timeModule.addSerializer(LocalDate.class, new LocalDateSerializer());
+        // 反序列化
+        timeModule.addDeserializer(LocalDateTime.class,
+                new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(dateTimeFormat)));
+        timeModule.addDeserializer(LocalDate.class,
+                new LocalDateDeserializer(DateTimeFormatter.ofPattern(dateFormat)));
+        // 允许对象忽略json中不存在的属性
+        OM.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+        OM.registerModule(timeModule);
+        return OM;
+    }
+
+    /**
+     * 将对象序列化
+     */
+    public static <T> String toJsonString(T obj) {
+        try {
+            ObjectMapper om = getObjectMapper();
+            return om.writeValueAsString(obj);
+        } catch (JsonProcessingException e) {
+            log.error("转json字符串失败:{}", obj);
+            return null;
+        }
+    }
+
+    /**
+     * 反序列化对象字符串
+     */
+    public static <T> T parseObject(String json, Class<T> clazz) {
+        try {
+            ObjectMapper om = getObjectMapper();
+            return om.readValue(json, clazz);
+        } catch (JsonProcessingException e) {
+            throw new RuntimeException("反序列化对象字符串失败");
+        }
+    }
+
+    /**
+     * 反序列化字符串成为对象
+     */
+    public static <T> T parseObject(String json, TypeReference<T> valueTypeRef) {
+        try {
+            ObjectMapper om = getObjectMapper();
+            return om.readValue(json, valueTypeRef);
+        } catch (JsonProcessingException e) {
+            throw new RuntimeException("反序列化字符串成为对象失败");
+        }
+    }
+
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxUtils.java b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxUtils.java
new file mode 100644
index 0000000..6287358
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxUtils.java
@@ -0,0 +1,175 @@
+package com.ruoyi.system.utils.wx.tools;
+
+import com.ruoyi.system.utils.wx.pojo.AppletUserDecodeData;
+import com.ruoyi.common.utils.sign.Base64;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.CharEncoding;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import javax.servlet.http.HttpServletRequest;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.security.AlgorithmParameters;
+import java.security.Security;
+import java.util.Arrays;
+
+/**
+ * @Description 获取用户信息工具类
+ * @Author xiaochen
+ * @Date 2021/8/12 15:45
+ */
+@Slf4j
+public class WxUtils {
+
+    /**
+     * 微信小程序API 用户数据的解密
+     *
+     * @param encryptedData
+     * @param sessionKey
+     * @param iv
+     * @return
+     */
+    public static AppletUserDecodeData encryptedData(String encryptedData, String sessionKey, String iv) {
+        // 被加密的数据
+        byte[] dataByte = Base64.decode(encryptedData);
+        // 加密秘钥
+        byte[] keyByte = Base64.decode(sessionKey);
+        // 偏移量
+        byte[] ivByte = Base64.decode(iv);
+        try {
+            // 如果密钥不足16位,那么就补足.  这个if 中的内容很重要
+            int base = 16;
+            if (keyByte.length % base != 0) {
+                int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
+                byte[] temp = new byte[groups * base];
+                Arrays.fill(temp, (byte) 0);
+                System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
+                keyByte = temp;
+            }
+            // 初始化
+            Security.addProvider(new BouncyCastleProvider());
+            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
+            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
+            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
+            parameters.init(new IvParameterSpec(ivByte));
+            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);
+            byte[] resultByte = cipher.doFinal(dataByte);
+            if (null != resultByte && resultByte.length > 0) {
+                String result = new String(resultByte, CharEncoding.UTF_8);
+                log.info("解密原串:{}", result);
+                return WxJsonUtils.parseObject(result, AppletUserDecodeData.class);
+            }
+            throw new RuntimeException("解密的数据为空");
+        } catch (Exception e) {
+            log.error("解密失败. error = {}", e.getMessage(), e);
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
+    /**
+     * 微信小程序API 用户数据的签名验证
+     * signature = sha1( rawData + session_key )
+     *
+     * @param rawData    不包括敏感信息的原始数据字符串,用于计算签名。
+     * @param sessionKey
+     */
+    public static void verifySignature(String rawData, String sessionKey, String signature) {
+        String serverSignature = SHA1.getSHA1(rawData + sessionKey);
+        log.info(rawData + ">>>>>>:" + sessionKey + " === " + serverSignature + "  ======" + signature);
+        if (!signature.equals(serverSignature)) {
+            throw new RuntimeException("数据验签不通过");
+        }
+    }
+
+    /**
+     * 根据流接收请求数据
+     *
+     * @param request
+     * @return
+     */
+    public static String streamBodyByReceive(HttpServletRequest request) throws IOException {
+        log.info("微信异步回调地址:{}", request.getRequestURL());
+        StringBuffer buffer = new StringBuffer();
+        InputStream inputStream = request.getInputStream();
+        InputStreamReader reader = new InputStreamReader(inputStream);
+        BufferedReader bufferedReader = new BufferedReader(reader);
+        String body = null;
+        while ((body = bufferedReader.readLine()) != null) {
+            buffer.append(body);
+        }
+        String data = buffer.toString();
+        reader.close();
+        inputStream.close();
+        log.info("微信异步回调数据:{}", data);
+        return data;
+    }
+
+    /**
+     * 日志
+     *
+     * @return
+     */
+    public static Logger getLogger() {
+        Logger logger = LoggerFactory.getLogger("wxpay java sdk");
+        return logger;
+    }
+
+    /**
+     * debug
+     *
+     * @param msg
+     * @param args
+     */
+    public static void debug(String msg, Object... args) {
+        Logger log = getLogger();
+        if (log.isDebugEnabled()) {
+            log.debug(msg, args);
+        }
+    }
+
+    /**
+     * info
+     *
+     * @param msg
+     * @param args
+     */
+    public static void info(String msg, Object... args) {
+        Logger log = getLogger();
+        if (log.isInfoEnabled()) {
+            log.info(msg, args);
+        }
+    }
+
+    /**
+     * warn
+     *
+     * @param msg
+     * @param args
+     */
+    public static void warn(String msg, Object... args) {
+        Logger log = getLogger();
+        if (log.isWarnEnabled()) {
+            log.warn(msg, args);
+        }
+    }
+
+    /**
+     * error
+     *
+     * @param msg
+     * @param args
+     */
+    public static void error(String msg, Object... args) {
+        Logger log = getLogger();
+        if (log.isErrorEnabled()) {
+            log.error(msg, args);
+        }
+    }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/vo/FaultConcatInfoVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/vo/FaultConcatInfoVO.java
new file mode 100644
index 0000000..8974d8c
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/vo/FaultConcatInfoVO.java
@@ -0,0 +1,17 @@
+package com.ruoyi.system.vo;
+
+import com.ruoyi.system.model.TContract;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+@ApiModel(value = "报修房源信息VO")
+public class FaultConcatInfoVO extends TContract {
+
+    @ApiModelProperty(value = "房屋名称")
+    private String houseName;
+
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysUserVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysUserVO.java
index 15cf0d2..09a4e0d 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysUserVO.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysUserVO.java
@@ -5,6 +5,8 @@
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
+import java.util.List;
+
 @Data
 @ApiModel(value = "账户列表VO")
 public class SysUserVO extends SysUser {
@@ -14,7 +16,7 @@
     @ApiModelProperty(value = "单位名称")
     private String companyName;
     @ApiModelProperty(value = "部门")
-    private String deptName;
+    private List<String> deptList;
     @ApiModelProperty(value = "角色")
     private String roleName;
 
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/vo/TBillVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/vo/TBillVO.java
index 6b4bbbe..604ff8b 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/vo/TBillVO.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/vo/TBillVO.java
@@ -1,6 +1,7 @@
 package com.ruoyi.system.vo;
 
 import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.system.model.TBill;
 import com.ruoyi.system.model.TBillDetail;
 import com.ruoyi.system.model.THouse;
@@ -9,6 +10,7 @@
 import lombok.Data;
 
 import java.math.BigDecimal;
+import java.time.LocalDateTime;
 import java.util.List;
 
 @Data
@@ -26,4 +28,18 @@
 
     @ApiModelProperty(value = "租金支付方式 月付 季付 年付")
     private String payType;
+
+    @ApiModelProperty(value = "押金")
+    private BigDecimal deposit;
+    @ApiModelProperty(value = "甲方联系人")
+    private String partyOnePerson;
+
+    @ApiModelProperty(value = "甲方联系方式")
+    private String partyOnePhone;
+    @ApiModelProperty(value = "合同开始时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime concatStartTime;
+    @ApiModelProperty(value = "合同结束时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime concatEndTime;
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/vo/TCheckAcceptRecordVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/vo/TCheckAcceptRecordVO.java
new file mode 100644
index 0000000..23de55e
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/vo/TCheckAcceptRecordVO.java
@@ -0,0 +1,20 @@
+package com.ruoyi.system.vo;
+
+import com.ruoyi.system.model.TCheckAcceptRecord;
+import com.ruoyi.system.model.TContract;
+import com.ruoyi.system.model.THouse;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+@ApiModel(value = "验收记录VO")
+public class TCheckAcceptRecordVO extends TCheckAcceptRecord {
+
+    @ApiModelProperty(value = "合同信息")
+    private TContract contract;
+
+    @ApiModelProperty(value = "房屋信息")
+    private THouse house;
+
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/vo/TFaultAreaDicVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/vo/TFaultAreaDicVO.java
new file mode 100644
index 0000000..9c3da5d
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/vo/TFaultAreaDicVO.java
@@ -0,0 +1,18 @@
+package com.ruoyi.system.vo;
+
+import com.ruoyi.system.model.TFaultAreaDic;
+import com.ruoyi.system.model.TFaultDescribeDic;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+@ApiModel(value = "故障区域vo")
+public class TFaultAreaDicVO extends TFaultAreaDic {
+
+    @ApiModelProperty(value = "故障描述")
+    private List<TFaultDescribeDic> faultDescribeDicList;
+
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/vo/TFaultRepairMessageVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/vo/TFaultRepairMessageVO.java
new file mode 100644
index 0000000..47c0123
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/vo/TFaultRepairMessageVO.java
@@ -0,0 +1,22 @@
+package com.ruoyi.system.vo;
+
+import com.ruoyi.system.model.TFaultRepairMessage;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+@ApiModel(value = "报修VO")
+public class TFaultRepairMessageVO extends TFaultRepairMessage {
+
+    @ApiModelProperty(value = "物品名称")
+    private String itemName;
+
+    @ApiModelProperty(value = "物品分类名称")
+    private String itemTypeName;
+
+    @ApiModelProperty(value = "用户名称")
+    private String residentName;
+
+
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/vo/TItemTypeVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/vo/TItemTypeVO.java
new file mode 100644
index 0000000..9c13408
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/vo/TItemTypeVO.java
@@ -0,0 +1,18 @@
+package com.ruoyi.system.vo;
+
+import com.ruoyi.system.model.TItem;
+import com.ruoyi.system.model.TItemType;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+@ApiModel(value = "物品类型VO")
+public class TItemTypeVO extends TItemType {
+
+    @ApiModelProperty(value = "维修物品集合")
+    private List<TItem> itemList;
+
+}
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml
index faaee57..cc568e7 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml
@@ -92,21 +92,6 @@
 			   sol.oper_time AS operTime, sol.cost_time AS costTime,sol.companyName AS companyName,sol.roleName AS roleName,sol.phonenumber AS phonenumber,
 			   sol.userId AS userId,sol.nickName AS nickName
 		from sys_oper_log sol
-		<where>
-			<if test="query.companyName != null and query.companyName != ''">
-				AND sol.companyName LIKE concat('%',#{query.companyName},'%')
-			</if>
-			<if test="query.roleName != null and query.roleName != ''">
-				AND sol.roleName LIKE concat('%',#{query.roleName},'%')
-			</if>
-			<if test="query.nickName != null and query.nickName != ''">
-				AND sol.nickName LIKE concat('%',#{query.nickName},'%')
-			</if>
-			<if test="query.startTime != null and query.startTime != '' and query.endTime != null and query.endTime != ''">
-				AND DATE_FORMAT(sol.oper_time, '%Y-%m-%d %H:%i:%s') &gt;= #{query.startTime}
-				AND DATE_FORMAT(sol.oper_time, '%Y-%m-%d %H:%i:%s') &lt;= #{query.endTime}
-			</if>
-		</where>
 		ORDER BY sol.oper_time DESC
 	</select>
 
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
index 7336905..7487409 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
@@ -228,19 +228,24 @@
 		from sys_user u
 		left join sys_user_role ur on u.user_id = ur.user_id
 		left join sys_role r on r.role_id = ur.role_id
+		left join t_dept_to_user tdtu on u.user_id = tdtu.user_id
 		WHERE u.del_flag = 0
-		<if test="query.nickName != null and query.nickName != ''">
-			AND u.nick_name LIKE concat('%',#{query.nickName},'%')
+		<if test="query.nickNameAndPhone != null and query.nickNameAndPhone != ''">
+			AND (u.nick_name LIKE concat('%',#{query.nickNameAndPhone},'%')
+			    OR u.phonenumber LIKE concat('%',#{query.nickNameAndPhone},'%'))
 		</if>
 		<if test="query.roleId != null">
 			AND r.role_id = #{query.roleId}
 		</if>
-		<if test="query.phonenumber != null and query.phonenumber != ''">
-			AND u.phonenumber LIKE concat('%',#{query.phonenumber},'%')
-		</if>
 		<if test="query.status != null and query.status != ''">
 			AND u.status = #{query.status}
 		</if>
+		<if test="query.deptIds != null and query.deptIds.size()>0">
+			AND u.user_id IN (select DISTINCT user_id from t_dept_to_user where dept_id IN
+			<foreach collection="query.deptIds" close=")" open="(" item="deptId" separator=",">
+				#{deptId}
+			</foreach>)
+		</if>
 		ORDER BY u.create_time DESC
 	</select>
 	<select id="selectIdByPhone" resultType="java.lang.Long">
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml
index f7715e4..9b0d3cd 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml
@@ -33,6 +33,12 @@
     <insert id="insertUserRole">
 		insert into sys_user_role(user_id, role_id) values (#{userRole.userId},#{userRole.roleId})
 	</insert>
+    <insert id="insertBatchUserDept">
+		insert into sys_user_role(user_id, dept_id) values
+		<foreach item="item" index="index" collection="deptToUserList" separator=",">
+			(#{item.userId},#{item.deptId})
+		</foreach>
+	</insert>
 
     <delete id="deleteUserRoleInfo" parameterType="SysUserRole">
 		delete from sys_user_role where user_id=#{userId} and role_id=#{roleId}
diff --git a/ruoyi-system/src/main/resources/mapper/system/TCheckAcceptRecordMapper.xml b/ruoyi-system/src/main/resources/mapper/system/TCheckAcceptRecordMapper.xml
index 150e9c2..2e99a8c 100644
--- a/ruoyi-system/src/main/resources/mapper/system/TCheckAcceptRecordMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/TCheckAcceptRecordMapper.xml
@@ -28,7 +28,53 @@
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, contract_id, house_id, check_time, lease_reason, check_person, accompany_person, overall_situation, furniture_situation, device_situation, clean_situation, other_problem, pictures, check_result, check_money, create_time, update_time, create_by, update_by, disabled
+        id, contract_id, house_id, check_time, lease_reason, check_person, accompany_person, overall_situation, furniture_situation, device_situation, clean_situation,
+            other_problem, pictures, check_result, check_money, create_time, update_time, create_by, update_by, disabled
     </sql>
+    <select id="pageList" resultType="com.ruoyi.system.vo.TCheckAcceptRecordVO">
+        select
+        t.id,
+        t.contract_id,
+        t.house_id,
+        t.check_time,
+        t.lease_reason,
+        t.check_person,
+        t.accompany_person,
+        t.overall_situation,
+        t.furniture_situation,
+        t.device_situation,
+        t.clean_situation,
+        t.other_problem,
+        t.pictures,
+        t.check_result,
+        t.check_money,
+        t.create_time,
+        t.update_time,
+        t.create_by,
+        t.update_by,
+        t.disabled,
+        c.contract_number,
+        h.house_name
+        from t_check_accept_record t
+        left join t_contract c on t.contract_id = c.id
+        left join t_house h on t.house_id = h.id
+        <where>
+            <if test="query.contractNumber != null and query.contractNumber != ''">
+                AND c.contract_number LIKE concat('%', #{query.contractNumber}, '%')
+            </if>
+            <if test="query.checkResult != null">
+                AND t.check_result = #{query.checkResult}
+            </if>
+            <if test="query.houseName != null and query.houseName != ''">
+                AND h.house_name LIKE concat('%', #{query.houseName}, '%')
+            </if>
+            <if test="query.startTime != null and query.startTime != '' and query.endTime != null and query.endTime != ''">
+                AND t.check_time &gt;= #{query.startTime}
+                AND t.check_time &lt;= #{query.endTime}
+            </if>
+            AND t.disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()}
+        </where>
+        ORDER BY t.create_time DESC
+    </select>
 
 </mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/TContractMapper.xml b/ruoyi-system/src/main/resources/mapper/system/TContractMapper.xml
index 9728d27..eb9f2e8 100644
--- a/ruoyi-system/src/main/resources/mapper/system/TContractMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/TContractMapper.xml
@@ -80,7 +80,7 @@
         select t1.*,t2.contract_number as contractNumber,t3.resident_name as residentName,t3.phone as phone
         from t_bill t1
         left join t_contract t2 on t1.contract_id = t2.id
-        left join t_resident t3 on t2.tenant_id = t3.id
+        left join t_tenant t3 on t2.tenant_id = t3.id
         where t2.id = #{query.id}
         and (t1.pay_fees_status = 1 or t1.pay_fees_status = 4)
         AND t1.disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()}
diff --git a/ruoyi-system/src/main/resources/mapper/system/TDeptToUserMapper.xml b/ruoyi-system/src/main/resources/mapper/system/TDeptToUserMapper.xml
index 8e20f23..a740cf8 100644
--- a/ruoyi-system/src/main/resources/mapper/system/TDeptToUserMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/TDeptToUserMapper.xml
@@ -13,5 +13,8 @@
     <sql id="Base_Column_List">
         id, dept_id, user_id
     </sql>
+    <delete id="deleteUserDeptByUserId">
+        delete from t_dept_to_user where user_id=#{userId}
+    </delete>
 
 </mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/TFaultAreaDicMapper.xml b/ruoyi-system/src/main/resources/mapper/system/TFaultAreaDicMapper.xml
index cb2bf60..d3d53ba 100644
--- a/ruoyi-system/src/main/resources/mapper/system/TFaultAreaDicMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/TFaultAreaDicMapper.xml
@@ -24,5 +24,11 @@
         WHERE disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()}
         ORDER BY sort_by,create_time DESC
     </select>
+    <select id="getAreaDicList" resultType="com.ruoyi.system.vo.TFaultAreaDicVO">
+        SELECT <include refid="Base_Column_List"></include>
+        FROM t_fault_area_dic
+        WHERE disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()}
+        ORDER BY sort_by,create_time DESC
+    </select>
 
 </mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/TFaultRepairMessageMapper.xml b/ruoyi-system/src/main/resources/mapper/system/TFaultRepairMessageMapper.xml
index 99bc9d9..56ca1b4 100644
--- a/ruoyi-system/src/main/resources/mapper/system/TFaultRepairMessageMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/TFaultRepairMessageMapper.xml
@@ -5,8 +5,10 @@
     <!-- 通用查询映射结果 -->
     <resultMap id="BaseResultMap" type="com.ruoyi.system.model.TFaultRepairMessage">
         <id column="id" property="id" />
-        <result column="app_user_id" property="appUserId" />
+        <result column="tenant_id" property="tenantId" />
         <result column="item_id" property="itemId" />
+        <result column="item_type_id" property="itemTypeId" />
+        <result column="contract_id" property="contractId" />
         <result column="fault_area_name" property="faultAreaName" />
         <result column="describe_name" property="describeName" />
         <result column="describe_detail" property="describeDetail" />
@@ -18,9 +20,10 @@
         <result column="leave_message" property="leaveMessage" />
         <result column="handle_person" property="handlePerson" />
         <result column="handle_time" property="handleTime" />
-        <result column="reault_describe" property="reaultDescribe" />
+        <result column="result_describe" property="resultDescribe" />
         <result column="repair_picture" property="repairPicture" />
         <result column="attachment" property="attachment" />
+        <result column="attachment_name" property="attachmentName" />
         <result column="status" property="status" />
         <result column="create_time" property="createTime" />
         <result column="update_time" property="updateTime" />
@@ -31,7 +34,101 @@
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, app_user_id, item_id, fault_area_name, describe_name, describe_detail, fault_pictures, service_address, repair_type, visit_time, contact_number, leave_message, handle_person, handle_time, reault_describe, repair_picture, attachment, status, create_time, update_time, create_by, update_by, disabled
+        id, tenant_id, item_id,item_type_id,contract_id, fault_area_name, describe_name, describe_detail, fault_pictures, service_address, repair_type,
+            visit_time, contact_number, leave_message, handle_person, handle_time, result_describe, repair_picture, attachment,attachment_name, status,
+            create_time,update_time, create_by, update_by, disabled
     </sql>
+    <select id="getDetailById" resultType="com.ruoyi.system.vo.TFaultRepairMessageVO">
+        SELECT
+        t.id,
+        t.tenant_id,
+        t.item_id,
+        t.item_type_id,
+        t.contract_id,
+        t.fault_area_name,
+        t.describe_name,
+        t.describe_detail,
+        t.fault_pictures,
+        t.service_address,
+        t.repair_type,
+        t.visit_time,
+        t.contact_number,
+        t.leave_message,
+        t.handle_person,
+        t.handle_time,
+        t.result_describe,
+        t.repair_picture,
+        t.attachment,
+        t.attachment_name,
+        t.status,
+        t.create_time,
+        t.update_time,
+        t.create_by,
+        t.update_by,
+        t.disabled,
+        i.item_name AS itemName,
+        it.type_name AS itemTypeName,
+        tnt.resident_name AS residentName
+        from t_fault_repair_message t
+        LEFT JOIN t_item i ON t.item_id = i.id
+        LEFT JOIN t_item_type it ON t.item_type_id = it.id
+        LEFT JOIN t_tenant tnt ON t.tenant_id = tnt.id
+        WHERE t.id = #{id}
+    </select>
+    <select id="pageList" resultType="com.ruoyi.system.vo.TFaultRepairMessageVO">
+        SELECT
+            t.id,
+            t.tenant_id,
+            t.item_id,
+            t.item_type_id,
+            t.contract_id,
+            t.fault_area_name,
+            t.describe_name,
+            t.describe_detail,
+            t.fault_pictures,
+            t.service_address,
+            t.repair_type,
+            t.visit_time,
+            t.contact_number,
+            t.leave_message,
+            t.handle_person,
+            t.handle_time,
+            t.result_describe,
+            t.repair_picture,
+            t.attachment,
+            t.attachment_name,
+            t.status,
+            t.create_time,
+            t.update_time,
+            t.create_by,
+            t.update_by,
+            t.disabled,
+            i.item_name AS itemName,
+            it.type_name AS itemTypeName,
+            tnt.resident_name AS residentName
+        from t_fault_repair_message t
+                 LEFT JOIN t_item i ON t.item_id = i.id
+                 LEFT JOIN t_item_type it ON t.item_type_id = it.id
+                 LEFT JOIN t_tenant tnt ON t.tenant_id = tnt.id
+        <where>
+            <if test="query.tenantId != null and query.tenantId != ''">
+                AND t.tenant_id = #{query.tenantId}
+            </if>
+            <if test="query.contactNumber != null and query.contactNumber != ''">
+                AND t.contact_number LIKE CONCAT('%', #{query.contactNumber}, '%')
+            </if>
+            <if test="query.status != null">
+                AND t.status = #{query.status}
+            </if>
+            <if test="query.repairType != null">
+                AND t.repair_type = #{query.repairType}
+            </if>
+            <if test="query.handlePerson != null and query.handlePerson != ''">
+                AND t.handle_person LIKE CONCAT('%', #{query.handlePerson}, '%')
+            </if>
+            AND t.disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()}
+        </where>
+        ORDER BY t.create_time DESC
+    </select>
 
 </mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/TItemMapper.xml b/ruoyi-system/src/main/resources/mapper/system/TItemMapper.xml
index 84d057e..7a03ea8 100644
--- a/ruoyi-system/src/main/resources/mapper/system/TItemMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/TItemMapper.xml
@@ -22,7 +22,7 @@
     </sql>
     <select id="pageList" resultType="com.ruoyi.system.vo.TItemVO">
         select
-        t.id, t.type_id, t.item_name, t.sort_by, t.pictures, t.create_time, t.update_time, t.create_by, t.update_by, t.disabled
+        t.id, t.type_id, t.item_name, t.sort_by, t.pictures, t.create_time, t.update_time, t.create_by, t.update_by, t.disabled,
         tt.type_name
         from t_item t
         left join t_item_type tt on t.type_id = tt.id
diff --git a/ruoyi-system/src/main/resources/mapper/system/TItemTypeMapper.xml b/ruoyi-system/src/main/resources/mapper/system/TItemTypeMapper.xml
index 51d9e9a..4f0c44e 100644
--- a/ruoyi-system/src/main/resources/mapper/system/TItemTypeMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/TItemTypeMapper.xml
@@ -25,5 +25,12 @@
         where disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()}
         ORDER BY sort_by,create_time DESC
     </select>
+    <select id="getItemList" resultType="com.ruoyi.system.vo.TItemTypeVO">
+        select
+        <include refid="Base_Column_List"/>
+        from t_item_type
+        where disabled = ${@com.ruoyi.common.enums.DisabledEnum@NO.getCode()}
+        ORDER BY sort_by,create_time DESC
+    </select>
 
 </mapper>

--
Gitblit v1.7.1