Commit 0a82502a authored by zhouleilei's avatar zhouleilei

Merge remote-tracking branch 'origin/master'

parents 2dde54a3 671b290f
...@@ -241,7 +241,93 @@ ...@@ -241,7 +241,93 @@
</attributes> </attributes>
</configuration> </configuration>
</plugin> </plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<!--<version>2.6</version>-->
<executions>
<!--将启动脚本复制到指定目录-->
<execution>
<id>copy-bin</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.parent.basedir}/assembly/${project.name}/bin</outputDirectory>
<resources>
<resource>
<directory>src/main/bin</directory>
<filtering>false</filtering>
</resource>
</resources>
</configuration>
</execution>
<!--将配置文件复制到指定目录-->
<execution>
<id>copy-configs</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.parent.basedir}/assembly/${project.name}/resources
</outputDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>**/bin/*</exclude>
</excludes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
<executions>
<!--将依赖jar包复制到lib目录-->
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.parent.basedir}/assembly/${project.name}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<!--指定生成jar包目录-->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<!--<classpathPrefix>lib/</classpathPrefix>-->
<classpathPrefix></classpathPrefix>
<mainClass> net.wanji.web.SignalApplication</mainClass>
</manifest>
<manifestEntries>
<Class-Path>../resources/</Class-Path>
</manifestEntries>
</archive>
<excludes>
<exclude>*.**</exclude>
<exclude>*/*.xml</exclude>
<!--<exclude>configs/**/**</exclude>-->
</excludes>
<outputDirectory>${project.parent.basedir}/assembly/${project.name}/lib</outputDirectory>
<classesDirectory>
</classesDirectory>
</configuration>
</plugin>
<!-- mvn clean package -Dmaven.test.skip=true jib:build -DsendCredentialsOverHttp=true --> <!-- mvn clean package -Dmaven.test.skip=true jib:build -DsendCredentialsOverHttp=true -->
<!-- 使用jib 无需深入学习docker, 无需编写Dockerfile --> <!-- 使用jib 无需深入学习docker, 无需编写Dockerfile -->
<plugin> <plugin>
......
package net.wanji.web.controller.base;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import net.wanji.common.framework.rest.JsonViewObject;
import net.wanji.databus.dao.entity.GreenwaveCrossPO;
import net.wanji.databus.dao.entity.GreenwaveInfoPO;
import net.wanji.databus.dao.entity.RidInfoEntity;
import net.wanji.databus.po.BaseCrossInfoPO;
import net.wanji.databus.po.CrossBaseLaneInfoPO;
import net.wanji.databus.po.CrossTurnInfoPO;
import net.wanji.web.service.BaseInfoService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.ws.rs.core.MediaType;
import java.util.List;
/**
* @author duanruiming
* @date 2024/11/13 20:30
*/
@Api(value = "CrossBaseInfoController", description = "路网基础信息")
@RequestMapping("/baseInfo")
@RestController
public class CrossBaseInfoController {
@Resource
private BaseInfoService baseInfoService;
@ApiOperation(value = "路口信息查询", notes = "路口信息查询", response = JsonViewObject.class,
produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
@GetMapping(value = "/crossInfoList")
@ApiResponses({
@ApiResponse(code = 200, message = "OK", response = JsonViewObject.class),
})
public JsonViewObject crossInfoList() {
List<BaseCrossInfoPO> baseCrossInfoPOS = baseInfoService.crossInfoList();
return JsonViewObject.newInstance().success(baseCrossInfoPOS);
}
@ApiOperation(value = "车道信息查询", notes = "车道信息查询", response = JsonViewObject.class,
produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
@GetMapping(value = "/laneInfoList")
@ApiResponses({
@ApiResponse(code = 200, message = "OK", response = JsonViewObject.class),
})
public JsonViewObject laneInfoList() {
List<CrossBaseLaneInfoPO> crossBaseLaneInfoPOS = baseInfoService.laneInfoList();
return JsonViewObject.newInstance().success(crossBaseLaneInfoPOS);
}
@ApiOperation(value = "路段信息查询", notes = "路段信息查询", response = JsonViewObject.class,
produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
@GetMapping(value = "/ridInfoList")
@ApiResponses({
@ApiResponse(code = 200, message = "OK", response = JsonViewObject.class),
})
public JsonViewObject ridInfoList() {
List<RidInfoEntity> ridInfoEntities = baseInfoService.ridInfoList();
return JsonViewObject.newInstance().success(ridInfoEntities);
}
@ApiOperation(value = "转向信息查询", notes = "车道信息查询", response = JsonViewObject.class,
produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
@GetMapping(value = "/turnInfoList")
@ApiResponses({
@ApiResponse(code = 200, message = "OK", response = JsonViewObject.class),
})
public JsonViewObject turnInfoList() {
List<CrossTurnInfoPO> crossTurnInfoPOS = baseInfoService.turnInfoList();
return JsonViewObject.newInstance().success(crossTurnInfoPOS);
}
@ApiOperation(value = "绿波基础信息查询", notes = "绿波基础信息查询", response = JsonViewObject.class,
produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
@GetMapping(value = "/greenInfoList")
@ApiResponses({
@ApiResponse(code = 200, message = "OK", response = JsonViewObject.class),
})
public JsonViewObject greenInfoList() {
List<GreenwaveInfoPO> greenwaveInfoPOS = baseInfoService.greenInfoList();
return JsonViewObject.newInstance().success(greenwaveInfoPOS);
}
@ApiOperation(value = "绿波关联路口信息查询", notes = "绿波关联路口信息查询", response = JsonViewObject.class,
produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
@GetMapping(value = "/greenCrossInfoList")
@ApiResponses({
@ApiResponse(code = 200, message = "OK", response = JsonViewObject.class),
})
public JsonViewObject greenCrossInfoList() {
List<GreenwaveCrossPO> greenwaveCrossPOS = baseInfoService.greenCrossInfoList();
return JsonViewObject.newInstance().success(greenwaveCrossPOS);
}
}
package net.wanji.web.service;
import net.wanji.databus.dao.entity.GreenwaveCrossPO;
import net.wanji.databus.dao.entity.GreenwaveInfoPO;
import net.wanji.databus.dao.entity.RidInfoEntity;
import net.wanji.databus.po.BaseCrossInfoPO;
import net.wanji.databus.po.CrossBaseLaneInfoPO;
import net.wanji.databus.po.CrossTurnInfoPO;
import java.util.List;
/**
* @author duanruiming
* @date 2024/11/13 20:33
*/
public interface BaseInfoService {
List<BaseCrossInfoPO> crossInfoList();
List<CrossBaseLaneInfoPO> laneInfoList();
List<RidInfoEntity> ridInfoList();
List<CrossTurnInfoPO> turnInfoList();
List<GreenwaveInfoPO> greenInfoList();
List<GreenwaveCrossPO> greenCrossInfoList();
}
package net.wanji.web.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import net.wanji.databus.dao.entity.GreenwaveCrossPO;
import net.wanji.databus.dao.entity.GreenwaveInfoPO;
import net.wanji.databus.dao.entity.RidInfoEntity;
import net.wanji.databus.dao.mapper.*;
import net.wanji.databus.po.BaseCrossInfoPO;
import net.wanji.databus.po.CrossBaseLaneInfoPO;
import net.wanji.databus.po.CrossTurnInfoPO;
import net.wanji.web.service.BaseInfoService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
* @author duanruiming
* @date 2024/11/13 20:33
*/
@Service
public class BaseInfoServiceImpl implements BaseInfoService {
@Resource
private RidInfoMapper ridInfoMapper;
@Resource
private BaseCrossInfoMapper baseCrossInfoMapper;
@Resource
private CrossBaseLaneInfoMapper crossBaseLaneInfoMapper;
@Resource
private BaseCrossTurnInfoMapper baseCrossTurnInfoMapper;
@Resource
private GreenwaveInfoMapper greenwaveInfoMapper;
@Resource
private GreenwaveCrossMapper greenwaveCrossMapper;
@Override
public List<BaseCrossInfoPO> crossInfoList() {
List<BaseCrossInfoPO> list = baseCrossInfoMapper.selectAll();
return list;
}
@Override
public List<CrossBaseLaneInfoPO> laneInfoList() {
LambdaQueryWrapper<CrossBaseLaneInfoPO> queryWrapper = new LambdaQueryWrapper<>();
List<CrossBaseLaneInfoPO> crossBaseLaneInfoPOS = crossBaseLaneInfoMapper.selectList(queryWrapper);
return crossBaseLaneInfoPOS;
}
@Override
public List<RidInfoEntity> ridInfoList() {
List<RidInfoEntity> ridInfoEntities = ridInfoMapper.selectAll();
return ridInfoEntities;
}
@Override
public List<CrossTurnInfoPO> turnInfoList() {
List<CrossTurnInfoPO> crossTurnInfoPOS = baseCrossTurnInfoMapper.selectAll();
return crossTurnInfoPOS;
}
@Override
public List<GreenwaveInfoPO> greenInfoList() {
List<GreenwaveInfoPO> greenwaveInfoPOS = greenwaveInfoMapper.selectAll();
return greenwaveInfoPOS;
}
@Override
public List<GreenwaveCrossPO> greenCrossInfoList() {
List<GreenwaveCrossPO> greenwaveCrossPOS = greenwaveCrossMapper.selectAll();
return greenwaveCrossPOS;
}
}
package net.wanji.web.service.scheme.impl; package net.wanji.web.service.scheme.impl;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import net.wanji.databus.bo.CrossIdBO;
import net.wanji.common.enums.LightsAddressEnum; import net.wanji.common.enums.LightsAddressEnum;
import net.wanji.databus.dao.mapper.*; import net.wanji.databus.bo.CrossIdBO;
import net.wanji.databus.dao.mapper.BaseCrossLaneLightsMapper;
import net.wanji.databus.dao.mapper.BaseCrossLightsMapper;
import net.wanji.databus.dao.mapper.BaseCrossPhaseLightsMapper;
import net.wanji.databus.dao.mapper.LaneInfoMapper;
import net.wanji.databus.po.BaseCrossLightsPO; import net.wanji.databus.po.BaseCrossLightsPO;
import net.wanji.databus.po.CrossLaneLightsPO; import net.wanji.databus.po.CrossLaneLightsPO;
import net.wanji.databus.po.LaneInfoPO; import net.wanji.databus.po.LaneInfoPO;
import net.wanji.web.common.enums.CrossLisghtsLaneDirEnum; import net.wanji.web.common.enums.CrossLisghtsLaneDirEnum;
import net.wanji.web.common.exception.LightLaneConflictException; import net.wanji.web.common.exception.LightLaneConflictException;
import net.wanji.web.common.exception.RidInfoException;
import net.wanji.web.dto.DirListElement; import net.wanji.web.dto.DirListElement;
import net.wanji.web.dto.LaneListElement; import net.wanji.web.dto.LaneListElement;
import net.wanji.web.dto.LedConfigListElement; import net.wanji.web.dto.LedConfigListElement;
...@@ -461,12 +462,13 @@ public class CrossConfigServiceImpl implements CrossConfigService { ...@@ -461,12 +462,13 @@ public class CrossConfigServiceImpl implements CrossConfigService {
String sortStr = "1" + (i + 1); String sortStr = "1" + (i + 1);
int sort = Integer.parseInt(sortStr); int sort = Integer.parseInt(sortStr);
// 上一个路口ID // 上一个路口ID
String preId = laneInfoMapper.selectPreId(crossId, dir); String preId = "13N8J0B5P10";
if (ObjectUtil.isEmpty(preId)) { //String preId = laneInfoMapper.selectPreId(crossId, dir);
throw new RidInfoException("基础路网中无上一路口数据"); //if (ObjectUtil.isEmpty(preId)) {
} // throw new RidInfoException("基础路网中无上一路口数据");
// 0 主路;900 进口道渠化序号。信控车道类型都是进口车道 //}
laneInfoPO.setId(preId + crossId + 0 + 900 + sort); // 主路;900 进口道渠化序号。信控车道类型都是进口车道
laneInfoPO.setId(dir + crossId + 0 + 900 + sort);
laneInfoPO.setCode(laneListElement.getName()); laneInfoPO.setCode(laneListElement.getName());
laneInfoPO.setSort(sort); laneInfoPO.setSort(sort);
laneInfoPO.setDir(dir); laneInfoPO.setDir(dir);
......
utc.service.url=http://37.12.182.29:32000/utc
utc.dt.service.url=http://37.12.182.29:39002/utc-dt
utc.hisense.service.url=http://37.12.182.29:39003/utc-hisense
control.url=http://37.12.182.29:32001/web
utc.service.url=http://173.17.0.1:32000/utc
utc.dt.service.url=http://173.17.0.1:39002/utc-dt
utc.hisense.service.url=http://173.17.0.1:39003/utc-hisense
control.url=http://173.17.0.1:32001/web
package net.wanji.opt.dao.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import net.wanji.opt.synthesis.pojo.StrategyFactoryEntity;
/**
* @author duanruiming
* @date 2024/11/13 13:42
*/
public interface StrategyFactoryMapper extends BaseMapper<StrategyFactoryEntity> {
}
...@@ -9,6 +9,7 @@ import net.wanji.opt.dao.mapper.SynthesisOptimizeLogInfoMapper; ...@@ -9,6 +9,7 @@ import net.wanji.opt.dao.mapper.SynthesisOptimizeLogInfoMapper;
import net.wanji.opt.synthesis.pojo.StrategyControlDataEntity; import net.wanji.opt.synthesis.pojo.StrategyControlDataEntity;
import net.wanji.opt.synthesis.pojo.StrategyControlDetailList; import net.wanji.opt.synthesis.pojo.StrategyControlDetailList;
import net.wanji.opt.synthesis.pojo.StrategyControlVO; import net.wanji.opt.synthesis.pojo.StrategyControlVO;
import net.wanji.opt.synthesis.pojo.StrategyFactoryEntity;
import net.wanji.opt.synthesis.service.StrategyControlService; import net.wanji.opt.synthesis.service.StrategyControlService;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
...@@ -66,6 +67,18 @@ public class StrategyControlController { ...@@ -66,6 +67,18 @@ public class StrategyControlController {
return strategyControlService.crossStrategyInfoList(type); return strategyControlService.crossStrategyInfoList(type);
} }
@ApiOperation(value = "路网优化监测", notes = "路网优化监测",
response = JsonViewObject.class,
produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
@GetMapping(value = "/crossOptInfoList")
@ApiResponses({
@ApiResponse(code = 200, message = "OK", response = StrategyControlDataEntity.class),
})
public JsonViewObject crossOptInfoList(@RequestParam Integer type) throws Exception {
return strategyControlService.crossOptInfoList(type);
}
@ApiOperation(value = "策略管理计划详情查询", notes = "策略管理计划详情查询", @ApiOperation(value = "策略管理计划详情查询", notes = "策略管理计划详情查询",
response = JsonViewObject.class, response = JsonViewObject.class,
produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON) produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
...@@ -100,4 +113,40 @@ public class StrategyControlController { ...@@ -100,4 +113,40 @@ public class StrategyControlController {
public JsonViewObject strategyPlanSave(@RequestBody @Validated StrategyControlDetailList list) throws Exception { public JsonViewObject strategyPlanSave(@RequestBody @Validated StrategyControlDetailList list) throws Exception {
return strategyControlService.strategyPlanSave(list); return strategyControlService.strategyPlanSave(list);
} }
@ApiOperation(value = "策略库查询列表", notes = "策略库查询列表",
response = JsonViewObject.class,
produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
@GetMapping(value = "/strategyFactoryList")
@ApiResponses({
@ApiResponse(code = 200, message = "OK", response = StrategyFactoryEntity.class),
})
public JsonViewObject strategyFactoryList() throws Exception {
return strategyControlService.strategyFactoryList();
}
@ApiOperation(value = "策略管理计划保存", notes = "策略管理计划列表查询",
response = JsonViewObject.class,
produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
@PostMapping(value = "/strategyFactorySave",
produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
@ApiResponses({
@ApiResponse(code = 200, message = "OK", response = StrategyFactoryEntity.class),
})
public JsonViewObject strategyFactorySave(@RequestBody @Validated StrategyFactoryEntity entity) throws Exception {
return strategyControlService.strategyFactorySave(entity);
}
@ApiOperation(value = "策略管理计划保存", notes = "策略管理计划列表查询",
response = JsonViewObject.class,
produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
@PostMapping(value = "/strategyFactoryDel",
produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
@ApiResponses({
@ApiResponse(code = 200, message = "OK", response = StrategyFactoryEntity.class),
})
public JsonViewObject strategyFactoryDel(@RequestBody Integer id) throws Exception {
return strategyControlService.strategyFactoryDel(id);
}
} }
...@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.IdType; ...@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data; import lombok.Data;
import net.wanji.databus.vo.PageVO; import net.wanji.databus.vo.PageVO;
...@@ -28,9 +29,11 @@ public class StrategyControlDataEntity extends PageVO { ...@@ -28,9 +29,11 @@ public class StrategyControlDataEntity extends PageVO {
private Integer strategy; private Integer strategy;
/** value = 开始时间日期 */ /** value = 开始时间日期 */
@TableField("schedule_start") @TableField("schedule_start")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date scheduleStart; private Date scheduleStart;
/** value = 结束时间日期 */ /** value = 结束时间日期 */
@TableField("schedule_end") @TableField("schedule_end")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date scheduleEnd; private Date scheduleEnd;
/** value = 日计划表 */ /** value = 日计划表 */
private String time; private String time;
......
package net.wanji.opt.synthesis.pojo;
import lombok.Data;
/**
* @author duanruiming
* @date 2024/11/13 19:31
*/
@Data
public class StrategyControlDataExt extends StrategyControlDataEntity{
private String strategyName;
private String optStatus;
}
package net.wanji.opt.synthesis.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author duanruiming
* @date 2024/11/13 13:35
*/
@Data
@TableName("t_strategy_factory_info")
@ApiModel(value = "StrategyFactoryEntity", description = "策略库实体")
public class StrategyFactoryEntity {
@ApiModelProperty("自增Id")
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@ApiModelProperty("场景")
@TableField("scene")
private Integer scene;
@ApiModelProperty("策略")
@TableField("strategy_name")
private String strategyName;
@ApiModelProperty("策略编号")
@TableField("strategy_no")
private String strategyNo;
@ApiModelProperty("算法厂商")
@TableField("company")
private String company;
@ApiModelProperty("备注")
@TableField("mark")
private String mark;
}
...@@ -4,6 +4,7 @@ import net.wanji.common.framework.rest.JsonViewObject; ...@@ -4,6 +4,7 @@ import net.wanji.common.framework.rest.JsonViewObject;
import net.wanji.opt.synthesis.pojo.StrategyControlDataEntity; import net.wanji.opt.synthesis.pojo.StrategyControlDataEntity;
import net.wanji.opt.synthesis.pojo.StrategyControlDetailList; import net.wanji.opt.synthesis.pojo.StrategyControlDetailList;
import net.wanji.opt.synthesis.pojo.StrategyControlVO; import net.wanji.opt.synthesis.pojo.StrategyControlVO;
import net.wanji.opt.synthesis.pojo.StrategyFactoryEntity;
/** /**
* @author duanruiming * @author duanruiming
...@@ -14,8 +15,12 @@ public interface StrategyControlService { ...@@ -14,8 +15,12 @@ public interface StrategyControlService {
JsonViewObject strategyInfoPageList(StrategyControlDataEntity entity) throws Exception; JsonViewObject strategyInfoPageList(StrategyControlDataEntity entity) throws Exception;
JsonViewObject crossStrategyInfoList(Integer type) throws Exception; JsonViewObject crossStrategyInfoList(Integer type) throws Exception;
JsonViewObject crossOptInfoList(Integer type) throws Exception;
JsonViewObject strategyPlanDetail(String crossId) throws Exception; JsonViewObject strategyPlanDetail(String crossId) throws Exception;
JsonViewObject strategyPush(StrategyControlDetailList list) throws Exception; JsonViewObject strategyPush(StrategyControlDetailList list) throws Exception;
JsonViewObject strategyPlanSave(StrategyControlDetailList list) throws Exception; JsonViewObject strategyPlanSave(StrategyControlDetailList list) throws Exception;
JsonViewObject strategyFactoryList() throws Exception;
JsonViewObject strategyFactorySave(StrategyFactoryEntity entity) throws Exception;
JsonViewObject strategyFactoryDel(Integer id) throws Exception;
} }
...@@ -12,11 +12,13 @@ import net.wanji.common.enums.DateStyle; ...@@ -12,11 +12,13 @@ import net.wanji.common.enums.DateStyle;
import net.wanji.common.framework.Constants; import net.wanji.common.framework.Constants;
import net.wanji.common.framework.rest.JsonViewObject; import net.wanji.common.framework.rest.JsonViewObject;
import net.wanji.common.utils.tool.JacksonUtils; import net.wanji.common.utils.tool.JacksonUtils;
import net.wanji.databus.dao.entity.GreenwaveInfoPO;
import net.wanji.databus.dao.mapper.BaseCrossInfoMapper; import net.wanji.databus.dao.mapper.BaseCrossInfoMapper;
import net.wanji.databus.dao.mapper.GreenwaveInfoMapper;
import net.wanji.databus.po.BaseCrossInfoPO; import net.wanji.databus.po.BaseCrossInfoPO;
import net.wanji.feign.service.UtcFeignClients;
import net.wanji.opt.dao.mapper.StrategyControlInfoMapper; import net.wanji.opt.dao.mapper.StrategyControlInfoMapper;
import net.wanji.opt.dao.mapper.StrategyDailyPlanInfoMapper; import net.wanji.opt.dao.mapper.StrategyDailyPlanInfoMapper;
import net.wanji.opt.dao.mapper.StrategyFactoryMapper;
import net.wanji.opt.dao.mapper.StrategyPlanInfoMapper; import net.wanji.opt.dao.mapper.StrategyPlanInfoMapper;
import net.wanji.opt.synthesis.pojo.*; import net.wanji.opt.synthesis.pojo.*;
import net.wanji.opt.synthesis.service.PushStrategyControlService; import net.wanji.opt.synthesis.service.PushStrategyControlService;
...@@ -28,6 +30,7 @@ import org.springframework.util.CollectionUtils; ...@@ -28,6 +30,7 @@ import org.springframework.util.CollectionUtils;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
...@@ -48,9 +51,11 @@ public class StrategyControlServiceImpl implements StrategyControlService { ...@@ -48,9 +51,11 @@ public class StrategyControlServiceImpl implements StrategyControlService {
@Resource @Resource
private StrategyDailyPlanInfoMapper strategyDailyPlanInfoMapper; private StrategyDailyPlanInfoMapper strategyDailyPlanInfoMapper;
@Resource @Resource
private UtcFeignClients utcFeignClients;
@Resource
private BaseCrossInfoMapper baseCrossInfoMapper; private BaseCrossInfoMapper baseCrossInfoMapper;
@Resource
private StrategyFactoryMapper strategyFactoryMapper;
@Resource
private GreenwaveInfoMapper greenwaveInfoMapper;
@Override @Override
...@@ -104,20 +109,8 @@ public class StrategyControlServiceImpl implements StrategyControlService { ...@@ -104,20 +109,8 @@ public class StrategyControlServiceImpl implements StrategyControlService {
List<StrategyControlDataReq> dataReqList = new ArrayList<>(dataList.size()); List<StrategyControlDataReq> dataReqList = new ArrayList<>(dataList.size());
for (StrategyControlDataVO dataVO : dataList) { for (StrategyControlDataVO dataVO : dataList) {
StrategyControlDataReq detailData = new StrategyControlDataReq(); StrategyControlDataReq detailData = new StrategyControlDataReq();
detailData.setBiz_id(dataVO.getBizId());
detailData.setBiz_type(dataVO.getBizType()); detailData.setBiz_type(dataVO.getBizType());
//try {
// if (0 == dataVO.getBizType()) {
// CrossIdBO crossIdBO = new CrossIdBO();
// crossIdBO.setCrossId(dataVO.getBizId());
// JsonViewObject jsonViewObject = utcFeignClients.crossInfoById(crossIdBO);
// Object content = jsonViewObject.getContent();
// CrossInfoPO crossInfoPO = instance.readValue(String.valueOf(content), CrossInfoPO.class);
// detailData.setBiz_id(crossInfoPO.getCode());
// }
//} catch (JsonProcessingException e) {
// detailData.setBiz_id(null);
//}
detailData.setBiz_id("311358");
detailData.setStrategy(dataVO.getStrategy()); detailData.setStrategy(dataVO.getStrategy());
detailData.setSchedule_start(DateUtil.format(dataVO.getScheduleStart(), DateStyle.YYYY_MM_DD_HH_MM_SS.getValue())); detailData.setSchedule_start(DateUtil.format(dataVO.getScheduleStart(), DateStyle.YYYY_MM_DD_HH_MM_SS.getValue()));
detailData.setSchedule_end(DateUtil.format(dataVO.getScheduleEnd(), DateStyle.YYYY_MM_DD_HH_MM_SS.getValue())); detailData.setSchedule_end(DateUtil.format(dataVO.getScheduleEnd(), DateStyle.YYYY_MM_DD_HH_MM_SS.getValue()));
...@@ -167,6 +160,16 @@ public class StrategyControlServiceImpl implements StrategyControlService { ...@@ -167,6 +160,16 @@ public class StrategyControlServiceImpl implements StrategyControlService {
@Override @Override
public JsonViewObject crossStrategyInfoList(Integer type) throws Exception { public JsonViewObject crossStrategyInfoList(Integer type) throws Exception {
try {
List<StrategyControlDataEntity> results = getCurrentStrateInfoList(type);
return JsonViewObject.newInstance().success(results);
} catch (Exception e) {
log.error("策略控制查询列表:{}", e);
throw new RuntimeException(e);
}
}
private List<StrategyControlDataEntity> getCurrentStrateInfoList(Integer type) throws Exception {
ObjectMapper instance = JacksonUtils.getInstance(); ObjectMapper instance = JacksonUtils.getInstance();
LambdaQueryWrapper<StrategyControlDataEntity> queryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<StrategyControlDataEntity> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(StrategyControlDataEntity::getBizType, type); queryWrapper.eq(StrategyControlDataEntity::getBizType, type);
...@@ -182,7 +185,8 @@ public class StrategyControlServiceImpl implements StrategyControlService { ...@@ -182,7 +185,8 @@ public class StrategyControlServiceImpl implements StrategyControlService {
result.setTime(""); result.setTime("");
} else { } else {
String time = entity.getTime(); String time = entity.getTime();
List<StrategyControlDataVO.TimeTable> timeTables = instance.readValue(time, new TypeReference<List<StrategyControlDataVO.TimeTable>>() {}); List<StrategyControlDataVO.TimeTable> timeTables = instance.readValue(time, new TypeReference<List<StrategyControlDataVO.TimeTable>>() {
});
for (StrategyControlDataVO.TimeTable timeTable : timeTables) { for (StrategyControlDataVO.TimeTable timeTable : timeTables) {
int currentWeek = DateUtil.thisDayOfWeek(); int currentWeek = DateUtil.thisDayOfWeek();
if (currentWeek != timeTable.getWeek()) { if (currentWeek != timeTable.getWeek()) {
...@@ -192,7 +196,7 @@ public class StrategyControlServiceImpl implements StrategyControlService { ...@@ -192,7 +196,7 @@ public class StrategyControlServiceImpl implements StrategyControlService {
for (String s : timeList) { for (String s : timeList) {
String[] hours = s.split(","); String[] hours = s.split(",");
for (String hour : hours) { for (String hour : hours) {
String[] currentHour = hour.split("-"); String[] currentHour = hour.split("-");
String startHour = currentHour[0]; String startHour = currentHour[0];
String entHour = currentHour[1]; String entHour = currentHour[1];
String format = DateUtil.format(current, "HH:mm"); String format = DateUtil.format(current, "HH:mm");
...@@ -207,13 +211,50 @@ public class StrategyControlServiceImpl implements StrategyControlService { ...@@ -207,13 +211,50 @@ public class StrategyControlServiceImpl implements StrategyControlService {
} }
} }
} }
BaseCrossInfoPO baseCrossInfoPO = baseCrossInfoMapper.selectById(entity.getBizId()); if (type == 0) {
result.setCrossName(baseCrossInfoPO.getName()); BaseCrossInfoPO baseCrossInfoPO = baseCrossInfoMapper.selectById(entity.getBizId());
result.setCrossName(baseCrossInfoPO.getName());
}
if (type == 1) {
GreenwaveInfoPO greenwaveInfoPO = greenwaveInfoMapper.selectById(Integer.valueOf(entity.getBizId()));
result.setCrossName(greenwaveInfoPO.getName());
}
results.add(result); results.add(result);
} }
return JsonViewObject.newInstance().success(results); return results;
} }
@Override
public JsonViewObject crossOptInfoList(Integer type) throws Exception {
JsonViewObject jsonViewObject = JsonViewObject.newInstance();
try {
List<StrategyControlDataEntity> currentStrateInfoList = getCurrentStrateInfoList(type);
List<StrategyFactoryEntity> strategyFactoryEntities = strategyFactoryMapper.selectList(null);
List<StrategyControlDataExt> strategyControlDataExts = new ArrayList<>();
for (StrategyControlDataEntity strategyControlDataEntity : currentStrateInfoList) {
Integer strategy = strategyControlDataEntity.getStrategy();
StrategyControlDataExt strategyControlDataExt = new StrategyControlDataExt();
BeanUtils.copyProperties(strategyControlDataExt, strategyControlDataEntity);
String strategyName = "";
for (StrategyFactoryEntity strategyFactoryEntity : strategyFactoryEntities) {
if (strategy == strategyFactoryEntity.getScene()) {
strategyName = strategyFactoryEntity.getStrategyName();
}
}
strategyControlDataExt.setStrategyName(strategyName);
strategyControlDataExt.setOptStatus("未执行");
if (StringUtils.isNotBlank(strategyControlDataEntity.getTime())) {
strategyControlDataExt.setOptStatus("优化中");
}
strategyControlDataExts.add(strategyControlDataExt);
}
strategyControlDataExts.sort(Comparator.comparing(StrategyControlDataExt::getOptStatus));
return jsonViewObject.success(strategyControlDataExts, "路网优化监测查询成功");
} catch (Exception e) {
log.error("路网优化监测查询失败: {}", e);
return jsonViewObject.fail("路网优化监测查询失败");
}
}
@Override @Override
public JsonViewObject strategyPlanDetail(String crossId) throws Exception { public JsonViewObject strategyPlanDetail(String crossId) throws Exception {
...@@ -235,7 +276,8 @@ public class StrategyControlServiceImpl implements StrategyControlService { ...@@ -235,7 +276,8 @@ public class StrategyControlServiceImpl implements StrategyControlService {
executePlan.setStatus(planInfoEntity.getStatus()); executePlan.setStatus(planInfoEntity.getStatus());
executePlan.setType(planInfoEntity.getType()); executePlan.setType(planInfoEntity.getType());
String planDetailsStr = planInfoEntity.getPlanDetails(); String planDetailsStr = planInfoEntity.getPlanDetails();
List<StrategyControlDetailList.ExecutePlan.PlanDetail> planDetails = instance.readValue(planDetailsStr, new TypeReference<List<StrategyControlDetailList.ExecutePlan.PlanDetail>>() {}); List<StrategyControlDetailList.ExecutePlan.PlanDetail> planDetails = instance.readValue(planDetailsStr, new TypeReference<List<StrategyControlDetailList.ExecutePlan.PlanDetail>>() {
});
executePlan.setPlanDetails(planDetails); executePlan.setPlanDetails(planDetails);
executePlans.add(executePlan); executePlans.add(executePlan);
} }
...@@ -250,7 +292,8 @@ public class StrategyControlServiceImpl implements StrategyControlService { ...@@ -250,7 +292,8 @@ public class StrategyControlServiceImpl implements StrategyControlService {
dailyPlan.setCrossId(dailyPlanInfoEntity.getCrossId()); dailyPlan.setCrossId(dailyPlanInfoEntity.getCrossId());
dailyPlan.setDailyPlanId(dailyPlanInfoEntity.getDailyPlanId()); dailyPlan.setDailyPlanId(dailyPlanInfoEntity.getDailyPlanId());
String dailyPlanDetailsStr = dailyPlanInfoEntity.getDailyPlanDetails(); String dailyPlanDetailsStr = dailyPlanInfoEntity.getDailyPlanDetails();
List<StrategyControlDetailList.DailyPlan.DailyPlanDetail> dailyPlanDetails = instance.readValue(dailyPlanDetailsStr, new TypeReference<List<StrategyControlDetailList.DailyPlan.DailyPlanDetail>>() {}); List<StrategyControlDetailList.DailyPlan.DailyPlanDetail> dailyPlanDetails = instance.readValue(dailyPlanDetailsStr, new TypeReference<List<StrategyControlDetailList.DailyPlan.DailyPlanDetail>>() {
});
dailyPlan.setDailyPlanDetails(dailyPlanDetails); dailyPlan.setDailyPlanDetails(dailyPlanDetails);
dailyPlans.add(dailyPlan); dailyPlans.add(dailyPlan);
} }
...@@ -279,6 +322,10 @@ public class StrategyControlServiceImpl implements StrategyControlService { ...@@ -279,6 +322,10 @@ public class StrategyControlServiceImpl implements StrategyControlService {
planInfoEntity.setEndTime(plan.getEndTime()); planInfoEntity.setEndTime(plan.getEndTime());
planInfoEntity.setCompany(plan.getCompany()); planInfoEntity.setCompany(plan.getCompany());
planInfoEntity.setPlanDetails(mapper.writeValueAsString(plan.getPlanDetails())); planInfoEntity.setPlanDetails(mapper.writeValueAsString(plan.getPlanDetails()));
LambdaQueryWrapper<StrategyPlanInfoEntity> planDel = new LambdaQueryWrapper<>();
planDel.eq(StrategyPlanInfoEntity::getCrossId, plan.getCrossId());
planDel.eq(StrategyPlanInfoEntity::getPlanId, plan.getPlanId());
strategyPlanInfoMapper.delete(planDel);
strategyPlanInfoMapper.insert(planInfoEntity); strategyPlanInfoMapper.insert(planInfoEntity);
} }
} }
...@@ -318,7 +365,7 @@ public class StrategyControlServiceImpl implements StrategyControlService { ...@@ -318,7 +365,7 @@ public class StrategyControlServiceImpl implements StrategyControlService {
planInfoEntity.setCrossId(executePlan.getCrossId()); planInfoEntity.setCrossId(executePlan.getCrossId());
planInfoEntity.setPlanId(executePlan.getPlanId()); planInfoEntity.setPlanId(executePlan.getPlanId());
planInfoEntity.setType(executePlan.getType()); planInfoEntity.setType(executePlan.getType());
planInfoEntity.setCompany("神思"); planInfoEntity.setCompany("A厂商");
planInfoEntity.setStatus(executePlan.getStatus()); planInfoEntity.setStatus(executePlan.getStatus());
planInfoEntity.setStartTime(executePlan.getStartTime()); planInfoEntity.setStartTime(executePlan.getStartTime());
planInfoEntity.setEndTime(executePlan.getEndTime()); planInfoEntity.setEndTime(executePlan.getEndTime());
...@@ -326,7 +373,24 @@ public class StrategyControlServiceImpl implements StrategyControlService { ...@@ -326,7 +373,24 @@ public class StrategyControlServiceImpl implements StrategyControlService {
strategyPlanInfoMapper.insert(planInfoEntity); strategyPlanInfoMapper.insert(planInfoEntity);
StrategyControlVO strategyControlVO = convertDataList(list); StrategyControlVO strategyControlVO = convertDataList(list);
StrategyControlReq req = convertReq(strategyControlVO); StrategyControlReq req = convertReq(strategyControlVO);
log.error(JacksonUtils.getInstance().writeValueAsString(req));
List<StrategyControlDataReq> data = req.getData();
for (StrategyControlDataReq datum : data) {
StrategyControlDataEntity strategyControlDataEntity = new StrategyControlDataEntity();
strategyControlDataEntity.setBizId(datum.getBiz_id());
strategyControlDataEntity.setBizType(datum.getBiz_type());
strategyControlDataEntity.setStrategy(datum.getStrategy());
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
strategyControlDataEntity.setScheduleStart(simpleDateFormat.parse(datum.getSchedule_start()));
strategyControlDataEntity.setScheduleStart(simpleDateFormat.parse(datum.getSchedule_start()));
ObjectMapper instance = JacksonUtils.getInstance();
strategyControlDataEntity.setTime(instance.writeValueAsString(datum.getTime_table()));
strategyControlDataEntity.setFrequency(datum.getStrategy());
strategyControlDataEntity.setStatus(datum.getStatus());
strategyControlInfoMapper.insert(strategyControlDataEntity);
}
log.error("下发神思策略信息详情: {}", JacksonUtils.getInstance().writeValueAsString(req));
//Result result = pushStrategyControlService.push(req); //Result result = pushStrategyControlService.push(req);
Result result = new Result("200", "成功", null); Result result = new Result("200", "成功", null);
if (Objects.nonNull(result)) { if (Objects.nonNull(result)) {
...@@ -397,9 +461,9 @@ public class StrategyControlServiceImpl implements StrategyControlService { ...@@ -397,9 +461,9 @@ public class StrategyControlServiceImpl implements StrategyControlService {
List<StrategyControlDetailList.ExecutePlan.PlanDetail> planDetails = plan.getPlanDetails(); List<StrategyControlDetailList.ExecutePlan.PlanDetail> planDetails = plan.getPlanDetails();
if (!CollectionUtils.isEmpty(planDetails)) { if (!CollectionUtils.isEmpty(planDetails)) {
for (StrategyControlDetailList.ExecutePlan.PlanDetail planDetail : planDetails) { for (StrategyControlDetailList.ExecutePlan.PlanDetail planDetail : planDetails) {
Integer dailyPlanId = planDetail.getDailyPlanId();
List<Integer> weeks = planDetail.getWeeks();
for (StrategyPlanDTO strategyPlanDTO : strategyPlanDTOS) { for (StrategyPlanDTO strategyPlanDTO : strategyPlanDTOS) {
Integer dailyPlanId = planDetail.getDailyPlanId();
List<Integer> weeks = planDetail.getWeeks();
if (dailyPlanId == strategyPlanDTO.getDailyPlanId()) { if (dailyPlanId == strategyPlanDTO.getDailyPlanId()) {
strategyPlanDTO.setPlanId(planId); strategyPlanDTO.setPlanId(planId);
strategyPlanDTO.setStartTime(startTime); strategyPlanDTO.setStartTime(startTime);
...@@ -414,7 +478,7 @@ public class StrategyControlServiceImpl implements StrategyControlService { ...@@ -414,7 +478,7 @@ public class StrategyControlServiceImpl implements StrategyControlService {
} }
} }
List<StrategyControlDataVO> dataList = new ArrayList<>(); List<StrategyControlDataVO> dataList = new ArrayList<>();
for (StrategyPlanDTO strategyPlanDTO : strategyPlanDTOS) { for (StrategyPlanDTO strategyPlanDTO : resultList) {
StrategyControlDataVO dataVO = new StrategyControlDataVO(); StrategyControlDataVO dataVO = new StrategyControlDataVO();
dataVO.setBizId(strategyPlanDTO.getCrossId()); dataVO.setBizId(strategyPlanDTO.getCrossId());
dataVO.setBizType(0); dataVO.setBizType(0);
...@@ -446,4 +510,42 @@ public class StrategyControlServiceImpl implements StrategyControlService { ...@@ -446,4 +510,42 @@ public class StrategyControlServiceImpl implements StrategyControlService {
} }
return null; return null;
} }
@Override
public JsonViewObject strategyFactoryList() throws Exception {
List<StrategyFactoryEntity> strategyFactoryEntities = strategyFactoryMapper.selectList(null);
JsonViewObject jsonViewObject = JsonViewObject.newInstance();
jsonViewObject.success(strategyFactoryEntities);
return jsonViewObject;
}
@Override
public JsonViewObject strategyFactorySave(StrategyFactoryEntity entity) throws Exception {
JsonViewObject jsonViewObject = JsonViewObject.newInstance();
try {
if (Objects.nonNull(entity.getId())) {
strategyFactoryMapper.updateById(entity);
} else {
strategyFactoryMapper.insert(entity);
}
} catch (Exception e) {
log.error("策略库保存失败:{}", e);
jsonViewObject.success("策略库保存失败");
}
return jsonViewObject.success("策略库保存成功");
}
@Override
public JsonViewObject strategyFactoryDel(Integer id) throws Exception {
JsonViewObject jsonViewObject = JsonViewObject.newInstance();
try {
StrategyFactoryEntity strategyFactoryEntity = new StrategyFactoryEntity();
strategyFactoryEntity.setId(id);
strategyFactoryMapper.deleteById(strategyFactoryEntity);
} catch (Exception e) {
log.error("策略库策略删除失败:{}", e);
jsonViewObject.success("策略库策略删除失败");
}
return jsonViewObject.success("策略库删除成功");
}
} }
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="net.wanji.opt.dao.mapper.StrategyFactoryMapper">
</mapper>
\ No newline at end of file
...@@ -12,4 +12,6 @@ public interface BaseCrossTurnInfoMapper { ...@@ -12,4 +12,6 @@ public interface BaseCrossTurnInfoMapper {
List<String> selectLaneIds(String crossId, Integer dirCode, Integer intTurnCode); List<String> selectLaneIds(String crossId, Integer dirCode, Integer intTurnCode);
List<CrossTurnInfoPO> selectAll();
} }
...@@ -52,6 +52,10 @@ public class AbnormalCrossListVO { ...@@ -52,6 +52,10 @@ public class AbnormalCrossListVO {
private Integer isCongestion; private Integer isCongestion;
@ApiModelProperty(value = "拥堵指数") @ApiModelProperty(value = "拥堵指数")
private Double congestionIndex; private Double congestionIndex;
@ApiModelProperty(value = "失衡指数")
private Double unbalanceIndex;
@ApiModelProperty(value = "溢出指数")
private Double spilloverIndex;
@ApiModelProperty(value = "同比", notes = "同比增长率= (本期数 - 同期数) / 同期数 × 100%;同比:取上一周同一时段数据") @ApiModelProperty(value = "同比", notes = "同比增长率= (本期数 - 同期数) / 同期数 × 100%;同比:取上一周同一时段数据")
private Double lastWeekIndex; private Double lastWeekIndex;
@ApiModelProperty(value = "环比", notes = "增长率= (本期数 - 上期数) / 上期数 × 100%;环比:取上一时段数据") @ApiModelProperty(value = "环比", notes = "增长率= (本期数 - 上期数) / 上期数 × 100%;环比:取上一时段数据")
......
...@@ -18,4 +18,9 @@ ...@@ -18,4 +18,9 @@
where cross_id = #{crossId} and dir = #{dirCode} and turn = #{intTurnCode} where cross_id = #{crossId} and dir = #{dirCode} and turn = #{intTurnCode}
</select> </select>
<select id="selectAll" resultType="net.wanji.databus.po.CrossTurnInfoPO">
select <include refid="baseColumnList"></include>
from t_base_cross_turn_info
</select>
</mapper> </mapper>
...@@ -84,7 +84,7 @@ ...@@ -84,7 +84,7 @@
select select
t2.id, t2.name, t2.is_signal, t1.unbalance_dirs, t1.congestion_dirs, t1.spillover_dirs, t1.status as realtimeStatus, t2.id, t2.name, t2.is_signal, t1.unbalance_dirs, t1.congestion_dirs, t1.spillover_dirs, t1.status as realtimeStatus,
t1.start_time, t1.duration, t2.location as locationStr, t1.is_unbalance, t1.is_spillover, t1.is_congestion, t1.start_time, t1.duration, t2.location as locationStr, t1.is_unbalance, t1.is_spillover, t1.is_congestion,
t1.congestion_index, t1.batch_time t1.congestion_index, t1.unbalance_index, t1.spillover_index, t1.batch_time
from t_cross_data_realtime t1 JOIN t_base_cross_info t2 from t_cross_data_realtime t1 JOIN t_base_cross_info t2
on t1.cross_id = t2.id on t1.cross_id = t2.id
<where> <where>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment