Commit 9f5e6b61 by chenjunxiong

build(service):

parent b2d70c56
......@@ -21,27 +21,32 @@
<artifactId>chanjx-utils</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-activemq</artifactId>-->
<!--&lt;!&ndash; <version>1.5.22.RELEASE</version>&ndash;&gt;-->
<!-- </dependency>-->
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-module-hikvision</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.apache.activemq</groupId>-->
<!-- <artifactId>activemq-pool</artifactId>-->
<!-- </dependency>-->
<!--引入微服务启动依赖 starter
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-starter-cloud</artifactId>
</dependency>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-starter-job</artifactId>
</dependency>-->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-core</artifactId>
<version>5.7.0</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
</dependencies>
<build>
......
package org.jeecg.modules.demo.pm.config;
import org.jeecg.pm.hikvision.sdk.client.HikvisionBaseClient;
import org.jeecg.pm.hikvision.sdk.client.HikvisionClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* <p>
*
* </p>
*
* @author 陈俊雄
* @since 2022/3/25
*/
@Configuration
public class HikvisionConfig {
@Bean
public HikvisionClient hikvisionClient() {
return new HikvisionBaseClient("f9c1514b", "13bd31dbd3fe449e9e13f7ce6693677a");
}
}
......@@ -4,6 +4,19 @@ import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.demo.pm.entity.PmBuildingInfo;
import org.jeecg.pm.hikvision.sdk.client.HikvisionClient;
import org.jeecg.pm.hikvision.sdk.entity.body.vss.preview.HikvisiongetPreviewParamByCameraUuid;
import org.jeecg.pm.hikvision.sdk.entity.body.vss.res.HikvisionGetCamerasEx;
import org.jeecg.pm.hikvision.sdk.request.base.netzone.HikvisionGetNetZonesRequest;
import org.jeecg.pm.hikvision.sdk.request.vss.preview.HikvisionPreviewParamByCameraUuidRequest;
import org.jeecg.pm.hikvision.sdk.request.vss.res.HikvisionGetCamerasExRequest;
import org.jeecg.pm.hikvision.sdk.response.base.netzone.HikvisionGetNetZonesResponse;
import org.jeecg.pm.hikvision.sdk.response.vss.preview.HikvisionPreviewParamByCameraUuidResponse;
import org.jeecg.pm.hikvision.sdk.response.vss.res.HikvisionGetCamerasExResponse;
import org.jeecg.pm.hikvision.sdk.result.base.netzone.HikvisionGetNetZonesResult;
import org.jeecg.pm.hikvision.sdk.result.vss.preview.HikvisionPreviewParamByCameraUuidResult;
import org.jeecg.pm.hikvision.sdk.result.vss.res.HikvisionGetCamerasExResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
......@@ -25,6 +38,9 @@ import java.util.List;
@Slf4j
public class PmBuildingInfoController {
@Autowired
private HikvisionClient hikvisionClient;
private static final List<PmBuildingInfo> BUILDING_INFOS = Arrays.asList(
new PmBuildingInfo()
.setName("望海路1号楼")
......@@ -38,4 +54,19 @@ public class PmBuildingInfoController {
public Result<List<PmBuildingInfo>> list() {
return Result.OK(BUILDING_INFOS);
}
@GetMapping("/hik")
public Result<HikvisionPreviewParamByCameraUuidResult> hik() {
final HikvisionGetCamerasEx camerasEx = new HikvisionGetCamerasEx(1, 10);
final HikvisionGetCamerasExResponse camerasExResponse = hikvisionClient.execute(new HikvisionGetCamerasExRequest(camerasEx));
final HikvisionGetCamerasExResult camerasExResult = camerasExResponse.getResult();
final String cameraUuid = camerasExResult.getData().getList().get(0).getCameraUuid();
final HikvisionGetNetZonesResponse netZonesResponse = hikvisionClient.execute(new HikvisionGetNetZonesRequest());
final List<HikvisionGetNetZonesResult.NetZone> netZones = netZonesResponse.getResult().getData();
final HikvisionPreviewParamByCameraUuidResponse response = hikvisionClient.execute(
new HikvisionPreviewParamByCameraUuidRequest(
new HikvisiongetPreviewParamByCameraUuid(cameraUuid, netZones.get(0).getNetZoneUuid())));
return Result.OK(response.getResult());
}
}
package org.jeecg.modules.pm.config;
import com.google.protobuf.InvalidProtocolBufferException;
import org.jeecg.modules.pm.entity.eps.EventDis;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.annotation.JmsListener;
import javax.jms.BytesMessage;
import javax.jms.JMSException;
/**
* <p>
*
* </p>
*
* @author 陈俊雄
* @since 2022/3/29
*/
@Configuration
public class HikvisionMQ {
@JmsListener(destination = "openapi.vss.topic")
public void processMessage(BytesMessage bytesMessage) throws JMSException, InvalidProtocolBufferException {
final byte[] bytes = new byte[(int) bytesMessage.getBodyLength()];
bytesMessage.readBytes(bytes);
final EventDis.CommEventLog commEventLog = EventDis.CommEventLog.parseFrom(bytes);
System.out.println(commEventLog);
}
}
//package org.jeecg.modules.pm.handler;
//
//import org.apache.activemq.ActiveMQConnectionFactory;
//import org.apache.activemq.command.ActiveMQTopic;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.jms.annotation.EnableJms;
//import org.springframework.jms.listener.DefaultMessageListenerContainer;
//
//import javax.jms.ConnectionFactory;
//import javax.jms.Topic;
//
///**
// * @author: JJww
// * @Date:2022/3/25
// */
//@EnableJms
//@Configuration
//public class ActiveMqConfig {
//
//
// private final static String VSS_TOPIC = "openapi.vss.topic";
//
// private final static String EPS_TOPIC = "openapi.eps.topic";
//
// @Bean(name = "topic")
// public Topic topic() {
// return new ActiveMQTopic(VSS_TOPIC);
// }
//
// @Bean
// public ConnectionFactory connectionFactory() {
// return new ActiveMQConnectionFactory("tcp://172.16.16.2:61618");
// }
//
//
// @Bean
// public DefaultMessageListenerContainer defaultMessageListenerContainer(ConnectionFactory connectionFactory) {
// final DefaultMessageListenerContainer defaultMessageListenerContainer = new DefaultMessageListenerContainer();
// defaultMessageListenerContainer.setDestinationName(VSS_TOPIC);
// defaultMessageListenerContainer.setConnectionFactory(connectionFactory);
// defaultMessageListenerContainer.setMessageListener(vssMssageListener);
// defaultMessageListenerContainer.setPubSubDomain(true);
// return defaultMessageListenerContainer;
// }
//
//
// public ActiveMQConnectionFactory activeMQConnectionFactory(){
//
// }
//
//
//}
package org.jeecg.modules.pm.handler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.ErrorHandler;
/**
* @author: JJww
* @Date:2022/3/25
*/
@Slf4j
@Service
public class EventErrorHandler implements ErrorHandler {
@Override
public void handleError(Throwable t) {
log.error("Error in listener", t);
}
}
//package org.jeecg.modules.pm.handler;
//
//
//import com.google.protobuf.ByteString;
//import lombok.extern.slf4j.Slf4j;
//import org.jeecg.modules.pm.entity.eps.EventDis;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.jms.annotation.JmsListener;
//import org.springframework.jms.core.JmsMessagingTemplate;
//import org.springframework.stereotype.Component;
//
//import javax.jms.BytesMessage;
//import javax.jms.Message;
//
///**
// * @author: JJww
// * @Date:2022/3/23
// */
//@Slf4j
//@Component
//public class EventMessageListener {
//
// @JmsListener(destination = "openapi.vss.topic", containerFactory = "topicListener")
// public void vssMessageListener(Message msg) throws Exception {
//
// try {
// // cms里发送的消息为BytesMessage,此处不做判断亦可
// if (msg instanceof BytesMessage) {
// BytesMessage bytesMessage = (BytesMessage) msg;
// long length = bytesMessage.getBodyLength();
// byte[] bt = new byte[(int) length];
// // 将BytesMessage转换为byte类型
// bytesMessage.readBytes(bt);
// // 壳文件字段,EventDis类为event_dis.proto文件解析而来,CommEventLog类为事件壳文件类
// EventDis.CommEventLog parseFrom = EventDis.CommEventLog.parseFrom(bt);
// // 输出壳文件字段
// // System.out.println(parseFrom.toString());
// // 扩展字段,此字段为设备上报事件内容,部分事件需要使用pb文件再次解析
// ByteString extInfo = parseFrom.getExtInfo();
// // 输出扩展字段
// // System.out.println(extInfo.toStringUtf8());
// }
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
//
//}
package org.jeecg.modules.pm.handler;
import com.google.protobuf.ByteString;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.jeecg.modules.pm.entity.eps.EventDis;
import javax.jms.*;
/**
* @author: JJww
* @Date:2022/3/28
*/
public class VssMssageListener {
/**
* 10.33.47.176:61618和openapi.vss.topic可通过openapi【事件订阅接口】获得
*/
public static final String BROKER_URL = "failover:(tcp://172.16.16.2:61618)?timeout=2000";
/**
* 10.33.47.176:61618和openapi.vss.topic可通过openapi【事件订阅接口】获得
*/
public static final String TARGET = "openapi.vss.topic";
public static void run() {
Connection connection = null;
Session session = null;
try {
// 创建链接工厂
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(BROKER_URL);
// 通过工厂创建一个连接
connection = factory.createConnection();
// factory.createConnection(userName, password)
// 启动连接
connection.start();
// 第一个参数表示是否使用事务,第二个参数指定消息的确认模式
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Topic topic = session.createTopic(TARGET);
MessageConsumer consumer = session.createConsumer(topic);
// 消费者异步接收topic里的消息
consumer.setMessageListener(new MessageListener() {
public void onMessage(Message msg) {
try {
// cms里发送的消息为BytesMessage,此处不做判断亦可
if (msg instanceof BytesMessage) {
BytesMessage bytesMessage = (BytesMessage) msg;
long length = bytesMessage.getBodyLength();
byte[] bt = new byte[(int) length];
// 将BytesMessage转换为byte类型
bytesMessage.readBytes(bt);
// 壳文件字段,EventDis类为event_dis.proto文件解析而来,CommEventLog类为事件壳文件类
EventDis.CommEventLog parseFrom = EventDis.CommEventLog.parseFrom(bt);
// 输出壳文件字段
System.out.println(parseFrom.toString());
// 扩展字段,此字段为设备上报事件内容,部分事件需要使用pb文件再次解析
ByteString extInfo = parseFrom.getExtInfo();
// 输出扩展字段
System.out.println(extInfo.toStringUtf8());
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
System.out.println("ActiveMQ开始监听");
} catch (Exception e) {
e.printStackTrace();
}
}
}
\ No newline at end of file
......@@ -30,6 +30,7 @@ import org.jeecg.pm.hikvision.sdk.response.vss.res.HikvisionGetCamerasExResponse
import org.jeecg.pm.hikvision.sdk.response.vss.res.HikvisionGetEncodersResponse;
import org.jeecg.pm.hikvision.sdk.result.base.netzone.HikvisionGetNetZonesResult;
import org.jeecg.pm.hikvision.sdk.result.vss.playback.HikvisionGetRecordPlansByCameraUuidsResult;
import org.jeecg.pm.hikvision.sdk.result.vss.preview.HikvisionPreviewParamByCameraUuidResult;
import org.jeecg.pm.hikvision.sdk.result.vss.res.HikvisionGetCamerasExResult;
import org.junit.jupiter.api.Test;
......@@ -93,12 +94,12 @@ public class HikvisionSdkTest {
final HikvisionGetNetZonesResponse netZonesResponse = CLIENT.execute(new HikvisionGetNetZonesRequest());
final List<HikvisionGetNetZonesResult.NetZone> netZones = netZonesResponse.getResult().getData();
netZones.forEach(netZone -> {
final HikvisionPreviewParamByCameraUuidResponse response = CLIENT.execute(
new HikvisionPreviewParamByCameraUuidRequest(
new HikvisiongetPreviewParamByCameraUuid(cameraUuid, netZone.getNetZoneUuid())));
System.out.println(response.getResult());
});
final HikvisionPreviewParamByCameraUuidResponse response = CLIENT.execute(
new HikvisionPreviewParamByCameraUuidRequest(
new HikvisiongetPreviewParamByCameraUuid(cameraUuid, netZones.get(0).getNetZoneUuid())));
final HikvisionPreviewParamByCameraUuidResult result = response.getResult();
System.out.println(response.getResult());
}
@Test
......
<!DOCTYPE html>
<html lang="en">
<head>
<link href="https://vjs.zencdn.net/7.18.1/video-js.css" rel="stylesheet" />
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<div class="ActiveX">
<object classid="clsid:461284E8-135D-44B3-BD59-549150A773EC" id="spv" width="900px" height="600px"></object>
</div>
<script>
init();
<video
id="my-video"
class="video-js"
controls
preload="auto"
width="640"
height="264"
poster="MY_VIDEO_POSTER.jpg"
data-setup="{}">
<source src="MY_VIDEO.mp4" type="video/mp4" />
<source src="MY_VIDEO.webm" type="video/webm" />
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a
web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank"
>supports HTML5 video</a
>
</p>
</video>
<script src="https://vjs.zencdn.net/7.18.1/video.min.js"></script>
function init() {
let spvxOcx = document.getElementById("spv");
var ret = spvxOcx.SPV_StartPreview("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<previewInfo><camera guids=\"19052415352287106520_3\" encoderPwd=\"DdAPB9Ntuh0=\" encoderUserName=\"DYVQXYk=\" cameraChannelNum=\"1\" encoderModel=\"134742528\" cascade=\"0\" decodeTag=\"hikvision\" installPosition=\"0\" supportFishEye=\"0\" extraSupport=\"0\" url=\"rtsp://172.16.16.2:554/hikvision://172.16.16.232:8000:0:0?cnid=4&amp;pnid=4&amp;username=1&amp;password=1&amp;token=pt-1nldW16E9lQMGCF9ZdWEQt39nbBYhwbBh29w\" sysCode=\"ac95e3a8c51348c6b110358a0cb46b9a\" name=\"B-10F电梯厅\" id=\"260\"/><presetlist/><cruiselist/><server password=\"12345\" username=\"admin\" port=\"7302\" ip=\"172.16.16.2\" id=\"1\"/><vrmServer port=\"6300\" ip=\"172.16.16.2\"/><right ptzcfg=\"1\" ptzcontrol=\"1\" videoParamcfg=\"1\" record=\"1\"/><user locktime=\"30\" priority=\"100\" id=\"4\"/></previewInfo>");
}
</script>
</div>
</body>
</html>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-parent</artifactId>
<version>3.1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-parent</artifactId>
<version>3.1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-boot-module-system</artifactId>
<artifactId>jeecg-boot-module-system</artifactId>
<repositories>
<repository>
<id>aliyun</id>
<name>aliyun Repository</name>
<url>https://maven.aliyun.com/repository/public</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>jeecg</id>
<name>jeecg Repository</name>
<url>https://maven.jeecg.org/nexus/content/repositories/jeecg</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<repositories>
<repository>
<id>aliyun</id>
<name>aliyun Repository</name>
<url>https://maven.aliyun.com/repository/public</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>jeecg</id>
<name>jeecg Repository</name>
<url>https://maven.jeecg.org/nexus/content/repositories/jeecg</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-system-local-api</artifactId>
</dependency>
<!-- jeewx api -->
<dependency>
<groupId>org.jeecgframework</groupId>
<artifactId>jeewx-api</artifactId>
<version>1.4.7</version>
<exclusions>
<exclusion>
<artifactId>commons-beanutils</artifactId>
<groupId>commons-beanutils</groupId>
</exclusion>
<exclusion>
<artifactId>commons-lang</artifactId>
<groupId>commons-lang</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- 积木报表 -->
<dependency>
<groupId>org.jeecgframework.jimureport</groupId>
<artifactId>jimureport-spring-boot-starter</artifactId>
<version>1.4.32</version>
</dependency>
<dependencies>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-system-local-api</artifactId>
</dependency>
<!-- jeewx api -->
<dependency>
<groupId>org.jeecgframework</groupId>
<artifactId>jeewx-api</artifactId>
<version>1.4.7</version>
<exclusions>
<exclusion>
<artifactId>commons-beanutils</artifactId>
<groupId>commons-beanutils</groupId>
</exclusion>
<exclusion>
<artifactId>commons-lang</artifactId>
<groupId>commons-lang</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- 积木报表 -->
<dependency>
<groupId>org.jeecgframework.jimureport</groupId>
<artifactId>jimureport-spring-boot-starter</artifactId>
<version>1.4.32</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<!-- DEMO 示例模块【微服务启动请注释掉】 -->
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-module-demo</artifactId>
<version>3.1.0</version>
</dependency>
<!-- DEMO 示例模块【微服务启动请注释掉】 -->
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-module-demo</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!--微服务模式下修改为true,跳过此打包插件,否则微服务模块无法引用-->
<skip>false</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!--微服务模式下修改为true,跳过此打包插件,否则微服务模块无法引用-->
<skip>false</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>
......@@ -2,8 +2,6 @@ package org.jeecg;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.pm.handler.VssMssageListener;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
......@@ -20,7 +18,7 @@ import java.net.UnknownHostException;
*/
@Slf4j
@SpringBootApplication(exclude = {MongoAutoConfiguration.class})
public class JeecgSystemApplication extends SpringBootServletInitializer implements CommandLineRunner {
public class JeecgSystemApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
......@@ -33,7 +31,6 @@ public class JeecgSystemApplication extends SpringBootServletInitializer impleme
String ip = InetAddress.getLocalHost().getHostAddress();
String port = env.getProperty("server.port");
String path = oConvertUtils.getString(env.getProperty("server.servlet.context-path"));
VssMssageListener.run();
log.info("\n----------------------------------------------------------\n\t" +
"Application Jeecg-Boot is running! Access URLs:\n\t" +
"Local: \t\thttp://localhost:" + port + path + "/\n\t" +
......@@ -43,8 +40,5 @@ public class JeecgSystemApplication extends SpringBootServletInitializer impleme
}
@Override
public void run(String... args) throws Exception {
VssMssageListener.run();
}
}
......@@ -155,6 +155,11 @@ spring:
shutdown-timeout: 100ms
password: 123456
port: 6379
activemq:
broker-url: failover:(tcp://172.16.16.2:61618)?timeout=2000
jms:
pub-sub-domain: true
#mybatis plus 设置
mybatis-plus:
mapper-locations: classpath*:org/jeecg/modules/**/xml/*Mapper.xml
......
......@@ -137,6 +137,11 @@
<artifactId>jeecg-boot-module-system</artifactId>
<version>${jeecgboot.version}</version>
</dependency>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-module-hikvision</artifactId>
<version>${jeecgboot.version}</version>
</dependency>
<!-- jeecg tools -->
<dependency>
......@@ -297,6 +302,18 @@
<artifactId>chanjx-utils</artifactId>
<version>1.0.21</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-core</artifactId>
<version>5.7.0</version>
<!--<type>bundle</type>-->
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>4.0.0-rc-2</version>
<!--<type>bundle</type>-->
</dependency>
</dependencies>
</dependencyManagement>
......
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