diff --git a/ludu-module-hiking/ludu-module-hiking-api/pom.xml b/ludu-module-hiking/ludu-module-hiking-api/pom.xml
new file mode 100644
index 000000000..6de143abf
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-api/pom.xml
@@ -0,0 +1,54 @@
+
+
+
+ ludu-module-hiking
+ cn.iocoder.cloud
+ 2.1.0-jdk8-snapshot
+
+ 4.0.0
+ ludu-module-hiking-api
+ jar
+
+ ${project.artifactId}
+
+ demo 模块 API,暴露给其它模块调用
+
+
+
+
+ cn.iocoder.cloud
+ yudao-common
+
+
+
+
+ cn.iocoder.cloud
+ yudao-common
+
+
+
+
+ org.springdoc
+ springdoc-openapi-ui
+ provided
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+ true
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+ true
+
+
+
+
+
diff --git a/ludu-module-hiking/ludu-module-hiking-api/src/main/java/cn/iocoder/yudao/module/hiking/api/camera/CameraApi.java b/ludu-module-hiking/ludu-module-hiking-api/src/main/java/cn/iocoder/yudao/module/hiking/api/camera/CameraApi.java
new file mode 100644
index 000000000..7cf1637a4
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-api/src/main/java/cn/iocoder/yudao/module/hiking/api/camera/CameraApi.java
@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.hiking.api.camera;
+
+import cn.hutool.db.Page;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.hiking.api.camera.dto.CameraDTO;
+import cn.iocoder.yudao.module.hiking.enums.ApiConstants;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.List;
+import java.util.Map;
+
+@FeignClient(name = ApiConstants.NAME)
+@Tag(name = "监控点信息")
+public interface CameraApi {
+ String PREFIX = ApiConstants.PREFIX + "/camera";
+ @GetMapping(PREFIX + "/selectCameraByPageAndCondition")
+ @Operation(summary = "分页条件查询监控点信息")
+ public CommonResult> selectCameraByPageAndCondition(@RequestParam String name);
+
+ @GetMapping(PREFIX + "/selectPreviewUrlByCameraIndexCode")
+ @Operation(summary = "获取监控点预览流URL")
+ public CommonResult selectPreviewUrlByCameraIndexCode(@RequestParam String cameraIndexCode);
+
+ @GetMapping(PREFIX + "/selectPlayBackUrlByCameraIndexCode")
+ @Operation(summary = "获取监控点回放流URL")
+ public CommonResult selectPlayBackUrlByCameraIndexCode(@RequestParam String cameraIndexCode, String beginTime,String endTime);
+}
diff --git a/ludu-module-hiking/ludu-module-hiking-api/src/main/java/cn/iocoder/yudao/module/hiking/api/camera/dto/CameraDTO.java b/ludu-module-hiking/ludu-module-hiking-api/src/main/java/cn/iocoder/yudao/module/hiking/api/camera/dto/CameraDTO.java
new file mode 100644
index 000000000..4d06d85e1
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-api/src/main/java/cn/iocoder/yudao/module/hiking/api/camera/dto/CameraDTO.java
@@ -0,0 +1,26 @@
+package cn.iocoder.yudao.module.hiking.api.camera.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "监控点 Response DTO")
+@Data
+public class CameraDTO {
+ @Schema(description = "监控点ID")
+ private Long id;
+
+ @Schema(description = "监控点唯一编码")
+ private String cameraIndexCode;
+
+ @Schema(description = "监控点名称")
+ private String cameraName;
+
+ @Schema(description = "监控点类型")
+ private Integer camera_type;
+
+// @Schema(description = "预览URL")
+// private String previewUrl;
+//
+// @Schema(description = "回放URL")
+// private String playBackUrl;
+}
diff --git a/ludu-module-hiking/ludu-module-hiking-api/src/main/java/cn/iocoder/yudao/module/hiking/enums/ApiConstants.java b/ludu-module-hiking/ludu-module-hiking-api/src/main/java/cn/iocoder/yudao/module/hiking/enums/ApiConstants.java
new file mode 100644
index 000000000..f3c46c5c0
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-api/src/main/java/cn/iocoder/yudao/module/hiking/enums/ApiConstants.java
@@ -0,0 +1,23 @@
+package cn.iocoder.yudao.module.hiking.enums;
+
+import cn.iocoder.yudao.framework.common.enums.RpcConstants;
+
+/**
+ * API 相关的枚举
+ *
+ * @author 芋道源码
+ */
+public class ApiConstants {
+
+ /**
+ * 服务名
+ *
+ * 注意,需要保证和 spring.application.name 保持一致
+ */
+ public static final String NAME = "hiking-server";
+
+ public static final String PREFIX = RpcConstants.RPC_API_PREFIX + "/hiking";
+
+ public static final String VERSION = "1.0.0";
+
+}
diff --git a/ludu-module-hiking/ludu-module-hiking-api/src/main/java/cn/iocoder/yudao/module/hiking/enums/ErrorCodeConstants.java b/ludu-module-hiking/ludu-module-hiking-api/src/main/java/cn/iocoder/yudao/module/hiking/enums/ErrorCodeConstants.java
new file mode 100644
index 000000000..8e65c771b
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-api/src/main/java/cn/iocoder/yudao/module/hiking/enums/ErrorCodeConstants.java
@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.hiking.enums;
+
+import cn.iocoder.yudao.framework.common.exception.ErrorCode;
+
+/**
+ * @Description TODO
+ */
+public interface ErrorCodeConstants {
+ // ========== 进出记录图片 1_005_001_015 ==========
+ ErrorCode ACCESS_RECORD_PICTURE_NOT_EXISTS = new ErrorCode(1_005_001_015, "进出记录图片不存在");
+ // ========== 心跳管理 1_005_001_025 ==========
+ ErrorCode HEARTBEAT_NOT_EXISTS = new ErrorCode(1_005_001_025, "心跳管理不存在");
+ // ========== 通道信息 1_005_001_026 ==========
+ ErrorCode PASSAGEWAY_NOT_EXISTS = new ErrorCode(1_005_001_026, "通道信息不存在");
+ // ========== 场库列表 1_005_001_027 ==========
+ ErrorCode PARK_NOT_EXISTS = new ErrorCode(1_005_001_027, "场库列表不存在");
+ // ========== 区域列表 1_005_001_028 ==========
+ ErrorCode AREA_NOT_EXISTS = new ErrorCode(1_005_001_028, "区域列表不存在");
+ ErrorCode VEHICLE_RENEWAL_RECORD_NOT_EXISTS = new ErrorCode(22222, "固定车续费记录不存在");
+ ErrorCode WARNING_NOT_EXISTS = new ErrorCode(33333, "告警记录不存在");
+ ErrorCode WHITE_NOT_EXISTS = new ErrorCode(444444, "白名单管理不存在");
+ ErrorCode BLACK_NOT_EXISTS = new ErrorCode(55555, "黑名单管理不存在");
+ // ========== 收费信息 1_005_001_029 ==========
+ ErrorCode CHARGE_INFO_NOT_EXISTS = new ErrorCode(1_005_001_029, "收费信息不存在");
+ // ========== 远程抬杠日志 1_005_001_030 ==========
+ ErrorCode LIFTING_ROD_NOT_EXISTS = new ErrorCode(1_005_001_030, "远程抬杠日志不存在");
+ // ========== 预约车 1_005_001_031 ==========
+ ErrorCode BOOK_CAR_NOT_EXISTS = new ErrorCode(1_005_001_031, "预约车不存在");
+ ErrorCode ENTRY_RECORD_NOT_EXISTS = new ErrorCode(666666, "入场记录不存在");
+ ErrorCode APPEARANCE_RECORD_NOT_EXISTS = new ErrorCode(77777, "出场记录不存在");
+ ErrorCode CAMERA_NOT_EXISTS = new ErrorCode(88888, "监控不存在");
+ ErrorCode REGION_NOT_EXISTS = new ErrorCode(99999, "区域不存在");
+}
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/pom.xml b/ludu-module-hiking/ludu-module-hiking-biz/pom.xml
new file mode 100644
index 000000000..e04c33962
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/pom.xml
@@ -0,0 +1,176 @@
+
+ 4.0.0
+
+ ludu-module-hiking
+ cn.iocoder.cloud
+ 2.1.0-jdk8-snapshot
+
+
+ ludu-module-hiking-biz
+
+ ${project.artifactId}
+
+
+
+ UTF-8
+
+
+
+
+ cn.iocoder.cloud
+ ludu-module-hiking-api
+ ${revision}
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-bootstrap
+
+
+
+ cn.iocoder.cloud
+ yudao-spring-boot-starter-env
+
+
+
+
+ cn.iocoder.cloud
+ yudao-module-system-api
+ ${revision}
+
+
+ cn.iocoder.cloud
+ yudao-module-infra-api
+ ${revision}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ cn.iocoder.cloud
+ yudao-spring-boot-starter-biz-data-permission
+
+
+ cn.iocoder.cloud
+ yudao-spring-boot-starter-biz-tenant
+
+
+
+
+
+
+
+
+ cn.iocoder.cloud
+ yudao-spring-boot-starter-web
+
+
+
+ cn.iocoder.cloud
+ yudao-spring-boot-starter-security
+
+
+
+
+ cn.iocoder.cloud
+ yudao-spring-boot-starter-mybatis
+
+
+
+ cn.iocoder.cloud
+ yudao-spring-boot-starter-redis
+
+
+
+
+ cn.iocoder.cloud
+ yudao-spring-boot-starter-rpc
+
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-discovery
+
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-config
+
+
+
+
+ cn.iocoder.cloud
+ yudao-spring-boot-starter-job
+
+
+
+
+ cn.iocoder.cloud
+ yudao-spring-boot-starter-mq
+
+
+
+
+ cn.iocoder.cloud
+ yudao-spring-boot-starter-test
+
+
+
+
+ cn.iocoder.cloud
+ yudao-spring-boot-starter-excel
+
+
+
+
+ cn.iocoder.cloud
+ yudao-spring-boot-starter-monitor
+
+
+
+ com.hikvision.ga
+ artemis-http-client
+ 1.1.3
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+
+
+ org.bytedeco
+ javacv
+ 1.5.9
+
+
+
+
+
+
+
+
+ maven-site-plugin
+
+ en,fr
+
+
+
+
+
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/GetRegionInfoUtil.java b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/GetRegionInfoUtil.java
new file mode 100644
index 000000000..42bd762a3
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/GetRegionInfoUtil.java
@@ -0,0 +1,228 @@
+package cn.iocoder.yudao.module.hiking;
+
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.hiking.controller.admin.region.vo.RegionSaveReqVO;
+import cn.iocoder.yudao.module.hiking.dal.dataobject.region.RegionDO;
+import cn.iocoder.yudao.module.hiking.service.region.RegionService;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+
+@RestController
+public class GetRegionInfoUtil {
+ @Autowired
+ private RedisTemplate redisTemplate;
+ @Resource
+ private RegionService regionService;
+ private static final String ACCESS_TOKEN_KEY = "hikingAPI:access_token";
+
+
+ public String getAccessToken() {
+ // 检查 Redis 中是否有 access_token
+ String accessToken = redisTemplate.opsForValue().get(ACCESS_TOKEN_KEY);
+ if (!StringUtils.isEmpty(accessToken)) {
+ System.out.println("使用缓存的token:" + accessToken);
+ return accessToken; // 如果存在则直接返回
+ }
+
+ // 如果没有,调用 API 获取并存入 Redis
+ System.out.println("获取新的token");
+ String accessTokenUrlResp = IntegrationURL.getAccessTokenURL();
+ try {
+ ObjectMapper objectMapper = new ObjectMapper();
+ JsonNode jsonNode = objectMapper.readTree(accessTokenUrlResp);
+ accessToken = jsonNode.get("access_token").asText();
+
+ // 将 access_token 存入 Redis,设置过期时间为 11 小时(有效期12小时)
+ redisTemplate.opsForValue().set(ACCESS_TOKEN_KEY, accessToken, 11, TimeUnit.HOURS);
+ } catch (Exception e) {
+
+ e.printStackTrace();
+ }
+ return accessToken;
+ }
+
+ public void deleteAccessToken() {
+ redisTemplate.delete(ACCESS_TOKEN_KEY);
+ }
+
+
+ public Boolean checkToken(String result) {
+ try {
+ ObjectMapper objectMapper = new ObjectMapper();
+ JsonNode jsonNode = objectMapper.readTree(result);
+ String code = jsonNode.path("code").asText();
+ if ("0x02401007".equals(code)) {
+ System.out.println("token失效,重新获取");
+ deleteAccessToken();
+ return false;
+ }
+ } catch (JsonProcessingException e) {
+ e.printStackTrace();
+ }
+ return true;
+ }
+
+ @GetMapping("/getRegionListToDB")
+ public void getRegionListToDB() {
+ try {
+ // 总记录数
+ int total = 0;
+ // 存储indexCodes
+ String[] indexCodes;
+ // 区域信息Json数据
+ String regionListJson;
+
+ JsonNode jsonNode;
+ JsonNode regionDataList;
+ // 查询有几条记录
+// String regionListPageURL = IntegrationURL.getRegionListPageURL(1, 1, getAccessToken());
+ String regionListPageURL = "{\n" +
+ " \"code\": \"0\",\n" +
+ " \"msg\": \"SUCCESS\",\n" +
+ " \"data\": {\n" +
+ " \"total\": 18,\n" +
+ " \"pageNo\": 2,\n" +
+ " \"pageSize\": 3,\n" +
+ " \"list\": [\n" +
+ " {\n" +
+ " \"indexCode\": \"root000000\",\n" +
+ " \"name\": \"根节点\",\n" +
+ " \"parentIndexCode\": \"null\",\n" +
+ " \"treeCode\": \"0\"\n" +
+ " }\n" +
+ " ]\n" +
+ " }\n" +
+ "}\n";
+// if (!checkToken(regionListPageURL)) {
+// regionListPageURL = IntegrationURL.getRegionListPageURL(1, 1, getAccessToken());
+// }
+ ObjectMapper objectMapper = new ObjectMapper();
+ jsonNode = objectMapper.readTree(regionListPageURL);
+ total = jsonNode.path("data").path("total").asInt();
+
+ // 查询所有记录的indexCode并保存
+ indexCodes = new String[100];
+ for (int i = 1; i <= (total / 100) + 1; i++) {
+// regionListPageURL = IntegrationURL.getRegionListPageURL(i, 100, getAccessToken());
+ ObjectMapper objectMapper2 = new ObjectMapper();
+ jsonNode = objectMapper2.readTree(regionListPageURL);
+ regionDataList = jsonNode.path("data").path("list");
+ Iterator elements2 = regionDataList.elements();
+ int j = 0;
+ while (elements2.hasNext()) {
+ indexCodes[j] = elements2.next().path("indexCode").asText();
+ j++;
+ }
+
+ // 保存后使用indexCodes数组查询区域详细信息
+// String regionListPageURL2 = IntegrationURL.getRegionByIndexCodesURL(indexCodes, getAccessToken());
+ String regionListPageURL2 = "{\n" +
+ " \"code\": \"0\",\n" +
+ " \"msg\": \"SUCCESS\",\n" +
+ " \"data\": {\n" +
+ " \"total\": 1,\n" +
+ " \"list\": [\n" +
+ " {\n" +
+ " \"indexCode\": \"root000000\",\n" +
+ " \"name\": \"根节点123123123123\",\n" +
+ " \"regionPath\": \"@root000000@\",\n" +
+ " \"parentIndexCode\": \"-1\",\n" +
+ " \"available\": true,\n" +
+ " \"leaf\": false,\n" +
+ " \"cascadeCode\": \"0\",\n" +
+ " \"cascadeType\": 0,\n" +
+ " \"catalogType\": 10,\n" +
+ " \"externalIndexCode\": \"34\",\n" +
+ " \"parentExternalIndexCode\": \"34\",\n" +
+ " \"sort\": 1,\n" +
+ " \"createTime\": \"2019-08-06T14:01:17.839+0800\",\n" +
+ " \"updateTime\": \"2019-08-07T14:01:17.839+0800\"\n" +
+ " }\n" +
+ " ]\n" +
+ " }\n" +
+ "}\n";
+ jsonNode = objectMapper.readTree(regionListPageURL2);
+ regionDataList = jsonNode.path("data").path("list");
+ Iterator elements3 = regionDataList.elements();
+ while (elements3.hasNext()) {
+ RegionDO regionDO = new RegionDO();
+ JsonNode regionNode = elements3.next();
+ regionDO.setIndexCode(regionNode.path("indexCode").asText());
+ regionDO.setName(regionNode.path("name").asText());
+ regionDO.setRegionPath(regionNode.path("regionPath").asText());
+ regionDO.setParentIndexCode(regionNode.path("parentIndexCode").asText());
+ regionDO.setCascadeCode(regionNode.path("cascadeCode").asText());
+ regionDO.setCascadeType(regionNode.path("cascadeType").asInt());
+ regionDO.setCatalogType(regionNode.path("catalogType").asInt());
+ regionDO.setExternalIndexCode(regionNode.path("externalIndexCode").asText());
+ regionDO.setSort(regionNode.path("sort").asInt());
+ System.out.println(regionNode.path("createTime").asText());
+ regionDO.setCreateTime(dateParse(regionNode.path("createTime").asText()));
+ regionDO.setUpdateTime(dateParse(regionNode.path("updateTime").asText()));
+ // 根据 indexCode 查询数据库中是否有对应的记录
+ RegionDO dbRegionData = regionService.selectByIndexCode(regionDO.getIndexCode());
+ RegionSaveReqVO regionSaveReqVO = BeanUtils.toBean(regionDO, RegionSaveReqVO.class);
+
+ // 如果数据库中有记录且数据不一致,执行更新操作
+ if (dbRegionData != null && !dbRegionData.getUpdateTime().equals(regionDO.getUpdateTime())) {
+ // 进行更新操作
+ System.out.println("dbRegionData:" + dbRegionData);
+ System.out.println("RegionDO:" + regionDO);
+ regionService.updateRegionCheckByCameraIndexCode(regionSaveReqVO);
+ System.out.println("更新了" + regionDO.getIndexCode() + "的数据");
+ } else if (dbRegionData == null) {
+ // 如果数据库中没有记录,则插入新数据
+ regionService.createRegion(regionSaveReqVO);
+ System.out.println("插入了" + regionDO.getIndexCode() + "的数据");
+ } else {
+ System.out.println("无需更新" + regionDO.getIndexCode() + "的数据");
+ }
+ }
+
+ // 本轮查询完毕后重置indexCodes
+ indexCodes = new String[total];
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ private LocalDateTime dateParse(String dateStr) {
+ String dateString = dateStr;
+ // 通过正则调整时区格式
+ // 这次确保只有一位数字时区后缀 +0800 被替换为 +08:00
+ if (dateString.matches(".*\\+\\d{4}$")) {
+ dateString = dateString.replaceAll("(\\+\\d{2})(\\d{2})$", "$1:$2");
+ }
+
+ // 定义一个日期格式化器,包括时区信息
+ DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
+
+ // 解析带有时区的字符串
+ OffsetDateTime offsetDateTime = OffsetDateTime.parse(dateString, formatter);
+
+ // 转换为 LocalDateTime
+ LocalDateTime localDateTime = offsetDateTime.toLocalDateTime();
+
+ return localDateTime;
+ }
+
+}
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/HikingServerApplication.java b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/HikingServerApplication.java
new file mode 100644
index 000000000..ef8785fb7
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/HikingServerApplication.java
@@ -0,0 +1,17 @@
+package cn.iocoder.yudao.module.hiking;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * @Description TODO
+ */
+@SpringBootApplication
+//@MapperScan("cn.iocoder.yudao.module.parking.dal.mysql.channelinformation.ChannelInformationMapper")
+public class HikingServerApplication {
+ //测试
+
+ public static void main(String[] args) {
+ SpringApplication.run(HikingServerApplication.class, args);
+ }
+}
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/api/HikingCameraApiImpl.java b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/api/HikingCameraApiImpl.java
new file mode 100644
index 000000000..8acac3681
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/api/HikingCameraApiImpl.java
@@ -0,0 +1,54 @@
+package cn.iocoder.yudao.module.hiking.api;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.hiking.IntegrationURL;
+import cn.iocoder.yudao.module.hiking.api.camera.CameraApi;
+import cn.iocoder.yudao.module.hiking.api.camera.dto.CameraDTO;
+import cn.iocoder.yudao.module.hiking.controller.admin.camera.vo.CameraPageReqVO;
+import cn.iocoder.yudao.module.hiking.dal.dataobject.camera.CameraConvert;
+import cn.iocoder.yudao.module.hiking.dal.dataobject.camera.CameraDO;
+import cn.iocoder.yudao.module.hiking.service.camera.CameraService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@RestController // 提供 RESTful API 接口,给 Feign 调用
+@Validated
+public class HikingCameraApiImpl implements CameraApi {
+ @Resource
+ private CameraService cameraService;
+
+ @Override
+ public CommonResult> selectCameraByPageAndCondition(String name) {
+ System.out.println(name);
+ CameraPageReqVO cameraPageReqVO = new CameraPageReqVO();
+ cameraPageReqVO.setCameraName(name);
+ PageResult cameraPage = cameraService.getCameraPage(cameraPageReqVO);
+ List cameraDTOList = new ArrayList<>();
+ cameraPage.getList().forEach(cameraDO -> {
+ CameraDTO cameraDTO = new CameraDTO();
+ cameraDTO.setCamera_type(cameraDO.getCameraType());
+ cameraDTO.setCameraName(cameraDO.getCameraName());
+ cameraDTO.setId(cameraDO.getId());
+ cameraDTO.setCameraIndexCode(cameraDO.getCameraIndexCode());
+ cameraDTOList.add(cameraDTO);
+ });
+ return success(cameraDTOList);
+ }
+
+ @Override
+ public CommonResult selectPreviewUrlByCameraIndexCode(String cameraIndexCode) {
+ return success(cameraService.getPreviewUrl(cameraIndexCode));
+ }
+
+ @Override
+ public CommonResult selectPlayBackUrlByCameraIndexCode(String cameraIndexCode, String beginTime, String endTime) {
+ return success(cameraService.getPlayBackUrl(cameraIndexCode, beginTime, endTime));
+ }
+}
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/controller/admin/camera/CameraController.java b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/controller/admin/camera/CameraController.java
new file mode 100644
index 000000000..47f370b39
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/controller/admin/camera/CameraController.java
@@ -0,0 +1,95 @@
+package cn.iocoder.yudao.module.hiking.controller.admin.camera;
+
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.security.access.prepost.PreAuthorize;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Operation;
+
+import java.util.*;
+import java.io.IOException;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
+
+import cn.iocoder.yudao.module.hiking.controller.admin.camera.vo.*;
+import cn.iocoder.yudao.module.hiking.dal.dataobject.camera.CameraDO;
+import cn.iocoder.yudao.module.hiking.service.camera.CameraService;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+
+@Tag(name = "管理后台 - 资源")
+@RestController
+@RequestMapping("/hiking/camera")
+@Validated
+public class CameraController {
+
+ @Resource
+ private CameraService cameraService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建资源")
+ @PreAuthorize("@ss.hasPermission('hiking:camera:create')")
+ public CommonResult createCamera(@Valid @RequestBody CameraSaveReqVO createReqVO) {
+ return success(cameraService.createCamera(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新资源")
+ @PreAuthorize("@ss.hasPermission('hiking:camera:update')")
+ public CommonResult updateCamera(@Valid @RequestBody CameraSaveReqVO updateReqVO) {
+ cameraService.updateCamera(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除资源")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('hiking:camera:delete')")
+ public CommonResult deleteCamera(@RequestParam("id") Long id) {
+ cameraService.deleteCamera(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得资源")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('hiking:camera:query')")
+ public CommonResult getCamera(@RequestParam("id") Long id) {
+ CameraDO camera = cameraService.getCamera(id);
+ return success(BeanUtils.toBean(camera, CameraRespVO.class));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得资源分页")
+ @PreAuthorize("@ss.hasPermission('hiking:camera:query')")
+ public CommonResult> getCameraPage(@Valid CameraPageReqVO pageReqVO) {
+ PageResult pageResult = cameraService.getCameraPage(pageReqVO);
+ return success(BeanUtils.toBean(pageResult, CameraRespVO.class));
+ }
+
+ @GetMapping("/export-excel")
+ @Operation(summary = "导出资源 Excel")
+ @PreAuthorize("@ss.hasPermission('hiking:camera:export')")
+ @ApiAccessLog(operateType = EXPORT)
+ public void exportCameraExcel(@Valid CameraPageReqVO pageReqVO,
+ HttpServletResponse response) throws IOException {
+ pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+ List list = cameraService.getCameraPage(pageReqVO).getList();
+ // 导出 Excel
+ ExcelUtils.write(response, "资源.xls", "数据", CameraRespVO.class,
+ BeanUtils.toBean(list, CameraRespVO.class));
+ }
+
+}
\ No newline at end of file
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/controller/admin/camera/vo/CameraPageReqVO.java b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/controller/admin/camera/vo/CameraPageReqVO.java
new file mode 100644
index 000000000..4f9016e81
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/controller/admin/camera/vo/CameraPageReqVO.java
@@ -0,0 +1,48 @@
+package cn.iocoder.yudao.module.hiking.controller.admin.camera.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 资源分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class CameraPageReqVO extends PageParam {
+
+ @Schema(description = "监控点类型说明")
+ private String cameraTypeName;
+
+ @Schema(description = "资源类型")
+ private String resourceType;
+
+ @Schema(description = "通道类型说明")
+ private String channelTypeName;
+
+ @Schema(description = "传输协议说明")
+ private String transTypeName;
+
+ @Schema(description = "接入协议说明")
+ private String treatyTypeName;
+
+ @Schema(description = "资源名称")
+ private String cameraName;
+
+ @Schema(description = "安装位置")
+ private String installLocation;
+
+ @Schema(description = "创建时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private String[] createTime;
+
+ @Schema(description = "更新时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private String[] updateTime;
+
+}
\ No newline at end of file
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/controller/admin/camera/vo/CameraRespVO.java b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/controller/admin/camera/vo/CameraRespVO.java
new file mode 100644
index 000000000..55fd3be0a
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/controller/admin/camera/vo/CameraRespVO.java
@@ -0,0 +1,174 @@
+package cn.iocoder.yudao.module.hiking.controller.admin.camera.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.util.*;
+import java.util.*;
+import java.math.BigDecimal;
+import com.alibaba.excel.annotation.*;
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
+
+@Schema(description = "管理后台 - 资源 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class CameraRespVO {
+
+ @Schema(description = "监控点唯一标识")
+ @ExcelProperty("监控点唯一标识")
+ private String cameraIndexCode;
+
+ @Schema(description = "海拔")
+ @ExcelProperty("海拔")
+ private String altitude;
+
+ @Schema(description = "监控点类型")
+ @ExcelProperty(value = "监控点类型", converter = DictConvert.class)
+ @DictFormat("camera_type") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
+ private Integer cameraType;
+
+ @Schema(description = "监控点类型说明")
+ @ExcelProperty("监控点类型说明")
+ private String cameraTypeName;
+
+ @Schema(description = "资源类型")
+ @ExcelProperty("资源类型")
+ private String resourceType;
+
+ @Schema(description = "设备能力集")
+ @ExcelProperty("设备能力集")
+ private String capabilitySet;
+
+ @Schema(description = "能力集说明")
+ @ExcelProperty("能力集说明")
+ private String capabilitySetName;
+
+ @Schema(description = "通道编号")
+ @ExcelProperty("通道编号")
+ private String channelNo;
+
+ @Schema(description = "通道类型说明")
+ @ExcelProperty("通道类型说明")
+ private String channelTypeName;
+
+ @Schema(description = "所属编码设备唯一标识")
+ @ExcelProperty("所属编码设备唯一标识")
+ private String encodeDevIndexCode;
+
+ @Schema(description = "监控点国标编号")
+ @ExcelProperty("监控点国标编号")
+ private String gbIndexCode;
+
+ @Schema(description = "键盘控制码")
+ @ExcelProperty("键盘控制码")
+ private String keyBoardCode;
+
+ @Schema(description = "录像存储位置说明")
+ @ExcelProperty("录像存储位置说明")
+ private String recordLocationName;
+
+ @Schema(description = "传输协议")
+ @ExcelProperty("传输协议")
+ private Integer transType;
+
+ @Schema(description = "传输协议说明")
+ @ExcelProperty("传输协议说明")
+ private String transTypeName;
+
+ @Schema(description = "接入协议")
+ @ExcelProperty("接入协议")
+ private String treatyType;
+
+ @Schema(description = "接入协议说明")
+ @ExcelProperty("接入协议说明")
+ private String treatyTypeName;
+
+ @Schema(description = "唯一编码")
+ @ExcelProperty("唯一编码")
+ private String indexCode;
+
+ @Schema(description = "监控点国标编号")
+ @ExcelProperty("监控点国标编号")
+ private String externalIndexCode;
+
+ @Schema(description = "资源名称")
+ @ExcelProperty("资源名称")
+ private String cameraName;
+
+ @Schema(description = "通道号")
+ @ExcelProperty("通道号")
+ private Integer chanNum;
+
+ @Schema(description = "级联编号")
+ @ExcelProperty("级联编号")
+ private String cascadeCode;
+
+ @Schema(description = "父级资源编号")
+ @ExcelProperty("父级资源编号")
+ private String parentIndexCode;
+
+ @Schema(description = "经度")
+ @ExcelProperty("经度")
+ private BigDecimal longitude;
+
+ @Schema(description = "纬度")
+ @ExcelProperty("纬度")
+ private BigDecimal latitude;
+
+ @Schema(description = "海拔高度")
+ @ExcelProperty("海拔高度")
+ private String elevation;
+
+ @Schema(description = "能力集")
+ @ExcelProperty("能力集")
+ private String capability;
+
+ @Schema(description = "录像存储位置")
+ @ExcelProperty("录像存储位置")
+ private String recordLocation;
+
+ @Schema(description = "通道子类型")
+ @ExcelProperty("通道子类型")
+ private String channelType;
+
+ @Schema(description = "所属区域")
+ @ExcelProperty("所属区域")
+ private String regionIndexCode;
+
+ @Schema(description = "所属区域路径")
+ @ExcelProperty("所属区域路径")
+ private String regionPath;
+
+ @Schema(description = "安装位置")
+ @ExcelProperty("安装位置")
+ private String installLocation;
+
+ @Schema(description = "创建时间")
+ @ExcelProperty("创建时间")
+ private String createTime;
+
+ @Schema(description = "更新时间")
+ @ExcelProperty("更新时间")
+ private String updateTime;
+
+ @Schema(description = "资源唯一编码")
+ @ExcelProperty("资源唯一编码")
+ private String resourceIndexCode;
+
+ @Schema(description = "解码模式")
+ @ExcelProperty("解码模式")
+ private String decodeTag;
+
+ @Schema(description = "监控点关联对讲唯一标志")
+ @ExcelProperty("监控点关联对讲唯一标志")
+ private String cameraRelateTalk;
+
+ @Schema(description = "所属区域路径")
+ @ExcelProperty("所属区域路径")
+ private String regionName;
+
+ @Schema(description = "区域路径名称")
+ @ExcelProperty("区域路径名称")
+ private String regionPathName;
+
+}
\ No newline at end of file
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/controller/admin/camera/vo/CameraSaveReqVO.java b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/controller/admin/camera/vo/CameraSaveReqVO.java
new file mode 100644
index 000000000..d83c7dfed
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/controller/admin/camera/vo/CameraSaveReqVO.java
@@ -0,0 +1,133 @@
+package cn.iocoder.yudao.module.hiking.controller.admin.camera.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+
+import java.time.LocalDateTime;
+import java.util.*;
+import java.math.BigDecimal;
+
+@Schema(description = "管理后台 - 资源新增/修改 Request VO")
+@Data
+public class CameraSaveReqVO {
+
+ @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED)
+ private Long id;
+
+ @Schema(description = "监控点唯一标识")
+ private String cameraIndexCode;
+
+ @Schema(description = "海拔")
+ private String altitude;
+
+ @Schema(description = "监控点类型")
+ private Integer cameraType;
+
+ @Schema(description = "监控点类型说明")
+ private String cameraTypeName;
+
+ @Schema(description = "资源类型")
+ private String resourceType;
+
+ @Schema(description = "设备能力集")
+ private String capabilitySet;
+
+ @Schema(description = "能力集说明")
+ private String capabilitySetName;
+
+ @Schema(description = "通道编号")
+ private String channelNo;
+
+ @Schema(description = "通道类型说明")
+ private String channelTypeName;
+
+ @Schema(description = "所属编码设备唯一标识")
+ private String encodeDevIndexCode;
+
+ @Schema(description = "监控点国标编号")
+ private String gbIndexCode;
+
+ @Schema(description = "键盘控制码")
+ private String keyBoardCode;
+
+ @Schema(description = "录像存储位置说明")
+ private String recordLocationName;
+
+ @Schema(description = "传输协议")
+ private Integer transType;
+
+ @Schema(description = "传输协议说明")
+ private String transTypeName;
+
+ @Schema(description = "接入协议")
+ private String treatyType;
+
+ @Schema(description = "接入协议说明")
+ private String treatyTypeName;
+
+ @Schema(description = "唯一编码")
+ private String indexCode;
+
+ @Schema(description = "监控点国标编号")
+ private String externalIndexCode;
+
+ @Schema(description = "资源名称")
+ private String cameraName;
+
+ @Schema(description = "通道号")
+ private Integer chanNum;
+
+ @Schema(description = "级联编号")
+ private String cascadeCode;
+
+ @Schema(description = "父级资源编号")
+ private String parentIndexCode;
+
+ @Schema(description = "经度")
+ private String longitude;
+
+ @Schema(description = "纬度")
+ private String latitude;
+
+ @Schema(description = "海拔高度")
+ private String elevation;
+
+ @Schema(description = "能力集")
+ private String capability;
+
+ @Schema(description = "录像存储位置")
+ private String recordLocation;
+
+ @Schema(description = "通道子类型")
+ private String channelType;
+
+ @Schema(description = "所属区域")
+ private String regionIndexCode;
+
+ @Schema(description = "所属区域路径")
+ private String regionPath;
+
+ @Schema(description = "安装位置")
+ private String installLocation;
+
+ @Schema(description = "数据在界面上的显示顺序")
+ private Integer disOrder;
+
+ @Schema(description = "资源唯一编码")
+ private String resourceIndexCode;
+
+ @Schema(description = "解码模式")
+ private String decodeTag;
+
+ @Schema(description = "监控点关联对讲唯一标志")
+ private String cameraRelateTalk;
+
+ @Schema(description = "所属区域路径")
+ private String regionName;
+
+ @Schema(description = "区域路径名称")
+ private String regionPathName;
+
+ private LocalDateTime createTime;
+ private LocalDateTime updateTime;
+}
\ No newline at end of file
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/controller/admin/region/RegionController.java b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/controller/admin/region/RegionController.java
new file mode 100644
index 000000000..ce672cc63
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/controller/admin/region/RegionController.java
@@ -0,0 +1,95 @@
+package cn.iocoder.yudao.module.hiking.controller.admin.region;
+
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.security.access.prepost.PreAuthorize;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Operation;
+
+import java.util.*;
+import java.io.IOException;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
+
+import cn.iocoder.yudao.module.hiking.controller.admin.region.vo.*;
+import cn.iocoder.yudao.module.hiking.dal.dataobject.region.RegionDO;
+import cn.iocoder.yudao.module.hiking.service.region.RegionService;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+
+@Tag(name = "管理后台 - 区域")
+@RestController
+@RequestMapping("/hiking/region")
+@Validated
+public class RegionController {
+
+ @Resource
+ private RegionService regionService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建区域")
+ @PreAuthorize("@ss.hasPermission('hiking:region:create')")
+ public CommonResult createRegion(@Valid @RequestBody RegionSaveReqVO createReqVO) {
+ return success(regionService.createRegion(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新区域")
+ @PreAuthorize("@ss.hasPermission('hiking:region:update')")
+ public CommonResult updateRegion(@Valid @RequestBody RegionSaveReqVO updateReqVO) {
+ regionService.updateRegion(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除区域")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('hiking:region:delete')")
+ public CommonResult deleteRegion(@RequestParam("id") Long id) {
+ regionService.deleteRegion(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得区域")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('hiking:region:query')")
+ public CommonResult getRegion(@RequestParam("id") Long id) {
+ RegionDO region = regionService.getRegion(id);
+ return success(BeanUtils.toBean(region, RegionRespVO.class));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得区域分页")
+ @PreAuthorize("@ss.hasPermission('hiking:region:query')")
+ public CommonResult> getRegionPage(@Valid RegionPageReqVO pageReqVO) {
+ PageResult pageResult = regionService.getRegionPage(pageReqVO);
+ return success(BeanUtils.toBean(pageResult, RegionRespVO.class));
+ }
+
+ @GetMapping("/export-excel")
+ @Operation(summary = "导出区域 Excel")
+ @PreAuthorize("@ss.hasPermission('hiking:region:export')")
+ @ApiAccessLog(operateType = EXPORT)
+ public void exportRegionExcel(@Valid RegionPageReqVO pageReqVO,
+ HttpServletResponse response) throws IOException {
+ pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+ List list = regionService.getRegionPage(pageReqVO).getList();
+ // 导出 Excel
+ ExcelUtils.write(response, "区域.xls", "数据", RegionRespVO.class,
+ BeanUtils.toBean(list, RegionRespVO.class));
+ }
+
+}
\ No newline at end of file
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/controller/admin/region/vo/RegionPageReqVO.java b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/controller/admin/region/vo/RegionPageReqVO.java
new file mode 100644
index 000000000..dbcec349f
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/controller/admin/region/vo/RegionPageReqVO.java
@@ -0,0 +1,41 @@
+package cn.iocoder.yudao.module.hiking.controller.admin.region.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 区域分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class RegionPageReqVO extends PageParam {
+
+ @Schema(description = "区域唯一标识码")
+ private String indexCode;
+
+ @Schema(description = "区域名称")
+ private String name;
+
+ @Schema(description = "区域类型")
+ private Integer regionType;
+
+ @Schema(description = "区域类型")
+ private Integer catalogType;
+
+ @Schema(description = "创建时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] createTime;
+
+ @Schema(description = "更新时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] updateTime;
+
+ @Schema(description = "资源状态")
+ private Integer status;
+
+}
\ No newline at end of file
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/controller/admin/region/vo/RegionRespVO.java b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/controller/admin/region/vo/RegionRespVO.java
new file mode 100644
index 000000000..ef2e6346b
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/controller/admin/region/vo/RegionRespVO.java
@@ -0,0 +1,60 @@
+package cn.iocoder.yudao.module.hiking.controller.admin.region.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.util.*;
+import java.util.*;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+import com.alibaba.excel.annotation.*;
+
+@Schema(description = "管理后台 - 区域 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class RegionRespVO {
+
+ @Schema(description = "区域唯一标识码")
+ @ExcelProperty("区域唯一标识码")
+ private String indexCode;
+
+ @Schema(description = "区域名称")
+ @ExcelProperty("区域名称")
+ private String name;
+
+ @Schema(description = "区域类型")
+ @ExcelProperty("区域类型")
+ private Integer regionType;
+
+ @Schema(description = "区域完整路径")
+ @ExcelProperty("区域完整路径")
+ private String regionPath;
+
+ @Schema(description = "区域类型")
+ @ExcelProperty("区域类型")
+ private Integer catalogType;
+
+ @Schema(description = "权限码")
+ @ExcelProperty("权限码")
+ private String authCodes;
+
+ @Schema(description = "外码")
+ @ExcelProperty("外码")
+ private String externalIndexCode;
+
+ @Schema(description = "父外码")
+ @ExcelProperty("父外码")
+ private String parentExternalIndexCode;
+
+ @Schema(description = "创建时间")
+ @ExcelProperty("创建时间")
+ private LocalDateTime createTime;
+
+ @Schema(description = "更新时间")
+ @ExcelProperty("更新时间")
+ private LocalDateTime updateTime;
+
+ @Schema(description = "资源状态")
+ @ExcelProperty("资源状态")
+ private Integer status;
+
+}
\ No newline at end of file
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/controller/admin/region/vo/RegionSaveReqVO.java b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/controller/admin/region/vo/RegionSaveReqVO.java
new file mode 100644
index 000000000..7d8fce354
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/controller/admin/region/vo/RegionSaveReqVO.java
@@ -0,0 +1,64 @@
+package cn.iocoder.yudao.module.hiking.controller.admin.region.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+
+import java.time.LocalDateTime;
+import java.util.*;
+
+@Schema(description = "管理后台 - 区域新增/修改 Request VO")
+@Data
+public class RegionSaveReqVO {
+
+ @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED)
+ private Long id;
+
+ @Schema(description = "区域唯一标识码")
+ private String indexCode;
+
+ @Schema(description = "区域名称")
+ private String name;
+
+ @Schema(description = "父级区域唯一标识码")
+ private String parentIndexCode;
+
+ @Schema(description = "树编号")
+ private String treeCode;
+
+ @Schema(description = "区域类型")
+ private Integer regionType;
+
+ @Schema(description = "区域完整路径")
+ private String regionPath;
+
+ @Schema(description = "是否为叶子节点")
+ private Integer leaf;
+
+ @Schema(description = "级联平台标识")
+ private String cascadeCode;
+
+ @Schema(description = "区域标识")
+ private Integer cascadeType;
+
+ @Schema(description = "区域类型")
+ private Integer catalogType;
+
+ @Schema(description = "权限码")
+ private String authCodes;
+
+ @Schema(description = "外码")
+ private String externalIndexCode;
+
+ @Schema(description = "父外码")
+ private String parentExternalIndexCode;
+
+ @Schema(description = "同级区域顺序")
+ private Integer sort;
+
+ @Schema(description = "资源状态")
+ private Integer status;
+
+ private LocalDateTime createTime;
+ private LocalDateTime updateTime;
+
+}
\ No newline at end of file
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/convert/camera/CameraConvertImpl.java b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/convert/camera/CameraConvertImpl.java
new file mode 100644
index 000000000..2bf7d0d86
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/convert/camera/CameraConvertImpl.java
@@ -0,0 +1,34 @@
+package cn.iocoder.yudao.module.hiking.convert.camera;
+
+import cn.iocoder.yudao.module.hiking.api.camera.dto.CameraDTO;
+import cn.iocoder.yudao.module.hiking.dal.dataobject.camera.CameraConvert;
+import cn.iocoder.yudao.module.hiking.dal.dataobject.camera.CameraDO;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CameraConvertImpl implements CameraConvert {
+ @Override
+ public CameraDTO convert02(CameraDO bean) {
+ if (bean == null) {
+ return null;
+ }
+ CameraDTO cameraDTO = new CameraDTO();
+ cameraDTO.setId(bean.getId());
+ cameraDTO.setCamera_type(bean.getCameraType());
+ cameraDTO.setCameraName(bean.getCameraName());
+ return cameraDTO;
+ }
+
+ @Override
+ public List convertList02(List list) {
+ if ( list == null ) {
+ return null;
+ }
+ List list1 = new ArrayList<>( list.size() );
+ for ( CameraDO cameraDO : list ) {
+ list1.add( convert02( cameraDO ) );
+ }
+ return list1;
+ }
+}
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/dal/dataobject/camera/CameraConvert.java b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/dal/dataobject/camera/CameraConvert.java
new file mode 100644
index 000000000..cdc3876e2
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/dal/dataobject/camera/CameraConvert.java
@@ -0,0 +1,12 @@
+package cn.iocoder.yudao.module.hiking.dal.dataobject.camera;
+
+import cn.iocoder.yudao.module.hiking.api.camera.dto.CameraDTO;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+
+public interface CameraConvert {
+ CameraConvert INSTANCE = Mappers.getMapper(CameraConvert.class);
+ CameraDTO convert02(CameraDO bean);
+ public List convertList02(List list);
+}
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/dal/dataobject/camera/CameraDO.java b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/dal/dataobject/camera/CameraDO.java
new file mode 100644
index 000000000..da12c8816
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/dal/dataobject/camera/CameraDO.java
@@ -0,0 +1,236 @@
+package cn.iocoder.yudao.module.hiking.dal.dataobject.camera;
+
+import lombok.*;
+
+import java.time.LocalDateTime;
+import java.util.*;
+import java.math.BigDecimal;
+import java.math.BigDecimal;
+import com.baomidou.mybatisplus.annotation.*;
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+
+/**
+ * 资源 DO
+ *
+ * @author 管理员
+ */
+@TableName("hiking_camera")
+@KeySequence("hiking_camera_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class CameraDO extends BaseDO {
+
+ /**
+ * 主键
+ */
+ @TableId
+ private Long id;
+ /**
+ * 监控点唯一标识
+ */
+ private String cameraIndexCode;
+ /**
+ * 海拔
+ */
+ private String altitude;
+ /**
+ * 资源名称
+ */
+ private String cameraName;
+ /**
+ * 监控点类型
+ *
+ * 枚举 {@link TODO camera_type 对应的类}
+ */
+ private Integer cameraType;
+ /**
+ * 监控点类型说明
+ */
+ private String cameraTypeName;
+ /**
+ * 设备能力集
+ */
+ private String capabilitySet;
+ /**
+ * 能力集说明
+ */
+ private String capabilitySetName;
+ /**
+ * 智能分析能力集
+ */
+ private String intelligentSet;
+ /**
+ * 智能分析能力集说明
+ */
+ private String intelligentSetName;
+ /**
+ * 通道编号
+ */
+ private String channelNo;
+ /**
+ * 通道子类型
+ */
+ private String channelType;
+ /**
+ * 通道类型说明
+ */
+ private String channelTypeName;
+ /**
+ * 所属编码设备唯一标识
+ */
+ private String encodeDevIndexCode;
+ /**
+ * 所属设备类型
+ */
+ private String encodeDevResourceType;
+ /**
+ * 所属设备类型说明
+ */
+ private String encodeDevResourceTypeName;
+ /**
+ * 监控点国标编号
+ */
+ private String gbIndexCode;
+ /**
+ * 安装位置
+ */
+ private String installLocation;
+ /**
+ * 键盘控制码
+ */
+ private String keyBoardCode;
+ /**
+ * 摄像机像素
+ */
+ private String pixel;
+ /**
+ * 云镜类型
+ */
+ private String ptz;
+ /**
+ * 云镜类型说明
+ */
+ private String ptzName;
+ /**
+ * 云台控制
+ */
+ private String ptzController;
+ /**
+ * 云台控制说明
+ */
+ private String ptzControllerName;
+ /**
+ * 录像存储位置
+ */
+ private String recordLocation;
+ /**
+ * 录像存储位置说明
+ */
+ private String recordLocationName;
+ /**
+ * 所属区域
+ */
+ private String regionIndexCode;
+ /**
+ * 在线状态
+ */
+ private String status;
+ /**
+ * 在线状态说明
+ */
+ private String statusName;
+ /**
+ * 传输协议
+ */
+ private Integer transType;
+ /**
+ * 传输协议说明
+ */
+ private String transTypeName;
+ /**
+ * 接入协议
+ */
+ private String treatyType;
+ /**
+ * 接入协议说明
+ */
+ private String treatyTypeName;
+ /**
+ * 可视域相关
+ */
+ private String viewshed;
+ /**
+ * 唯一编码
+ */
+ private String indexCode;
+ /**
+ * 资源类型
+ */
+ private String resourceType;
+ /**
+ * 监控点国标编号
+ */
+ private String externalIndexCode;
+ /**
+ * 通道号
+ */
+ private Integer chanNum;
+ /**
+ * 级联编号
+ */
+ private String cascadeCode;
+ /**
+ * 父级资源编号
+ */
+ private String parentIndexCode;
+ /**
+ * 经度
+ */
+ private String longitude;
+ /**
+ * 纬度
+ */
+ private String latitude;
+ /**
+ * 海拔高度
+ */
+ private String elevation;
+ /**
+ * 能力集
+ */
+ private String capability;
+ /**
+ * 所属区域路径
+ */
+ private String regionPath;
+ /**
+ * 数据在界面上的显示顺序
+ */
+ private Integer disOrder;
+ /**
+ * 资源唯一编码
+ */
+ private String resourceIndexCode;
+ /**
+ * 解码模式
+ */
+ private String decodeTag;
+ /**
+ * 监控点关联对讲唯一标志
+ */
+ private String cameraRelateTalk;
+ /**
+ * 所属区域路径
+ */
+ private String regionName;
+ /**
+ * 区域路径名称
+ */
+ private String regionPathName;
+ private LocalDateTime createTime;
+ private LocalDateTime updateTime;
+}
\ No newline at end of file
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/dal/dataobject/region/RegionDO.java b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/dal/dataobject/region/RegionDO.java
new file mode 100644
index 000000000..0e829dad4
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/dal/dataobject/region/RegionDO.java
@@ -0,0 +1,93 @@
+package cn.iocoder.yudao.module.hiking.dal.dataobject.region;
+
+import lombok.*;
+import java.util.*;
+import java.time.LocalDateTime;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.*;
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+
+/**
+ * 区域 DO
+ *
+ * @author 管理员
+ */
+@TableName("hiking_region")
+@KeySequence("hiking_region_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class RegionDO extends BaseDO {
+
+ /**
+ * 主键
+ */
+ @TableId
+ private Long id;
+ /**
+ * 区域唯一标识码
+ */
+ private String indexCode;
+ /**
+ * 区域名称
+ */
+ private String name;
+ /**
+ * 父级区域唯一标识码
+ */
+ private String parentIndexCode;
+ /**
+ * 树编号
+ */
+ private String treeCode;
+ /**
+ * 区域类型
+ */
+ private Integer regionType;
+ /**
+ * 区域完整路径
+ */
+ private String regionPath;
+ /**
+ * 是否为叶子节点
+ */
+ private Integer leaf;
+ /**
+ * 级联平台标识
+ */
+ private String cascadeCode;
+ /**
+ * 区域标识
+ */
+ private Integer cascadeType;
+ /**
+ * 区域类型
+ */
+ private Integer catalogType;
+ /**
+ * 权限码
+ */
+ private String authCodes;
+ /**
+ * 外码
+ */
+ private String externalIndexCode;
+ /**
+ * 父外码
+ */
+ private String parentExternalIndexCode;
+ /**
+ * 同级区域顺序
+ */
+ private Integer sort;
+ /**
+ * 资源状态
+ */
+ private Integer status;
+
+ private LocalDateTime createTime;
+ private LocalDateTime updateTime;
+}
\ No newline at end of file
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/dal/mysql/camera/CameraMapper.java b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/dal/mysql/camera/CameraMapper.java
new file mode 100644
index 000000000..d13f4ca35
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/dal/mysql/camera/CameraMapper.java
@@ -0,0 +1,42 @@
+package cn.iocoder.yudao.module.hiking.dal.mysql.camera;
+
+import java.util.*;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.module.hiking.dal.dataobject.camera.CameraDO;
+import cn.iocoder.yudao.module.hiking.dal.dataobject.region.RegionDO;
+import org.apache.ibatis.annotations.Mapper;
+import cn.iocoder.yudao.module.hiking.controller.admin.camera.vo.*;
+
+/**
+ * 资源 Mapper
+ *
+ * @author 管理员
+ */
+@Mapper
+public interface CameraMapper extends BaseMapperX {
+
+ default PageResult selectPage(CameraPageReqVO reqVO) {
+ return selectPage(reqVO, new LambdaQueryWrapperX()
+ .likeIfPresent(CameraDO::getCameraTypeName, reqVO.getCameraTypeName())
+ .eqIfPresent(CameraDO::getResourceType, reqVO.getResourceType())
+ .likeIfPresent(CameraDO::getChannelTypeName, reqVO.getChannelTypeName())
+ .likeIfPresent(CameraDO::getTransTypeName, reqVO.getTransTypeName())
+ .likeIfPresent(CameraDO::getTreatyTypeName, reqVO.getTreatyTypeName())
+ .likeIfPresent(CameraDO::getCameraName, reqVO.getCameraName())
+ .eqIfPresent(CameraDO::getInstallLocation, reqVO.getInstallLocation())
+ .betweenIfPresent(CameraDO::getCreateTime, reqVO.getCreateTime())
+ .betweenIfPresent(CameraDO::getUpdateTime, reqVO.getUpdateTime())
+ .orderByDesc(CameraDO::getId));
+ }
+
+ default CameraDO selectByCameraIndexCode(String cameraIndexCode) {
+ return selectOne(new LambdaQueryWrapperX().eq(CameraDO::getCameraIndexCode, cameraIndexCode));
+ }
+
+ default int updateByCameraIndexCode(CameraDO updateObj) {
+ return update(updateObj, new LambdaQueryWrapperX().eq(CameraDO::getCameraIndexCode, updateObj.getCameraIndexCode()));
+ }
+}
\ No newline at end of file
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/dal/mysql/region/RegionMapper.java b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/dal/mysql/region/RegionMapper.java
new file mode 100644
index 000000000..f62de4685
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/dal/mysql/region/RegionMapper.java
@@ -0,0 +1,43 @@
+package cn.iocoder.yudao.module.hiking.dal.mysql.region;
+
+import java.util.*;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.module.hiking.dal.dataobject.region.RegionDO;
+import org.apache.ibatis.annotations.Mapper;
+import cn.iocoder.yudao.module.hiking.controller.admin.region.vo.*;
+
+/**
+ * 区域 Mapper
+ *
+ * @author 管理员
+ */
+@Mapper
+public interface RegionMapper extends BaseMapperX {
+
+ default PageResult selectPage(RegionPageReqVO reqVO) {
+ return selectPage(reqVO, new LambdaQueryWrapperX()
+ .eqIfPresent(RegionDO::getIndexCode, reqVO.getIndexCode())
+ .likeIfPresent(RegionDO::getName, reqVO.getName())
+ .eqIfPresent(RegionDO::getRegionType, reqVO.getRegionType())
+ .eqIfPresent(RegionDO::getCatalogType, reqVO.getCatalogType())
+ .betweenIfPresent(RegionDO::getCreateTime, reqVO.getCreateTime())
+ .betweenIfPresent(RegionDO::getUpdateTime, reqVO.getUpdateTime())
+ .eqIfPresent(RegionDO::getStatus, reqVO.getStatus())
+ .orderByDesc(RegionDO::getId));
+ }
+
+ default RegionDO selectByIndexCode(String indexCode) {
+ return selectOne(new LambdaQueryWrapperX().eq(RegionDO::getIndexCode, indexCode));
+ }
+
+ default RegionDO selectByRegionName(String regionName) {
+ return selectOne(new LambdaQueryWrapperX().eq(RegionDO::getName, regionName));
+ }
+
+ default int updateByRegionIndexCode(RegionDO regionDO) {
+ return update(regionDO, new LambdaQueryWrapperX().eq(RegionDO::getIndexCode, regionDO.getIndexCode()));
+ }
+}
\ No newline at end of file
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/framework/security/config/SecurityConfiguration.java b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/framework/security/config/SecurityConfiguration.java
new file mode 100644
index 000000000..799cb65c3
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/framework/security/config/SecurityConfiguration.java
@@ -0,0 +1,38 @@
+package cn.iocoder.yudao.module.hiking.framework.security.config;
+
+import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer;
+import cn.iocoder.yudao.module.hiking.enums.ApiConstants;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
+
+/**
+ * Demo 模块的 Security 配置
+ */
+@Configuration(proxyBeanMethods = false)
+public class SecurityConfiguration {
+
+ @Bean
+ public AuthorizeRequestsCustomizer authorizeRequestsCustomizer() {
+ return new AuthorizeRequestsCustomizer() {
+
+ @Override
+ public void customize(ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry registry) {
+ registry.antMatchers("/**").permitAll(); // 允许所有路径都可以访问
+ // Swagger 接口文档
+ registry.antMatchers("/v3/api-docs/**").permitAll() // 元数据
+ .antMatchers("/swagger-ui.html").permitAll(); // Swagger UI
+ // Druid 监控
+ registry.antMatchers("/druid/**").anonymous();
+ // Spring Boot Actuator 的安全配置
+ registry.antMatchers("/actuator").anonymous()
+ .antMatchers("/actuator/**").anonymous();
+ // RPC 服务的安全配置
+ registry.antMatchers(ApiConstants.PREFIX + "/**").permitAll();
+ }
+
+ };
+ }
+
+}
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/service/camera/CameraService.java b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/service/camera/CameraService.java
new file mode 100644
index 000000000..ad838cd34
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/service/camera/CameraService.java
@@ -0,0 +1,63 @@
+package cn.iocoder.yudao.module.hiking.service.camera;
+
+import java.util.*;
+import cn.iocoder.yudao.module.hiking.controller.admin.camera.vo.*;
+import cn.iocoder.yudao.module.hiking.dal.dataobject.camera.CameraDO;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+
+import javax.validation.Valid;
+
+/**
+ * 资源 Service 接口
+ *
+ * @author 管理员
+ */
+public interface CameraService {
+
+ /**
+ * 创建资源
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ Long createCamera(@Valid CameraSaveReqVO createReqVO);
+
+ /**
+ * 更新资源
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateCamera(@Valid CameraSaveReqVO updateReqVO);
+
+ /**
+ * 删除资源
+ *
+ * @param id 编号
+ */
+ void deleteCamera(Long id);
+
+ /**
+ * 获得资源
+ *
+ * @param id 编号
+ * @return 资源
+ */
+ CameraDO getCamera(Long id);
+
+ /**
+ * 获得资源分页
+ *
+ * @param pageReqVO 分页查询
+ * @return 资源分页
+ */
+ PageResult getCameraPage(CameraPageReqVO pageReqVO);
+
+ CameraDO selectByCameraIndexCode(String cameraIndexCode);
+
+ String getPreviewUrl(String cameraIndexCode);
+ String getPlayBackUrl(String cameraIndexCode, String startTime, String endTime);
+
+ void updateCameraCheckByCameraIndexCode(@Valid CameraSaveReqVO cameraSaveReqVO);
+
+}
\ No newline at end of file
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/service/camera/CameraServiceImpl.java b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/service/camera/CameraServiceImpl.java
new file mode 100644
index 000000000..84f800a58
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/service/camera/CameraServiceImpl.java
@@ -0,0 +1,168 @@
+package cn.iocoder.yudao.module.hiking.service.camera;
+
+import cn.iocoder.yudao.module.hiking.IntegrationURL;
+import cn.iocoder.yudao.module.hiking.service.region.RegionService;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+import cn.iocoder.yudao.module.hiking.controller.admin.camera.vo.*;
+import cn.iocoder.yudao.module.hiking.dal.dataobject.camera.CameraDO;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+
+import cn.iocoder.yudao.module.hiking.dal.mysql.camera.CameraMapper;
+
+import javax.annotation.Resource;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.hiking.enums.ErrorCodeConstants.*;
+
+/**
+ * 资源 Service 实现类
+ *
+ * @author 管理员
+ */
+@Service
+@Validated
+public class CameraServiceImpl implements CameraService {
+
+ @Resource
+ private CameraMapper cameraMapper;
+
+ private ObjectMapper objectMapper;
+ @Autowired
+ private RedisTemplate redisTemplate;
+ private static final String ACCESS_TOKEN_KEY = "hikingAPI:access_token";
+
+
+ public String getAccessToken() {
+ // 检查 Redis 中是否有 access_token
+ String accessToken = (String) redisTemplate.opsForValue().get(ACCESS_TOKEN_KEY);
+ if (!StringUtils.isEmpty(accessToken)) {
+ System.out.println("使用缓存的token:" + accessToken);
+ return accessToken; // 如果存在则直接返回
+ }
+
+ // 如果没有,调用 API 获取并存入 Redis
+ System.out.println("获取新的token");
+ String accessTokenUrlResp = IntegrationURL.getAccessTokenURL();
+ try {
+
+ JsonNode jsonNode = objectMapper.readTree(accessTokenUrlResp);
+ accessToken = jsonNode.get("access_token").asText();
+
+ // 将 access_token 存入 Redis,设置过期时间为 11 小时(有效期12小时)
+ redisTemplate.opsForValue().set(ACCESS_TOKEN_KEY, accessToken, 11, TimeUnit.HOURS);
+ } catch (Exception e) {
+
+ e.printStackTrace();
+ }
+ return accessToken;
+ }
+
+ public void deleteAccessToken() {
+ redisTemplate.delete(ACCESS_TOKEN_KEY);
+ }
+
+
+ public Boolean checkToken(String result) {
+ try {
+
+ JsonNode jsonNode = objectMapper.readTree(result);
+ String code = jsonNode.path("code").asText();
+ if ("0x02401007".equals(code)) {
+ System.out.println("token失效,重新获取");
+ deleteAccessToken();
+ return false;
+ }
+ } catch (JsonProcessingException e) {
+ e.printStackTrace();
+ }
+ return true;
+ }
+
+
+ @Override
+ public Long createCamera(CameraSaveReqVO createReqVO) {
+ // 插入
+ CameraDO camera = BeanUtils.toBean(createReqVO, CameraDO.class);
+ cameraMapper.insert(camera);
+ // 返回
+ return camera.getId();
+ }
+
+ @Override
+ public void updateCamera(CameraSaveReqVO updateReqVO) {
+ // 校验存在
+ validateCameraExists(updateReqVO.getId());
+ // 更新
+ CameraDO updateObj = BeanUtils.toBean(updateReqVO, CameraDO.class);
+ cameraMapper.updateById(updateObj);
+ }
+
+ @Override
+ public void deleteCamera(Long id) {
+ // 校验存在
+ validateCameraExists(id);
+ // 删除
+ cameraMapper.deleteById(id);
+ }
+
+ private void validateCameraExists(Long id) {
+ if (cameraMapper.selectById(id) == null) {
+ throw exception(CAMERA_NOT_EXISTS);
+ }
+ }
+
+ private void validateCameraExistsByCameraIndexCode(String cameraIndexCode) {
+ if (cameraMapper.selectByCameraIndexCode(cameraIndexCode) == null) {
+ throw exception(CAMERA_NOT_EXISTS);
+ }
+ }
+
+ @Override
+ public CameraDO getCamera(Long id) {
+ return cameraMapper.selectById(id);
+ }
+
+ @Override
+ public PageResult getCameraPage(CameraPageReqVO pageReqVO) {
+ return cameraMapper.selectPage(pageReqVO);
+ }
+
+ @Override
+ public CameraDO selectByCameraIndexCode(String cameraIndexCode) {
+ return cameraMapper.selectByCameraIndexCode(cameraIndexCode);
+ }
+
+ @Override
+ public String getPreviewUrl(String cameraIndexCode) {
+ return IntegrationURL.getPreviewURL(cameraIndexCode, getAccessToken());
+ }
+
+ @Override
+ public String getPlayBackUrl(String cameraIndexCode, String startTime, String endTime) {
+ return IntegrationURL.getPlaybackURL(cameraIndexCode, startTime, endTime, getAccessToken());
+ }
+
+ @Override
+ public void updateCameraCheckByCameraIndexCode(CameraSaveReqVO updateReqVO) {
+ // 校验存在
+ validateCameraExistsByCameraIndexCode(updateReqVO.getCameraIndexCode());
+ // 更新
+ CameraDO updateObj = BeanUtils.toBean(updateReqVO, CameraDO.class);
+ cameraMapper.updateByCameraIndexCode(updateObj);
+ }
+
+}
\ No newline at end of file
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/service/region/RegionService.java b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/service/region/RegionService.java
new file mode 100644
index 000000000..0f507a9c8
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/service/region/RegionService.java
@@ -0,0 +1,59 @@
+package cn.iocoder.yudao.module.hiking.service.region;
+
+import java.util.*;
+import cn.iocoder.yudao.module.hiking.controller.admin.region.vo.*;
+import cn.iocoder.yudao.module.hiking.dal.dataobject.region.RegionDO;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+
+import javax.validation.Valid;
+
+/**
+ * 区域 Service 接口
+ *
+ * @author 管理员
+ */
+public interface RegionService {
+
+ /**
+ * 创建区域
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ Long createRegion(@Valid RegionSaveReqVO createReqVO);
+
+ /**
+ * 更新区域
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateRegion(@Valid RegionSaveReqVO updateReqVO);
+
+ /**
+ * 删除区域
+ *
+ * @param id 编号
+ */
+ void deleteRegion(Long id);
+
+ /**
+ * 获得区域
+ *
+ * @param id 编号
+ * @return 区域
+ */
+ RegionDO getRegion(Long id);
+
+ /**
+ * 获得区域分页
+ *
+ * @param pageReqVO 分页查询
+ * @return 区域分页
+ */
+ PageResult getRegionPage(RegionPageReqVO pageReqVO);
+ RegionDO selectByIndexCode(String indexCode);
+ RegionDO selectByRegionName(String regionName);
+
+ public void updateRegionCheckByCameraIndexCode(RegionSaveReqVO updateReqVO);
+}
\ No newline at end of file
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/service/region/RegionServiceImpl.java b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/service/region/RegionServiceImpl.java
new file mode 100644
index 000000000..a9d06ed20
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/src/main/java/cn/iocoder/yudao/module/hiking/service/region/RegionServiceImpl.java
@@ -0,0 +1,101 @@
+package cn.iocoder.yudao.module.hiking.service.region;
+
+import cn.iocoder.yudao.module.hiking.controller.admin.camera.vo.CameraSaveReqVO;
+import cn.iocoder.yudao.module.hiking.dal.dataobject.camera.CameraDO;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+import cn.iocoder.yudao.module.hiking.controller.admin.region.vo.*;
+import cn.iocoder.yudao.module.hiking.dal.dataobject.region.RegionDO;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+
+import cn.iocoder.yudao.module.hiking.dal.mysql.region.RegionMapper;
+
+import javax.annotation.Resource;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.hiking.enums.ErrorCodeConstants.*;
+
+/**
+ * 区域 Service 实现类
+ *
+ * @author 管理员
+ */
+@Service
+@Validated
+public class RegionServiceImpl implements RegionService {
+
+ @Resource
+ private RegionMapper regionMapper;
+
+ @Override
+ public Long createRegion(RegionSaveReqVO createReqVO) {
+ // 插入
+ RegionDO region = BeanUtils.toBean(createReqVO, RegionDO.class);
+ regionMapper.insert(region);
+ // 返回
+ return region.getId();
+ }
+
+ @Override
+ public void updateRegion(RegionSaveReqVO updateReqVO) {
+ // 校验存在
+ validateRegionExists(updateReqVO.getId());
+ // 更新
+ RegionDO updateObj = BeanUtils.toBean(updateReqVO, RegionDO.class);
+ regionMapper.updateById(updateObj);
+ }
+
+ @Override
+ public void deleteRegion(Long id) {
+ // 校验存在
+ validateRegionExists(id);
+ // 删除
+ regionMapper.deleteById(id);
+ }
+
+ private void validateRegionExists(Long id) {
+ if (regionMapper.selectById(id) == null) {
+ throw exception(REGION_NOT_EXISTS);
+ }
+ }
+
+ private void validateRegionExistsByCameraIndexCode(String regionIndexCode) {
+ if (regionMapper.selectByIndexCode(regionIndexCode) == null) {
+ throw exception(CAMERA_NOT_EXISTS);
+ }
+ }
+
+ @Override
+ public RegionDO getRegion(Long id) {
+ return regionMapper.selectById(id);
+ }
+
+ @Override
+ public PageResult getRegionPage(RegionPageReqVO pageReqVO) {
+ return regionMapper.selectPage(pageReqVO);
+ }
+
+ @Override
+ public RegionDO selectByIndexCode(String indexCode) {
+ return regionMapper.selectByIndexCode(indexCode);
+ }
+
+ @Override
+ public RegionDO selectByRegionName(String regionName) {
+ return regionMapper.selectByRegionName(regionName);
+ }
+
+ @Override
+ public void updateRegionCheckByCameraIndexCode(RegionSaveReqVO updateReqVO) {
+ // 校验存在
+ validateRegionExistsByCameraIndexCode(updateReqVO.getIndexCode());
+ // 更新
+ RegionDO updateObj = BeanUtils.toBean(updateReqVO, RegionDO.class);
+ regionMapper.updateByRegionIndexCode(updateObj);
+ }
+}
\ No newline at end of file
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/src/main/resources/bootstrap.yaml b/ludu-module-hiking/ludu-module-hiking-biz/src/main/resources/bootstrap.yaml
new file mode 100644
index 000000000..884446dc5
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/src/main/resources/bootstrap.yaml
@@ -0,0 +1,38 @@
+spring:
+ application:
+ name: hiking-server
+ main:
+ allow-bean-definition-overriding: true # 允许 Bean 覆盖,例如说 Feign 等会存在重复定义的服务
+ profiles:
+ active: local
+
+server:
+ port: 48094
+
+# 日志文件配置。注意,如果 logging.file.name 不放在 bootstrap.yaml 配置文件,而是放在 application.yaml 中,会导致出现 LOG_FILE_IS_UNDEFINED 文件
+logging:
+ file:
+ name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径
+--- #################### 注册中心相关配置 ####################
+
+spring:
+ cloud:
+ nacos:
+ server-addr: 172.17.0.1:8848
+ discovery:
+ namespace: ${spring.profiles.active} # 命名空间。这里使用 dev 开发环境
+ metadata:
+ version: 1.0.0 # 服务实例的版本号,可用于灰度发布
+
+--- #################### 配置中心相关配置 ####################
+
+spring:
+ cloud:
+ nacos:
+ # Nacos Config 配置项,对应 NacosConfigProperties 配置属性类
+ config:
+ server-addr: 172.17.0.1:8848 # Nacos 服务器地址
+ namespace: ${spring.profiles.active} # 命名空间 dev 的ID,不能直接使用 dev 名称。创建命名空间的时候需要指定ID为 dev,这里使用 dev 开发环境
+ group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
+ name: ${spring.application.name} # 使用的 Nacos 配置集的 dataId,默认为 spring.application.name
+ file-extension: yaml # 使用的 Nacos 配置集的 dataId 的文件拓展名,同时也是 Nacos 配置集的配置格式,默认为 properties
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/src/main/resources/mapper/camera/CameraMapper.xml b/ludu-module-hiking/ludu-module-hiking-biz/src/main/resources/mapper/camera/CameraMapper.xml
new file mode 100644
index 000000000..c9fdb654d
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/src/main/resources/mapper/camera/CameraMapper.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/src/main/resources/mapper/region/RegionMapper.xml b/ludu-module-hiking/ludu-module-hiking-biz/src/main/resources/mapper/region/RegionMapper.xml
new file mode 100644
index 000000000..429198be4
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/src/main/resources/mapper/region/RegionMapper.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ludu-module-hiking/ludu-module-hiking-biz/src/test/java/cn/iocoder/yudao/module/hiking/service/camera/CameraServiceImplTest.java b/ludu-module-hiking/ludu-module-hiking-biz/src/test/java/cn/iocoder/yudao/module/hiking/service/camera/CameraServiceImplTest.java
new file mode 100644
index 000000000..684b14dea
--- /dev/null
+++ b/ludu-module-hiking/ludu-module-hiking-biz/src/test/java/cn/iocoder/yudao/module/hiking/service/camera/CameraServiceImplTest.java
@@ -0,0 +1,162 @@
+package cn.iocoder.yudao.module.hiking.service.camera;
+
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.mock.mockito.MockBean;
+
+import jakarta.annotation.Resource;
+
+import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
+
+import cn.iocoder.yudao.module.hiking.controller.admin.camera.vo.*;
+import cn.iocoder.yudao.module.hiking.dal.dataobject.camera.CameraDO;
+import cn.iocoder.yudao.module.hiking.dal.mysql.camera.CameraMapper;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+
+import jakarta.annotation.Resource;
+import org.springframework.context.annotation.Import;
+import java.util.*;
+import java.time.LocalDateTime;
+
+import static cn.hutool.core.util.RandomUtil.*;
+import static cn.iocoder.yudao.module.hiking.enums.ErrorCodeConstants.*;
+import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
+import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
+import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+/**
+ * {@link CameraServiceImpl} 的单元测试类
+ *
+ * @author 管理员
+ */
+@Import(CameraServiceImpl.class)
+public class CameraServiceImplTest extends BaseDbUnitTest {
+
+ @Resource
+ private CameraServiceImpl cameraService;
+
+ @Resource
+ private CameraMapper cameraMapper;
+
+ @Test
+ public void testCreateCamera_success() {
+ // 准备参数
+ CameraSaveReqVO createReqVO = randomPojo(CameraSaveReqVO.class).setId(null);
+
+ // 调用
+ Long cameraId = cameraService.createCamera(createReqVO);
+ // 断言
+ assertNotNull(cameraId);
+ // 校验记录的属性是否正确
+ CameraDO camera = cameraMapper.selectById(cameraId);
+ assertPojoEquals(createReqVO, camera, "id");
+ }
+
+ @Test
+ public void testUpdateCamera_success() {
+ // mock 数据
+ CameraDO dbCamera = randomPojo(CameraDO.class);
+ cameraMapper.insert(dbCamera);// @Sql: 先插入出一条存在的数据
+ // 准备参数
+ CameraSaveReqVO updateReqVO = randomPojo(CameraSaveReqVO.class, o -> {
+ o.setId(dbCamera.getId()); // 设置更新的 ID
+ });
+
+ // 调用
+ cameraService.updateCamera(updateReqVO);
+ // 校验是否更新正确
+ CameraDO camera = cameraMapper.selectById(updateReqVO.getId()); // 获取最新的
+ assertPojoEquals(updateReqVO, camera);
+ }
+
+ @Test
+ public void testUpdateCamera_notExists() {
+ // 准备参数
+ CameraSaveReqVO updateReqVO = randomPojo(CameraSaveReqVO.class);
+
+ // 调用, 并断言异常
+ assertServiceException(() -> cameraService.updateCamera(updateReqVO), CAMERA_NOT_EXISTS);
+ }
+
+ @Test
+ public void testDeleteCamera_success() {
+ // mock 数据
+ CameraDO dbCamera = randomPojo(CameraDO.class);
+ cameraMapper.insert(dbCamera);// @Sql: 先插入出一条存在的数据
+ // 准备参数
+ Long id = dbCamera.getId();
+
+ // 调用
+ cameraService.deleteCamera(id);
+ // 校验数据不存在了
+ assertNull(cameraMapper.selectById(id));
+ }
+
+ @Test
+ public void testDeleteCamera_notExists() {
+ // 准备参数
+ Long id = randomLongId();
+
+ // 调用, 并断言异常
+ assertServiceException(() -> cameraService.deleteCamera(id), CAMERA_NOT_EXISTS);
+ }
+
+ @Test
+ @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
+ public void testGetCameraPage() {
+ // mock 数据
+ CameraDO dbCamera = randomPojo(CameraDO.class, o -> { // 等会查询到
+ o.setCameraTypeName(null);
+ o.setResourceType(null);
+ o.setChannelTypeName(null);
+ o.setTransTypeName(null);
+ o.setTreatyTypeName(null);
+ o.setName(null);
+ o.setInstallLocation(null);
+ o.setCreateTime(null);
+ o.setUpdateTime(null);
+ });
+ cameraMapper.insert(dbCamera);
+ // 测试 cameraTypeName 不匹配
+ cameraMapper.insert(cloneIgnoreId(dbCamera, o -> o.setCameraTypeName(null)));
+ // 测试 resourceType 不匹配
+ cameraMapper.insert(cloneIgnoreId(dbCamera, o -> o.setResourceType(null)));
+ // 测试 channelTypeName 不匹配
+ cameraMapper.insert(cloneIgnoreId(dbCamera, o -> o.setChannelTypeName(null)));
+ // 测试 transTypeName 不匹配
+ cameraMapper.insert(cloneIgnoreId(dbCamera, o -> o.setTransTypeName(null)));
+ // 测试 treatyTypeName 不匹配
+ cameraMapper.insert(cloneIgnoreId(dbCamera, o -> o.setTreatyTypeName(null)));
+ // 测试 name 不匹配
+ cameraMapper.insert(cloneIgnoreId(dbCamera, o -> o.setName(null)));
+ // 测试 installLocation 不匹配
+ cameraMapper.insert(cloneIgnoreId(dbCamera, o -> o.setInstallLocation(null)));
+ // 测试 createTime 不匹配
+ cameraMapper.insert(cloneIgnoreId(dbCamera, o -> o.setCreateTime(null)));
+ // 测试 updateTime 不匹配
+ cameraMapper.insert(cloneIgnoreId(dbCamera, o -> o.setUpdateTime(null)));
+ // 准备参数
+ CameraPageReqVO reqVO = new CameraPageReqVO();
+ reqVO.setCameraTypeName(null);
+ reqVO.setResourceType(null);
+ reqVO.setChannelTypeName(null);
+ reqVO.setTransTypeName(null);
+ reqVO.setTreatyTypeName(null);
+ reqVO.setName(null);
+ reqVO.setInstallLocation(null);
+ reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
+ reqVO.setUpdateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
+
+ // 调用
+ PageResult pageResult = cameraService.getCameraPage(reqVO);
+ // 断言
+ assertEquals(1, pageResult.getTotal());
+ assertEquals(1, pageResult.getList().size());
+ assertPojoEquals(dbCamera, pageResult.getList().get(0));
+ }
+
+}
\ No newline at end of file
diff --git a/ludu-module-hiking/pom.xml b/ludu-module-hiking/pom.xml
new file mode 100644
index 000000000..63357bfdc
--- /dev/null
+++ b/ludu-module-hiking/pom.xml
@@ -0,0 +1,21 @@
+
+ 4.0.0
+
+ cn.iocoder.cloud
+ yudao
+ 2.1.0-jdk8-snapshot
+
+
+ ludu-module-hiking
+ pom
+
+ ${project.artifactId}
+ 2.1.0-jdk8-snapshot
+ http://maven.apache.org/
+ 2001
+
+ ludu-module-hiking-api
+ ludu-module-hiking-biz
+
+
diff --git a/pom.xml b/pom.xml
index c5a145adc..b70c7d517 100644
--- a/pom.xml
+++ b/pom.xml
@@ -18,6 +18,7 @@
ludu-job-admin
ludu-module-parking
ludu-module-datacenter
+ ludu-module-hiking