Commit 97780abe authored by 赵啸非's avatar 赵啸非

修改pom文件

parent 479346c2
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
<version>1.0.0-SNAPSHOT</version> <version>1.0.0-SNAPSHOT</version>
</parent> </parent>
<properties>
<rabbitmq.version>4.8.0</rabbitmq.version>
</properties>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>com.mortals.framework</groupId> <groupId>com.mortals.framework</groupId>
...@@ -33,6 +37,23 @@ ...@@ -33,6 +37,23 @@
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
</dependency> </dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</dependency>
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>${rabbitmq.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId> <artifactId>commons-pool2</artifactId>
...@@ -62,6 +83,7 @@ ...@@ -62,6 +83,7 @@
<artifactId>javase</artifactId> <artifactId>javase</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
......
package com.mortals.xhx.common;
/**
* @author: zxfei
* @date: 2021/11/22 11:17
* @description:
**/
public class BrokerConfig {
}
package com.mortals.xhx.common.model;
import com.mortals.xhx.queue.TbQueueMsgHeaders;
import java.util.HashMap;
import java.util.Map;
/**
* 默认消息头
*
* @author: zxfei
* @date: 2021/11/22 11:14
*/
public class DefaultTbQueueMsgHeaders implements TbQueueMsgHeaders {
protected final Map<String, byte[]> data = new HashMap<>();
public DefaultTbQueueMsgHeaders() {
data.put(MessageHeader.TOPIC, new byte[]{});
data.put(MessageHeader.QOS, new byte[]{(byte) 0});
}
@Override
public byte[] put(String key, byte[] value) {
return data.put(key, value);
}
@Override
public byte[] get(String key) {
return data.get(key);
}
@Override
public Map<String, byte[]> getData() {
return data;
}
}
package com.mortals.xhx.common.model;
/**
* 消息头
*
* @author: zxfei
* @date: 2021/11/22 11:15
*/
public class MessageHeader {
/**
* 客户id
*/
public static final String CLIENTID = "clientId";
public static final String MESSAGEPROTOCOL = "protocol";
public static final String TIMESTAMP = "timestamp";
public static final String MESSAGETYPE = "messageType";
/**
* topic
*/
public static final String TOPIC = "topic";
public static final String QOS = "qos";
public static final String RETAIN = "retain";
public static final String WILL = "will";
public static final String DUP = "dup";
public static final String productKey = "dup";
// public static final String productKey = "dup";
}
package com.mortals.xhx.queue;
import com.alibaba.fastjson.JSONObject;
import lombok.Getter;
import lombok.extern.apachecommons.CommonsLog;
import org.slf4j.Logger;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 服务端消费消息服务
*
* @author: zxfei
* @date: 2021/11/22 11:31
*/
@CommonsLog
public class ConsumerService {
private long pollDuration;
protected volatile ExecutorService consumersExecutor;
@Getter
private TbQueueConsumer<TbQueueMsg> mainConsumer;
private String currentIp;
protected volatile boolean stopped = false;
public void init(TbQueueConsumer<TbQueueMsg> mainConsumer) {
this.consumersExecutor = Executors.newCachedThreadPool();
this.mainConsumer = mainConsumer;
launchMainConsumers();
this.mainConsumer.subscribe();
}
public ConsumerService(long pollDuration, String currentIp) {
this.pollDuration = pollDuration;
this.currentIp = currentIp;
}
/**
* 消费服务主线程
*/
protected void launchMainConsumers() {
consumersExecutor.submit(() -> {
while (!stopped) {
try {
//todo
List<TbQueueMsg> poll = mainConsumer.poll(pollDuration);
List<TbQueueMsg> msgs = poll;
if (msgs.isEmpty()) {
continue;
}
for (TbQueueMsg item : msgs) {
//todo
// Message innerMsg = new Message();
// TbQueueMsgHeaders headMap = item.getHeaders();
// int messageProtocl = headMap.get(MessageHeader.MESSAGEPROTOCOL)[0];
// Map<String, Object> headers = new HashMap<>();
// innerMsg.setPayload(item.getData());
// headers.put(MessageHeader.MESSAGEPROTOCOL, messageProtocl);
// innerMsg.setStoreTime(DateUtils.getCurrDate().getTime());
// if(messageProtocl== MsgTypeEnum.MSG_SYSTEM.getValue()){
// innerMsg.setHeaders(headers);
// sendSysMessage2Cluster(innerMsg);
// }else{
// String clientId = MixAll.convertByteS2Str(headMap.get(MessageHeader.CLIENTID));
// int messageType = headMap.get(MessageHeader.MESSAGETYPE)[0];
// String topic = MixAll.convertByteS2Str(headMap.get(MessageHeader.TOPIC));
// int qos = headMap.get(MessageHeader.QOS)[0];
//
// innerMsg.setClientId(clientId);
// innerMsg.setType(Message.Type.valueOf(messageType));
// headers.put(MessageHeader.TOPIC, topic);
// headers.put(MessageHeader.QOS, qos);
// headers.put(MessageHeader.RETAIN, false);
// headers.put(MessageHeader.DUP, false);
// innerMsg.setHeaders(headers);
// sendContrlMessage2Cluster(innerMsg);
// }
}
} catch (Exception e) {
log.error("Exception", e);
}
}
log.info("Queue Consumer stopped.");
});
}
public void destroy() {
if (!stopped) {
stopMainConsumers();
}
stopped = true;
if (consumersExecutor != null) {
consumersExecutor.shutdownNow();
}
}
protected void stopMainConsumers() {
if (mainConsumer != null) {
mainConsumer.unsubscribe();
}
}
}
package com.mortals.xhx.queue;
import com.mortals.xhx.queue.processing.AbstractConsumerService;
import com.mortals.xhx.queue.provider.TbCoreQueueFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.List;
@Service
@Slf4j
public class DefaultTbCoreConsumerService extends AbstractConsumerService<TbQueueMsg> implements TbCoreConsumerService {
@Value("${queue.core.poll-interval}")
private long pollDuration;
@Value("${queue.core.pack-processing-timeout}")
private long packProcessingTimeout;
private TbQueueConsumer<TbQueueMsg> mainConsumer;
public DefaultTbCoreConsumerService(TbCoreQueueFactory tbCoreQueueFactory) {
this.mainConsumer = tbCoreQueueFactory.createMsgConsumer();
}
@PostConstruct
public void init() {
log.info("初始化消费服务线程");
super.init("core-consumer");
// super.init("tb-core-consumer", "tb-core-notifications-consumer");
}
@PreDestroy
public void destroy() {
super.destroy();
}
@EventListener(ApplicationReadyEvent.class)
@Order(value = 2)
public void onApplicationEvent(ApplicationReadyEvent event) {
super.onApplicationEvent(event);
}
@Override
protected void launchMainConsumers() {
log.info("启动消费线程!");
consumersExecutor.submit(() -> {
while (!stopped) {
try {
List<TbQueueMsg> msgs = mainConsumer.poll(pollDuration);
if (msgs.isEmpty()) {
continue;
}
for (TbQueueMsg item:msgs){
log.info("msg:"+item.toString());
}
mainConsumer.commit();
} catch (Exception e) {
if (!stopped) {
log.warn("Failed to obtain messages from queue.", e);
try {
Thread.sleep(pollDuration);
} catch (InterruptedException e2) {
log.trace("Failed to wait until the server has capacity to handle new requests", e2);
}
}
}
}
log.info(" Core Consumer stopped.");
});
}
@Override
public void onApplicationEvent(ApplicationEvent applicationEvent) {
}
private static class PendingMsgHolder {
// @Getter
// @Setter
// private volatile ToCoreMsg toCoreMsg;
}
@Override
protected void stopMainConsumers() {
if (mainConsumer != null) {
mainConsumer.unsubscribe();
}
}
}
package com.mortals.xhx.queue;
import com.mortals.xhx.common.model.DefaultTbQueueMsgHeaders;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.UUID;
/**
* 默认消息
*
* @author: zxfei
* @date: 2021/11/22 10:59
*/
@Data
@AllArgsConstructor
public class DefaultTbQueueMsg implements TbQueueMsg {
private final UUID key;
private final byte[] data;
private final TbQueueMsgHeaders headers;
public DefaultTbQueueMsg(TbQueueMsg msg) {
this.key = msg.getKey();
this.data = msg.getData();
TbQueueMsgHeaders headers = new DefaultTbQueueMsgHeaders();
msg.getHeaders().getData().forEach(headers::put);
this.headers = headers;
}
}
package com.mortals.xhx.queue;
import com.mortals.xhx.common.BrokerConfig;
/**
* 消息队列工厂类,初始化MQ类型(kafka,rabbitMQ,memory)
*
* @author: zxfei
* @date: 2021/11/22 10:57
*/
public interface MessageQueueFactory {
/**
* 创建消息生产者
* @return
*/
TbQueueProducer<TbQueueMsg> createMsgProducer(BrokerConfig brokerConfig);
/**
* 创建消息消费者
* @return
*/
TbQueueConsumer<TbQueueMsg> createMsgConsumer(BrokerConfig brokerConfig);
}
package com.mortals.xhx.queue;
import org.springframework.context.ApplicationListener;
public interface TbCoreConsumerService extends ApplicationListener {
}
package com.mortals.xhx.queue;
/**
* 队列回调消息
*
* @author: zxfei
* @date: 2021/11/22 10:57
*/
public interface TbQueueCallback {
void onSuccess(TbQueueMsgMetadata metadata);
void onFailure(Throwable t);
}
package com.mortals.xhx.queue;
import java.util.List;
import java.util.Set;
/**
* 队列消息消费者接口
*
* @author: zxfei
* @date: 2021/11/22 10:57
*/
public interface TbQueueConsumer<T extends TbQueueMsg> {
/**
* 获取当topic
* @return
*/
String getTopic();
/**
* 订阅
*/
void subscribe();
/**
* 订阅(分区)
* @param partitions
*/
void subscribe(Set<TopicPartitionInfo> partitions);
/**
* 取消订阅
*/
void unsubscribe();
/**
* 拉取消息间隔
* @param durationInMillis
* @return
*/
List<T> poll(long durationInMillis);
/**
* 提交
*/
void commit();
}
package com.mortals.xhx.queue;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Data
@Component
public class TbQueueCoreSettings {
@Value("${queue.core.topic}")
private String topic;
@Value("${queue.core.partitions}")
private int partitions;
}
package com.mortals.xhx.queue;
import java.util.UUID;
/**
* 队列消息体
*
* @author: zxfei
* @date: 2021/11/22 10:56
*/
public interface TbQueueMsg {
UUID getKey();
TbQueueMsgHeaders getHeaders();
byte[] getData();
}
package com.mortals.xhx.queue;
public interface TbQueueMsgDecoder<T extends TbQueueMsg> {
T decode(TbQueueMsg msg);
}
package com.mortals.xhx.queue;
import java.util.Map;
/**
* 消息头信息
*
* @author: zxfei
* @date: 2021/11/22 10:56
*/
public interface TbQueueMsgHeaders {
byte[] put(String key, byte[] value);
byte[] get(String key);
Map<String, byte[]> getData();
}
package com.mortals.xhx.queue;
/**
* 队列消息元数据
*
* @author: zxfei
* @date: 2021/11/22 10:56
*/
public interface TbQueueMsgMetadata {
}
package com.mortals.xhx.queue;
/**
* 队列消息生产者
*
* @author: zxfei
* @date: 2021/11/22 10:55
*/
public interface TbQueueProducer<T extends TbQueueMsg> {
void init();
String getDefaultTopic();
//发送消息
void send(TopicPartitionInfo tpi, T msg, TbQueueCallback callback);
void stop();
}
package com.mortals.xhx.queue;
import lombok.Builder;
import lombok.Data;
import java.util.Objects;
import java.util.Optional;
@Data
public class TopicPartitionInfo {
private String topic;
private Integer partition;
private String fullTopicName;
@Builder
public TopicPartitionInfo(String topic, Integer partition) {
this.topic = topic;
this.partition = partition;
String tmp = topic;
if (partition != null) {
tmp += "." + partition;
}
this.fullTopicName = tmp;
}
public TopicPartitionInfo newByTopic(String topic) {
return new TopicPartitionInfo(topic, this.partition);
}
public String getTopic() {
return topic;
}
public Optional<Integer> getPartition() {
return Optional.ofNullable(partition);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TopicPartitionInfo that = (TopicPartitionInfo) o;
return topic.equals(that.topic) &&
Objects.equals(partition, that.partition) &&
fullTopicName.equals(that.fullTopicName);
}
@Override
public int hashCode() {
return Objects.hash(fullTopicName);
}
}
package com.mortals.xhx.queue.kafka;
import com.mortals.xhx.queue.TbQueueConsumer;
import com.mortals.xhx.queue.TbQueueMsg;
import com.mortals.xhx.queue.TopicPartitionInfo;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
import static java.util.Collections.emptyList;
/**
* 抽象队列消费者模板
*
* @author: zxfei
* @date: 2021/11/22 11:12
*/
@Slf4j
public abstract class AbstractTbQueueConsumerTemplate<R, T extends TbQueueMsg> implements TbQueueConsumer<T> {
private volatile boolean subscribed;
protected volatile boolean stopped = false;
protected volatile Set<TopicPartitionInfo> partitions;
protected final ReentrantLock consumerLock = new ReentrantLock();
final Queue<Set<TopicPartitionInfo>> subscribeQueue = new ConcurrentLinkedQueue<>();
@Getter
private final String topic;
public AbstractTbQueueConsumerTemplate(String topic) {
this.topic = topic;
}
@Override
public void subscribe() {
log.info("enqueue topic subscribe {} ", topic);
if (stopped) {
log.error("trying subscribe, but consumer stopped for topic {}", topic);
return;
}
subscribeQueue.add(Collections.singleton(new TopicPartitionInfo(topic, null)));
}
@Override
public void subscribe(Set<TopicPartitionInfo> partitions) {
log.info("enqueue topics subscribe {} ", partitions);
if (stopped) {
log.error("trying subscribe, but consumer stopped for topic {}", topic);
return;
}
subscribeQueue.add(partitions);
}
@Override
public List<T> poll(long durationInMillis) {
List<R> records;
long startNanos = System.nanoTime();
if (stopped) {
return errorAndReturnEmpty();
}
if (!subscribed && partitions == null && subscribeQueue.isEmpty()) {
return sleepAndReturnEmpty(startNanos, durationInMillis);
}
if (consumerLock.isLocked()) {
log.error("poll. consumerLock is locked. will wait with no timeout. it looks like a race conditions or deadlock", new RuntimeException("stacktrace"));
}
consumerLock.lock();
try {
//更新订阅的主题
while (!subscribeQueue.isEmpty()) {
subscribed = false;
partitions = subscribeQueue.poll();
}
if (!subscribed) {
List<String> topicNames = partitions.stream().map(TopicPartitionInfo::getFullTopicName).collect(Collectors.toList());
doSubscribe(topicNames);
subscribed = true;
}
records = partitions.isEmpty() ? emptyList() : doPoll(durationInMillis);
} finally {
consumerLock.unlock();
}
if (records.isEmpty()) {
return sleepAndReturnEmpty(startNanos, durationInMillis);
}
return decodeRecords(records);
}
List<T> decodeRecords(List<R> records) {
List<T> result = new ArrayList<>(records.size());
records.forEach(record -> {
try {
if (record != null) {
result.add(decode(record));
}
} catch (IOException e) {
log.error("Failed decode record: [{}]", record);
throw new RuntimeException("Failed to decode record: ", e);
}
});
return result;
}
List<T> errorAndReturnEmpty() {
log.error("poll invoked but consumer stopped for topic:" + topic, new RuntimeException("stacktrace"));
return emptyList();
}
List<T> sleepAndReturnEmpty(final long startNanos, final long durationInMillis) {
long durationNanos = TimeUnit.MILLISECONDS.toNanos(durationInMillis);
long spentNanos = System.nanoTime() - startNanos;
if (spentNanos < durationNanos) {
try {
Thread.sleep(Math.max(TimeUnit.NANOSECONDS.toMillis(durationNanos - spentNanos), 1));
} catch (InterruptedException e) {
if (!stopped) {
log.error("Failed to wait", e);
}
}
}
return emptyList();
}
@Override
public void commit() {
if (consumerLock.isLocked()) {
log.error("commit. consumerLock is locked. will wait with no timeout. it looks like a race conditions or deadlock", new RuntimeException("stacktrace"));
}
consumerLock.lock();
try {
doCommit();
} finally {
consumerLock.unlock();
}
}
@Override
public void unsubscribe() {
log.info("unsubscribe topic and stop consumer {}", getTopic());
stopped = true;
consumerLock.lock();
try {
doUnsubscribe();
} finally {
consumerLock.unlock();
}
}
abstract protected List<R> doPoll(long durationInMillis);
abstract protected T decode(R record) throws IOException;
abstract protected void doSubscribe(List<String> topicNames);
abstract protected void doCommit();
abstract protected void doUnsubscribe();
}
package com.mortals.xhx.queue.kafka;
import com.mortals.xhx.common.model.DefaultTbQueueMsgHeaders;
import com.mortals.xhx.queue.TbQueueMsg;
import com.mortals.xhx.queue.TbQueueMsgHeaders;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import java.util.UUID;
public class KafkaTbQueueMsg implements TbQueueMsg {
private final UUID key;
private final TbQueueMsgHeaders headers;
private final byte[] data;
public KafkaTbQueueMsg(ConsumerRecord<String, byte[]> record) {
this.key = UUID.fromString(record.key());
TbQueueMsgHeaders headers = new DefaultTbQueueMsgHeaders();
record.headers().forEach(header -> {
headers.put(header.key(), header.value());
});
this.headers = headers;
this.data = record.value();
}
@Override
public UUID getKey() {
return key;
}
@Override
public TbQueueMsgHeaders getHeaders() {
return headers;
}
@Override
public byte[] getData() {
return data;
}
}
package com.mortals.xhx.queue.kafka;
import com.mortals.xhx.queue.TbQueueMsgMetadata;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.kafka.clients.producer.RecordMetadata;
/**
* 队列元数据
*
* @author: zxfei
* @date: 2021/11/22 14:40
*/
@Data
@AllArgsConstructor
public class KafkaTbQueueMsgMetadata implements TbQueueMsgMetadata {
private RecordMetadata metadata;
}
package com.mortals.xhx.queue.kafka;
import com.mortals.xhx.queue.TbQueueMsg;
import lombok.Builder;
import lombok.extern.apachecommons.CommonsLog;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.slf4j.Logger;
import java.io.IOException;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
/**
* kafka consumer 消费者模板
*
* @author: zxfei
* @date: 2021/11/22 11:21
*/
@Slf4j
public class TbKafkaConsumerTemplate<T extends TbQueueMsg> extends AbstractTbQueueConsumerTemplate<ConsumerRecord<String, byte[]>, T> {
private final KafkaConsumer<String, byte[]> consumer;
private final String groupId;
private final TbKafkaDecoder<T> decoder;
@Builder
private TbKafkaConsumerTemplate(TbKafkaSettings settings, String clientId, TbKafkaDecoder<T> decoder, String groupId, String topic) {
//默认topic
super(topic);
Properties props = settings.toConsumerProps();
//多个输入源的时候 需要配置
//props.put(ConsumerConfig.CLIENT_ID_CONFIG, clientId);
if (groupId != null) {
props.put(ConsumerConfig.GROUP_ID_CONFIG, groupId);
}
this.groupId = groupId;
this.consumer = new KafkaConsumer<>(props);
this.decoder = decoder;
}
@Override
protected void doSubscribe(List<String> topicNames) {
if (!topicNames.isEmpty()) {
// topicNames.forEach(admin::createTopicIfNotExists);
log.info("subscribe topics {}", topicNames);
consumer.subscribe(topicNames);
} else {
log.info("unsubscribe due to empty topic list");
consumer.unsubscribe();
}
}
@Override
protected List<ConsumerRecord<String, byte[]>> doPoll(long durationInMillis) {
ConsumerRecords<String, byte[]> records = consumer.poll(Duration.ofMillis(durationInMillis));
records.forEach(record -> {
System.out.printf("topic = %s ,partition = %d,offset = %d, key = %s, value = %s%n", record.topic(), record.partition(),
record.offset(), record.key(), record.value());
});
if (records.isEmpty()) {
return Collections.emptyList();
} else {
List<ConsumerRecord<String, byte[]>> recordList = new ArrayList<>(256);
records.forEach(recordList::add);
return recordList;
}
}
@Override
public T decode(ConsumerRecord<String, byte[]> record) throws IOException {
return decoder.decode(new KafkaTbQueueMsg(record));
}
@Override
protected void doCommit() {
//同步提交,线程会阻塞,直到当前批次offset提交成功
consumer.commitAsync();
}
@Override
protected void doUnsubscribe() {
log.info("unsubscribe topic and close consumer for topic {}", getTopic());
if (consumer != null) {
//consumer.unsubscribe();
consumer.close();
}
}
public static void main(String[] args) {
// TbKafkaConsumerTemplate.builder().
}
}
package com.mortals.xhx.queue.kafka;
import com.mortals.xhx.queue.TbQueueMsg;
import java.io.IOException;
/**
* 队列消息编码
*
* @author: zxfei
* @date: 2021/11/22 11:22
*/
public interface TbKafkaDecoder<T extends TbQueueMsg> {
T decode(TbQueueMsg msg) throws IOException;
}
package com.mortals.xhx.queue.kafka;
import com.mortals.xhx.queue.TbQueueCallback;
import com.mortals.xhx.queue.TbQueueMsg;
import com.mortals.xhx.queue.TbQueueProducer;
import com.mortals.xhx.queue.TopicPartitionInfo;
import lombok.Builder;
import lombok.Data;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.header.Header;
import org.apache.kafka.common.header.internals.RecordHeader;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
* kafka 生产者模板
*
* @author: zxfei
* @date: 2021/11/22 11:23
*/
@Data
@Slf4j
public class TbKafkaProducerTemplate<T extends TbQueueMsg> implements TbQueueProducer<T> {
/**
* 生产者
*/
private KafkaProducer<String, byte[]> producer;
/**
* kafka 配置信息
*/
private TbKafkaSettings settings;
private String defaultTopic;
/**
* topic组
*/
private Set<TopicPartitionInfo> topics;
@Builder
private TbKafkaProducerTemplate(TbKafkaSettings settings,String defaultTopic) {
this.settings = settings;
//初始化生产者参数
this.producer = new KafkaProducer<>(settings.toProducerProps());
this.defaultTopic = defaultTopic;
topics = ConcurrentHashMap.newKeySet();
}
@Override
public void init() {
}
@Override
public void send(TopicPartitionInfo tpi, T msg, TbQueueCallback callback) {
String key = msg.getKey().toString();
byte[] data = msg.getData();
ProducerRecord<String, byte[]> record;
if (tpi.getTopic() == null) {
tpi.setTopic(this.defaultTopic);
}
Iterable<Header> headers = msg.getHeaders().getData().entrySet().stream().map(e -> new RecordHeader(e.getKey(), e.getValue())).collect(Collectors.toList());
record = new ProducerRecord<>(tpi.getTopic(), null, key, data, headers);
producer.send(record, (metadata, exception) -> {
if (exception == null) {
if (callback != null) {
callback.onSuccess(new KafkaTbQueueMsgMetadata(metadata));
}
} else {
if (callback != null) {
callback.onFailure(exception);
} else {
log.warn("Producer template failure: {}", exception.getMessage(), exception);
}
}
});
}
@Override
public void stop() {
if (producer != null) {
producer.close();
}
}
}
package com.mortals.xhx.queue.kafka;
import lombok.Data;
/**
* 其它配置类
*
* @author: zxfei
* @date: 2021/11/22 13:31
*/
@Data
public class TbKafkaProperty {
private String key;
private String value;
}
package com.mortals.xhx.queue.kafka;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.CommonClientConfigs;
import org.apache.kafka.clients.admin.AdminClientConfig;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.common.serialization.ByteArrayDeserializer;
import org.apache.kafka.common.serialization.ByteArraySerializer;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.apache.kafka.common.serialization.StringSerializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Properties;
/**
* kafka 配置类
*
* @author: zxfei
* @date: 2021/11/22 13:30
*/
@Slf4j
@ConditionalOnProperty(prefix = "queue", value = "type", havingValue = "kafka")
@ConfigurationProperties(prefix = "queue.kafka")
@Component
public class TbKafkaSettings {
@Value("${queue.kafka.bootstrap.servers}")
private String servers;
@Value("${queue.kafka.acks}")
private String acks;
@Value("${queue.kafka.retries}")
private int retries;
@Value("${queue.kafka.batch.size}")
private int batchSize;
@Value("${queue.kafka.linger.ms}")
private long lingerMs;
@Value("${queue.kafka.buffer.memory}")
private long bufferMemory;
@Value("${queue.kafka.replication_factor}")
@Getter
private short replicationFactor;
@Value("${queue.kafka.max_poll_records:8192}")
private int maxPollRecords;
@Value("${queue.kafka.max_poll_interval_ms:300000}")
private int maxPollIntervalMs;
@Value("${queue.kafka.max_partition_fetch_bytes:16777216}")
private int maxPartitionFetchBytes;
@Value("${queue.kafka.fetch_max_bytes:134217728}")
private int fetchMaxBytes;
@Setter
private List<TbKafkaProperty> other;
/**
* 管理端参数配置
* @return
*/
public Properties toAdminProps() {
Properties props = toProps();
props.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, servers);
props.put(AdminClientConfig.RETRIES_CONFIG, retries);
return props;
}
/**
* 消费者参数
*
* @return
*/
public Properties toConsumerProps() {
Properties props = toProps();
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, servers);
props.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, maxPollRecords);
props.put(ConsumerConfig.MAX_PARTITION_FETCH_BYTES_CONFIG, maxPartitionFetchBytes);
props.put(ConsumerConfig.FETCH_MAX_BYTES_CONFIG, fetchMaxBytes);
props.put(ConsumerConfig.MAX_POLL_INTERVAL_MS_CONFIG, maxPollIntervalMs);
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, ByteArrayDeserializer.class);
return props;
}
/**
* 生产者参数
*
* @return
*/
public Properties toProducerProps() {
Properties props = toProps();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, servers);
props.put(ProducerConfig.RETRIES_CONFIG, retries);
props.put(ProducerConfig.ACKS_CONFIG, acks);
props.put(ProducerConfig.BATCH_SIZE_CONFIG, batchSize);
props.put(ProducerConfig.LINGER_MS_CONFIG, lingerMs);
props.put(ProducerConfig.BUFFER_MEMORY_CONFIG, bufferMemory);
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, ByteArraySerializer.class);
return props;
}
private Properties toProps() {
Properties props = new Properties();
//添加其它参数
if (other != null) {
other.forEach(kv -> props.put(kv.getKey(), kv.getValue()));
}
return props;
}
}
package com.mortals.xhx.queue.processing;
import com.mortals.xhx.queue.TbQueueMsg;
import com.mortals.xhx.utils.IotThreadFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import javax.annotation.PreDestroy;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Slf4j
public abstract class AbstractConsumerService<N extends TbQueueMsg> {
protected volatile ExecutorService consumersExecutor;
protected volatile boolean stopped = false;
public void init(String mainConsumerThreadName) {
this.consumersExecutor = Executors.newCachedThreadPool(IotThreadFactory.forName(mainConsumerThreadName));
}
@EventListener(ApplicationReadyEvent.class)
@Order(value = 2)
public void onApplicationEvent(ApplicationReadyEvent event) {
launchMainConsumers();
}
/**
* 启动消费主线程服务
*/
protected abstract void launchMainConsumers();
/**
* 停止消费主线程服务
*/
protected abstract void stopMainConsumers();
@PreDestroy
public void destroy() {
stopped = true;
stopMainConsumers();
if (consumersExecutor != null) {
consumersExecutor.shutdownNow();
}
}
}
package com.mortals.xhx.queue.provider;
import com.mortals.xhx.queue.TbQueueConsumer;
import com.mortals.xhx.queue.TbQueueMsg;
import com.mortals.xhx.queue.TbQueueProducer;
import com.mortals.xhx.queue.kafka.TbKafkaConsumerTemplate;
import com.mortals.xhx.queue.kafka.TbKafkaProducerTemplate;
import com.mortals.xhx.queue.kafka.TbKafkaSettings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Component;
/**
* kafka 消息工厂类
*
* @author: zxfei
* @date: 2021/11/22 15:00
*/
@Component
@ConditionalOnExpression("'${queue.type:null}'=='kafka'")
public class KafkaTbCoreQueueFactory implements TbCoreQueueFactory {
@Autowired
private TbKafkaSettings kafkaSettings;
/**
* 初始化创建消息生产者
*
* @return
*/
@Override
public TbQueueProducer<TbQueueMsg> createMsgProducer() {
TbKafkaProducerTemplate.TbKafkaProducerTemplateBuilder<TbQueueMsg> builder = TbKafkaProducerTemplate.builder();
builder.settings(kafkaSettings);
return builder.build();
}
/**
* 初始化创建消息消费者
*
* @return
*/
@Override
public TbQueueConsumer<TbQueueMsg> createMsgConsumer() {
TbKafkaConsumerTemplate.TbKafkaConsumerTemplateBuilder<TbQueueMsg> comsumerBuilder = TbKafkaConsumerTemplate.builder();
comsumerBuilder.settings(kafkaSettings);
return comsumerBuilder.build();
}
}
package com.mortals.xhx.queue.provider;
import com.mortals.xhx.queue.*;
import com.mortals.xhx.queue.rabbitmq.TbRabbitMqConsumerTemplate;
import com.mortals.xhx.queue.rabbitmq.TbRabbitMqProducerTemplate;
import com.mortals.xhx.queue.rabbitmq.TbRabbitMqSettings;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Component;
import java.util.UUID;
@Component
@ConditionalOnExpression("'${queue.type:null}'=='rabbitmq'")
public class RabbitMqTbCoreQueueFactory implements TbCoreQueueFactory {
private final TbRabbitMqSettings rabbitMqSettings;
private final TbQueueCoreSettings coreSettings;
public RabbitMqTbCoreQueueFactory(TbRabbitMqSettings rabbitMqSettings, TbQueueCoreSettings coreSettings) {
this.rabbitMqSettings = rabbitMqSettings;
this.coreSettings = coreSettings;
}
@Override
public TbQueueProducer<TbQueueMsg> createMsgProducer() {
return new TbRabbitMqProducerTemplate<>(rabbitMqSettings, coreSettings.getTopic());
}
@Override
public TbQueueConsumer<TbQueueMsg> createMsgConsumer() {
return new TbRabbitMqConsumerTemplate<>(rabbitMqSettings, coreSettings.getTopic(), msg -> new TbQueueMsg() {
@Override
public UUID getKey() {
return msg.getKey();
}
@Override
public TbQueueMsgHeaders getHeaders() {
return msg.getHeaders();
}
@Override
public byte[] getData() {
return msg.getData();
}
});
}
}
package com.mortals.xhx.queue.provider;
import com.mortals.xhx.queue.TbQueueConsumer;
import com.mortals.xhx.queue.TbQueueMsg;
import com.mortals.xhx.queue.TbQueueProducer;
public interface TbCoreQueueFactory {
/**
* 消息生产者
* @return
*/
TbQueueProducer<TbQueueMsg> createMsgProducer();
/**
* 消息消费服务
* @return
*/
TbQueueConsumer<TbQueueMsg> createMsgConsumer();
}
package com.mortals.xhx.queue.provider;
import com.mortals.xhx.queue.TbQueueMsg;
import com.mortals.xhx.queue.TbQueueProducer;
import lombok.extern.apachecommons.CommonsLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
/**
* 初始化消息生产者服务
*/
@CommonsLog
@Service
public class TbCoreQueueProducerProvider implements TbQueueProducerProvider {
/**
* 消息队列提供
*/
@Autowired
private TbCoreQueueFactory tbQueueProvider;
/**
* 消息队列生产者
*/
private TbQueueProducer<TbQueueMsg> queueProducer;
// public TbCoreQueueProducerProvider(TbCoreQueueFactory tbQueueProvider) {
// this.tbQueueProvider = tbQueueProvider;
// }
//
@PostConstruct
public void init() {
log.info("消息队列生产服务开始...");
this.queueProducer = tbQueueProvider.createMsgProducer();
}
@Override
public TbQueueProducer<TbQueueMsg> getTbCoreMsgProducer() {
return queueProducer;
}
}
package com.mortals.xhx.queue.provider;
import com.mortals.xhx.queue.TbQueueMsg;
import com.mortals.xhx.queue.TbQueueProducer;
/**
* 消息队列提供接口
*
* @author: zxfei
* @date: 2021/11/22 14:59
*/
public interface TbQueueProducerProvider {
/**
* 消息生产者
* @return
*/
TbQueueProducer<TbQueueMsg> getTbCoreMsgProducer();
}
package com.mortals.xhx.queue.rabbitmq;
import com.alibaba.fastjson.JSON;
import com.mortals.xhx.queue.DefaultTbQueueMsg;
import com.mortals.xhx.queue.TbQueueMsg;
import com.mortals.xhx.queue.TbQueueMsgDecoder;
import com.mortals.xhx.queue.TopicPartitionInfo;
import com.mortals.xhx.queue.kafka.AbstractTbQueueConsumerTemplate;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.GetResponse;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
@Slf4j
public class TbRabbitMqConsumerTemplate<T extends TbQueueMsg> extends AbstractTbQueueConsumerTemplate<GetResponse, T> {
private final TbQueueMsgDecoder<T> decoder;
private Channel channel;
private Connection connection;
private volatile Set<String> queues;
public TbRabbitMqConsumerTemplate(TbRabbitMqSettings rabbitMqSettings, String topic, TbQueueMsgDecoder<T> decoder) {
super(topic);
this.decoder = decoder;
try {
connection = rabbitMqSettings.getConnectionFactory().newConnection();
channel = connection.createChannel();
} catch (IOException | TimeoutException e) {
log.error("Failed to create connection." , e);
// throw new RuntimeException("Failed to create connection." , e);
}
stopped = false;
}
@Override
protected List<GetResponse> doPoll(long durationInMillis) {
List<GetResponse> result = queues.stream()
.map(queue -> {
try {
return channel.basicGet(queue, false);
} catch (IOException e) {
log.error("Failed to get messages from queue: [{}]" , queue);
return null;
// throw new RuntimeException("Failed to get messages from queue." , e);
}
}).filter(Objects::nonNull).collect(Collectors.toList());
if (result.size() > 0) {
return result;
} else {
return Collections.emptyList();
}
}
@Override
protected void doSubscribe(List<String> topicNames) {
queues = partitions.stream()
.map(TopicPartitionInfo::getFullTopicName)
.collect(Collectors.toSet());
//queues.forEach(admin::createTopicIfNotExists);
}
@Override
protected void doCommit() {
try {
channel.basicAck(0, true);
} catch (IOException e) {
log.error("Failed to ack messages." , e);
}
}
@Override
protected void doUnsubscribe() {
if (channel != null) {
try {
channel.close();
} catch (IOException | TimeoutException e) {
log.error("Failed to close the channel.");
}
}
if (connection != null) {
try {
connection.close();
} catch (IOException e) {
log.error("Failed to close the connection.");
}
}
}
public T decode(GetResponse message) {
DefaultTbQueueMsg msg = JSON.parseObject(new String(message.getBody()), DefaultTbQueueMsg.class);
return decoder.decode(msg);
}
}
package com.mortals.xhx.queue.rabbitmq;
import com.alibaba.fastjson.JSON;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.mortals.xhx.queue.*;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeoutException;
@Slf4j
public class TbRabbitMqProducerTemplate<T extends TbQueueMsg> implements TbQueueProducer<T> {
private String defaultTopic;
private TbRabbitMqSettings rabbitMqSettings;
private ListeningExecutorService producerExecutor;
private Channel channel;
private Connection connection;
private final Set<TopicPartitionInfo> topics = ConcurrentHashMap.newKeySet();
public TbRabbitMqProducerTemplate(TbRabbitMqSettings rabbitMqSettings, String defaultTopic) {
this.defaultTopic = defaultTopic;
this.rabbitMqSettings = rabbitMqSettings;
producerExecutor = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
try {
connection = rabbitMqSettings.getConnectionFactory().newConnection();
channel = connection.createChannel();
} catch (IOException | TimeoutException e) {
log.error("Failed to create connection." , e);
// throw new RuntimeException("Failed to create connection." , e);
}
}
@Override
public void init() {
}
@Override
public String getDefaultTopic() {
return defaultTopic;
}
@Override
public void send(TopicPartitionInfo tpi, T msg, TbQueueCallback callback) {
createTopicIfNotExist(tpi);
AMQP.BasicProperties properties = new AMQP.BasicProperties();
try {
channel.basicPublish(rabbitMqSettings.getExchangeName(), tpi.getFullTopicName(), properties, JSON.toJSONString(new DefaultTbQueueMsg(msg)).getBytes());
if (callback != null) {
callback.onSuccess(null);
}
} catch (IOException e) {
log.error("Failed publish message: [{}]." , msg, e);
if (callback != null) {
callback.onFailure(e);
}
}
}
@Override
public void stop() {
if (producerExecutor != null) {
producerExecutor.shutdownNow();
}
if (channel != null) {
try {
channel.close();
} catch (IOException | TimeoutException e) {
log.error("Failed to close the channel.");
}
}
if (connection != null) {
try {
connection.close();
} catch (IOException e) {
log.error("Failed to close the connection.");
}
}
}
private void createTopicIfNotExist(TopicPartitionInfo tpi) {
if (topics.contains(tpi)) {
return;
}
// admin.createTopicIfNotExists(tpi.getFullTopicName());
topics.add(tpi);
}
}
package com.mortals.xhx.queue.rabbitmq;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
//@Component
//@ConditionalOnExpression("'${queue.type:null}'=='rabbitmq'")
public class TbRabbitMqQueueArguments {
@Value("${queue.rabbitmq.queue-properties.core}")
private String coreProperties;
@Value("${queue.rabbitmq.queue-properties.rule-engine}")
private String ruleEngineProperties;
@Value("${queue.rabbitmq.queue-properties.transport-api}")
private String transportApiProperties;
@Value("${queue.rabbitmq.queue-properties.notifications}")
private String notificationsProperties;
@Value("${queue.rabbitmq.queue-properties.js-executor}")
private String jsExecutorProperties;
@Getter
private Map<String, Object> coreArgs;
@Getter
private Map<String, Object> ruleEngineArgs;
@Getter
private Map<String, Object> transportApiArgs;
@Getter
private Map<String, Object> notificationsArgs;
@Getter
private Map<String, Object> jsExecutorArgs;
@PostConstruct
private void init() {
coreArgs = getArgs(coreProperties);
ruleEngineArgs = getArgs(ruleEngineProperties);
transportApiArgs = getArgs(transportApiProperties);
notificationsArgs = getArgs(notificationsProperties);
jsExecutorArgs = getArgs(jsExecutorProperties);
}
private Map<String, Object> getArgs(String properties) {
Map<String, Object> configs = new HashMap<>();
for (String property : properties.split(";")) {
int delimiterPosition = property.indexOf(":");
String key = property.substring(0, delimiterPosition);
String strValue = property.substring(delimiterPosition + 1);
configs.put(key, getObjectValue(strValue));
}
return configs;
}
private Object getObjectValue(String str) {
if (str.equalsIgnoreCase("true") || str.equalsIgnoreCase("false")) {
return Boolean.valueOf(str);
} else if (isNumeric(str)) {
return getNumericValue(str);
}
return str;
}
private Object getNumericValue(String str) {
if (str.contains(".")) {
return Double.valueOf(str);
} else {
return Long.valueOf(str);
}
}
private static final Pattern PATTERN = Pattern.compile("-?\\d+(\\.\\d+)?");
public boolean isNumeric(String strNum) {
if (strNum == null) {
return false;
}
return PATTERN.matcher(strNum).matches();
}
}
package com.mortals.xhx.queue.rabbitmq;
import com.rabbitmq.client.ConnectionFactory;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Slf4j
@ConditionalOnExpression("'${queue.type:null}'=='rabbitmq'")
@Component
@Data
public class TbRabbitMqSettings {
@Value("${queue.rabbitmq.exchange_name:}")
private String exchangeName;
@Value("${queue.rabbitmq.host:}")
private String host;
@Value("${queue.rabbitmq.port:}")
private int port;
@Value("${queue.rabbitmq.virtual_host:}")
private String virtualHost;
@Value("${queue.rabbitmq.username:}")
private String username;
@Value("${queue.rabbitmq.password:}")
private String password;
@Value("${queue.rabbitmq.automatic_recovery_enabled:}")
private boolean automaticRecoveryEnabled;
@Value("${queue.rabbitmq.connection_timeout:}")
private int connectionTimeout;
@Value("${queue.rabbitmq.handshake_timeout:}")
private int handshakeTimeout;
private ConnectionFactory connectionFactory;
@PostConstruct
private void init() {
connectionFactory = new ConnectionFactory();
connectionFactory.setHost(host);
connectionFactory.setPort(port);
connectionFactory.setVirtualHost(virtualHost);
connectionFactory.setUsername(username);
connectionFactory.setPassword(password);
connectionFactory.setAutomaticRecoveryEnabled(automaticRecoveryEnabled);
connectionFactory.setConnectionTimeout(connectionTimeout);
connectionFactory.setHandshakeTimeout(handshakeTimeout);
}
}
package com.mortals.xhx.utils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import java.util.HashSet;
import java.util.Set;
public class BeanUtil
{
/**
*
* @Title: getNullPropertyNames
* @Description: 获取一个对象中属性值为null的属性名字符串数组
* @param source
* @return
*/
public static String[] getNullPropertyNames (Object source) {
final BeanWrapper src = new BeanWrapperImpl(source);
java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();
Set<String> emptyNames = new HashSet<String>();
for(java.beans.PropertyDescriptor pd : pds) {
Object srcValue = src.getPropertyValue(pd.getName());
if (srcValue == null) emptyNames.add(pd.getName());
}
String[] result = new String[emptyNames.size()];
return emptyNames.toArray(result);
}
}
package com.mortals.xhx.utils;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
public class IotThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
public static IotThreadFactory forName(String name) {
return new IotThreadFactory(name);
}
private IotThreadFactory(String name) {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
namePrefix = name + "-" +
poolNumber.getAndIncrement() +
"-thread-";
}
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}
package com.mortals.xhx.utils;//package com.mortals.coops.utils;
//
//import javax.validation.Constraint;
//import javax.validation.ConstraintValidator;
//import javax.validation.ConstraintValidatorContext;
//import javax.validation.Payload;
//import java.lang.annotation.*;
//import java.time.LocalDate;
//
//@Target({ElementType.FIELD})
//@Retention(RetentionPolicy.RUNTIME)
//@Constraint(validatedBy = PastLocalDate.PastValidator.class)
//@Documented
//public @interface PastLocalDate {
// String message() default "{javax.validation.constraints.Past.message}";
//
// Class<?>[] groups() default {};
//
// Class<? extends Payload>[] payload() default {};
//
// class PastValidator implements ConstraintValidator<PastLocalDate,
// LocalDate> {
// public void initialize(PastLocalDate past) {
// }
//
// public boolean isValid(LocalDate localDate,
// ConstraintValidatorContext context) {
// return localDate == null || localDate.isBefore(LocalDate.now());
// }
// }
//}
package com.mortals.xhx.utils;
import com.mortals.framework.util.DateUtils;
import java.text.SimpleDateFormat;
import java.util.*;
public class TimeUtil {
public static List<String> findDaysStr(String begintTime, String endTime) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date dBegin = null;
Date dEnd = null;
try {
dBegin = sdf.parse(begintTime);
dEnd = sdf.parse(endTime);
} catch (Exception e) {
e.printStackTrace();
}
//存放每一天日期String对象的daysStrList
List<String> daysStrList = new ArrayList<String>();
//放入开始的那一天日期String
daysStrList.add(sdf.format(dBegin));
Calendar calBegin = Calendar.getInstance();
// 使用给定的 Date 设置此 Calendar 的时间
calBegin.setTime(dBegin);
Calendar calEnd = Calendar.getInstance();
// 使用给定的 Date 设置此 Calendar 的时间
calEnd.setTime(dEnd);
// 判断循环此日期是否在指定日期之后
while (dEnd.after(calBegin.getTime())) {
// 根据日历的规则,给定的日历字段增加或减去指定的时间量
calBegin.add(Calendar.DAY_OF_MONTH, 1);
String dayStr = sdf.format(calBegin.getTime());
daysStrList.add(dayStr);
}
return daysStrList;
}
public static List<String> findMonthsStr(String begintTime, String endTime) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
Date dBegin = null;
Date dEnd = null;
try {
dBegin = sdf.parse(begintTime);
dEnd = sdf.parse(endTime);
} catch (Exception e) {
e.printStackTrace();
}
//存放每一天日期String对象的daysStrList
List<String> monthsStrList = new ArrayList<String>();
//放入开始的那一天的月份String
monthsStrList.add(sdf1.format(dBegin));
Calendar calBegin = Calendar.getInstance();
// 使用给定的 Date 设置此 Calendar 的时间
calBegin.setTime(dBegin);
Calendar calEnd = Calendar.getInstance();
// 使用给定的 Date 设置此 Calendar 的时间
calEnd.setTime(dEnd);
// 判断循环此日期是否在指定日期之后
while (dEnd.after(calBegin.getTime())) {
// 根据日历的规则,给定的日历字段增加或减去指定的时间量
calBegin.add(Calendar.MONTH, 1);
String dayStr = sdf1.format(calBegin.getTime());
monthsStrList.add(dayStr);
}
return monthsStrList;
}
public static List<String> findYearsStr(String begintTime, String endTime) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
Date dBegin = null;
Date dEnd = null;
try {
dBegin = sdf.parse(begintTime);
dEnd = sdf.parse(endTime);
} catch (Exception e) {
e.printStackTrace();
}
List<String> yearsStrList = new ArrayList<String>();
yearsStrList.add(sdf.format(dBegin));
Calendar calBegin = Calendar.getInstance();
// 使用给定的 Date 设置此 Calendar 的时间
calBegin.setTime(dBegin);
Calendar calEnd = Calendar.getInstance();
// 使用给定的 Date 设置此 Calendar 的时间
calEnd.setTime(dEnd);
// 判断循环此日期是否在指定日期之后
while (dEnd.after(calBegin.getTime())) {
// 根据日历的规则,给定的日历字段增加或减去指定的时间量
calBegin.add(Calendar.YEAR, 1);
String dayStr = sdf.format(calBegin.getTime());
yearsStrList.add(dayStr);
}
return yearsStrList;
}
public static void main(String[] args) {
/* String begintTime = "2017";
String endTime = "2018";
// TimeUtil.findDaysStr(begintTime,endTime).stream().forEach(f->System.out.println(f));
//TimeUtil.findMonthsStr(begintTime,endTime).stream().forEach(f->System.out.println(f));
TimeUtil.findYearsStr(begintTime,endTime).stream().forEach(f->System.out.println(f));*/
/* String begintTime = "2017-03-01";
;
String yyyy = DateUtils.getDateTimeStr(DateUtils.StrToDateTime(begintTime, "yyyy"), DateUtils.P_yyyy_MM_dd);
System.out.println(yyyy);*/
String startTime="2019-03-18";
System.out.println(DateUtils.StrToDateTime(startTime,DateUtils.P_yyyy_MM_dd).getTime());
}
}
package com.mortals.xhx.utils.stream.messaging;//package com.mortals.xhx.utils.stream.messaging;
//
///**
// * @author karlhoo
// */
//public interface ProcessTaskProcessor extends ProcessTaskSink, ProcessTaskSource {
//}
package com.mortals.xhx.utils.stream.service.impl;//package com.mortals.xhx.utils.stream.service.impl;
//
//import com.mortals.xhx.utils.stream.service.IMessageService;
//import lombok.extern.apachecommons.CommonsLog;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.cloud.stream.annotation.EnableBinding;
//import org.springframework.kafka.support.KafkaHeaders;
//import org.springframework.messaging.Message;
//import org.springframework.messaging.MessageChannel;
//import org.springframework.messaging.support.MessageBuilder;
//import org.springframework.stereotype.Component;
//
///**
// * @author karlhoo
// */
//@CommonsLog
//@Component
//public class DefaultMessageServiceImpl implements IMessageService {
//
// @Override
// public boolean sendMessage(MessageChannel messageChannel, String message) {
// return sendMessage(messageChannel, message, null);
// }
//
// @Override
// public boolean sendMessage(MessageChannel messageChannel, String message, String messageKey) {
// return sendMessage(messageChannel, MessageBuilder.withPayload(message).setHeader(KafkaHeaders.MESSAGE_KEY, messageKey == null ? messageKey : messageKey.getBytes()).build());
// }
//
// private boolean sendMessage(MessageChannel messageChannel, Message message) {
// try {
// return messageChannel.send(message);
// } catch (Exception e) {
// log.error(String.format("提交消息出错 messageChannel: %s, message: %s", messageChannel.toString(), message.getPayload()), e);
// return false;
// }
// }
//
//}
...@@ -2,5 +2,8 @@ ...@@ -2,5 +2,8 @@
NODE_ENV = development NODE_ENV = development
# 地址 # 地址
VUE_APP_BASE_API =127.0.0.1:18211/m VUE_APP_BASE_API =http://plm.testnew.com:8082/m
# websocket地址
VUE_APP_WEBSOCKET_API =127.0.0.1:18211/m
...@@ -2,5 +2,8 @@ ...@@ -2,5 +2,8 @@
NODE_ENV = production NODE_ENV = production
# 地址 # 地址
VUE_APP_BASE_API = 192.168.0.26:18221 VUE_APP_BASE_API = http://192.168.0.100:11021/m
# websocket地址
VUE_APP_WEBSOCKET_API =192.168.0.100:18211/m
# 测试环境配置
NODE_ENV = test
# 地址
VUE_APP_BASE_API = 192.168.0.26:18221/m
...@@ -4,8 +4,9 @@ ...@@ -4,8 +4,9 @@
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "vue-cli-service serve", "dev": "vue-cli-service serve",
"build": "vue-cli-service build --model test", "build": "vue-cli-service build",
"build:prod": "vue-cli-service build --model production" "stage": "vue-cli-service build --mode stage",
"build:prod": "vue-cli-service build --model prod"
}, },
"dependencies": { "dependencies": {
"@chenfengyuan/vue-qrcode": "^1.0.2", "@chenfengyuan/vue-qrcode": "^1.0.2",
......
import axios from 'axios'; import axios from 'axios';
import { import {
formatter,formatterAmount, formatterDate,formatterDateOnly, find, formatter, formatterAmount, formatterDate, formatterDateOnly, find,
} from '@/assets/utils/table'; } from '@/assets/utils/table';
const tagsMap = { const tagsMap = {
...@@ -15,11 +15,11 @@ export default { ...@@ -15,11 +15,11 @@ export default {
watch: { watch: {
'$route'(route) { '$route'(route) {
this.query = Object.assign({}, this.query, route.query); this.query = Object.assign({}, this.query, route.query);
this.getData(); this.getData();
} }
}, },
beforeDestroy () { beforeDestroy() {
this.source.cancel('自动取消ajax操作'); this.source.cancel('自动取消ajax操作');
clearTimeout(this.loadingTimer); clearTimeout(this.loadingTimer);
}, },
...@@ -29,11 +29,11 @@ export default { ...@@ -29,11 +29,11 @@ export default {
return Promise.resolve(); return Promise.resolve();
}, },
// 表格接收数据前 // 表格接收数据前
beforeRender(data){return data}, beforeRender(data) { return data },
// 表格接收数据后 // 表格接收数据后
afterRender(data){}, afterRender(data) { },
// 删除动作发生后 // 删除动作发生后
afterDel(data){}, afterDel(data) { },
// 默认拉取数据 // 默认拉取数据
async getData() { async getData() {
try { try {
...@@ -42,30 +42,30 @@ export default { ...@@ -42,30 +42,30 @@ export default {
return; return;
} }
this.tableData.loading = true; this.tableData.loading = true;
console.log("list:"+this.pageInfo.list) console.log("list:" + this.pageInfo.list)
this.$post(this.pageInfo.list, this.query,{ this.$post(this.pageInfo.list, this.query, {
cancelToken: this.source.token cancelToken: this.source.token
}) })
.then(({data})=>{ .then(({ data }) => {
this.tableData = this.beforeRender( this.tableData = this.beforeRender(
Object.assign({}, this.tableData, data) Object.assign({}, this.tableData, data)
); );
this.afterRender(this.tableData); this.afterRender(this.tableData);
}) })
.catch(error=>{ .catch(error => {
if(error.message == '自动取消ajax操作') return if (error.message == '自动取消ajax操作') return
this.$message.error(error.message); this.$message.error(error.message);
}) })
.then(data=>{ .then(data => {
clearTimeout(this.loadingTimer); clearTimeout(this.loadingTimer);
this.loadingTimer = setTimeout(() => { this.loadingTimer = setTimeout(() => {
this.tableData.loading = false; this.tableData.loading = false;
}, 300); }, 300);
}) })
}, },
// 复制一个数组或对象 // 复制一个数组或对象
util_copy(data) { util_copy(data) {
if(typeof data !== 'object') return data; if (typeof data !== 'object') return data;
return JSON.parse(JSON.stringify(data)) return JSON.parse(JSON.stringify(data))
}, },
_showAll(item) { _showAll(item) {
...@@ -77,11 +77,11 @@ export default { ...@@ -77,11 +77,11 @@ export default {
util_short(key, size) { util_short(key, size) {
return row => { return row => {
let string = row[key] || ''; let string = row[key] || '';
if(string.length < size || row.isShowAll) return string; if (string.length < size || row.isShowAll) return string;
return ( return (
<span> <span>
{string.substr(0, 50)+'...'} {string.substr(0, 50) + '...'}
<el-button size='mini' type='text' onClick={()=>{this._showAll(row)}}>更多</el-button> <el-button size='mini' type='text' onClick={() => { this._showAll(row) }}>更多</el-button>
</span> </span>
) )
} }
...@@ -97,72 +97,88 @@ export default { ...@@ -97,72 +97,88 @@ export default {
// 通过id修改某条记录 // 通过id修改某条记录
util_update(id, newData, idColumnName) { util_update(id, newData, idColumnName) {
let table = this.tableData.result; let table = this.tableData.result;
let {index, data} = find(table, !idColumnName ? 'id' : idColumnName, id); let { index, data } = find(table, !idColumnName ? 'id' : idColumnName, id);
table.splice(index, 1, Object.assign({}, data, newData)); table.splice(index, 1, Object.assign({}, data, newData));
}, },
// 工具方法,把数字转化为字符串 // 工具方法,把数字转化为字符串
util_toString(data, array) { util_toString(data, array) {
const dataCopy = Object.assign({}, data); const dataCopy = Object.assign({}, data);
for(var item in data) { for (var item in data) {
dataCopy[item] = dataCopy[item] === undefined ? '' : dataCopy[item]+''; dataCopy[item] = dataCopy[item] === undefined ? '' : dataCopy[item] + '';
} }
return dataCopy; return dataCopy;
}, },
util_formatterDate(time, fmt) { util_formatterDate(time, fmt) {
if(!time) return ''; if (!time) return '';
let date = new Date(Number(time)); let date = new Date(Number(time));
var o = { var o = {
"M+": date.getMonth() + 1, //月份 "M+": date.getMonth() + 1, //月份
"d+": date.getDate(), //日 "d+": date.getDate(), //日
"[h|H]+": date.getHours(), //小时 "[h|H]+": date.getHours(), //小时
"m+": date.getMinutes(), //分 "m+": date.getMinutes(), //分
"s+": date.getSeconds(), //秒 "s+": date.getSeconds(), //秒
"q+": Math.floor((date.getMonth() + 3) / 3), //季度 "q+": Math.floor((date.getMonth() + 3) / 3), //季度
"S": date.getMilliseconds() //毫秒 "S": date.getMilliseconds() //毫秒
}; };
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length)); if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
for (var k in o) for (var k in o)
if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
return fmt; return fmt;
}, },
util_getPrevMonthDate() { util_getPrevMonthDate() {
let date = new Date(); let date = new Date();
var year = date.getFullYear(); var year = date.getFullYear();
var month = date.getMonth(); var month = date.getMonth();
var day = date.getDate(); var day = date.getDate();
if(month == 0){//年份为0代表,是本年的第一月,所以不能减 if (month == 0) {//年份为0代表,是本年的第一月,所以不能减
month = 11;//月份为上年的最后月份 month = 11;//月份为上年的最后月份
year--;//年份减1 year--;//年份减1
return new Date(year,month,day); return new Date(year, month, day);
} }
month--;//否则,只减去月份 month--;//否则,只减去月份
return new Date(year,month,day); return new Date(year, month, day);
}, },
// 格式化单元格数据 // 格式化单元格数据
formatter(row, column, val) { formatter(row, column, val) {
const content = formatter(this.tableData, column, val); const content = formatter(this.tableData, column, val);
//return content;
return content ? <el-tag type={'info'} size='mini'>{content}</el-tag> : val return content ? <el-tag type={'info'} size='mini'>{content}</el-tag> : val
}, },
formatterYES(row, column, val) {
const content = formatter(this.tableData, column, val);
console.log("content:"+content)
//return content;
if (content) {
if (val == '0') {
return <el-tag type={'danger'} size='mini'>{content}</el-tag>
} else if (val == '1') {
return <el-tag type={'success'} size='mini'>{content}</el-tag>
}
} else {
return val
}
},
formatterDictLink(row, column, val) { formatterDictLink(row, column, val) {
const content = formatter(this.tableData, column, val); const content = formatter(this.tableData, column, val);
let underline=false; let underline = false;
let type="primary" let type = "primary"
if(val===3){ if (val === 3) {
type='danger' type = 'danger'
} }
return content ? <el-link type={type} underline={underline} onClick={() => { this.toDrawerMsg(row)}} size='mini'>{content}</el-link> : val return content ? <el-link type={type} underline={underline} onClick={() => { this.toDrawerMsg(row) }} size='mini'>{content}</el-link> : val
}, },
formatterLink(row, column, val) { formatterLink(row, column, val) {
//const content = formatter(this.tableData, column-2, val); //const content = formatter(this.tableData, column-2, val);
return <el-link type="primary" href={val} target="_blank">{row.fileName}</el-link> return <el-link type="primary" href={val} target="_blank">{row.fileName}</el-link>
//return content; //return content;
// return content ? <el-tag type={'info'} size='mini'>{content}</el-tag> : val // return content ? <el-tag type={'info'} size='mini'>{content}</el-tag> : val
}, },
formatterString(row, column, val) { formatterString(row, column, val) {
return formatter(this.tableData, column, val) return formatter(this.tableData, column, val)
...@@ -173,8 +189,8 @@ export default { ...@@ -173,8 +189,8 @@ export default {
}, },
// 格式化单元格数据钱单位里换算成元 // 格式化单元格数据钱单位里换算成元
formatterMoney(row, column, val) { formatterMoney(row, column, val) {
return ((val || 0) / 1000).toFixed(2) return ((val || 0) / 1000).toFixed(2)
}, },
// 格式化单元格数据 // 格式化单元格数据
formatterDate(row, column) { formatterDate(row, column) {
return formatterDate(row, column) return formatterDate(row, column)
...@@ -184,32 +200,32 @@ export default { ...@@ -184,32 +200,32 @@ export default {
return formatterDateOnly(row, column) return formatterDateOnly(row, column)
}, },
// 格式化人员 // 格式化人员
formaterPeople(row, column, val){ formaterPeople(row, column, val) {
let info let info
if(val){ if (val) {
if(typeof(val) === 'number'){ if (typeof (val) === 'number') {
info = <el-tag type={'info'} size='mini'>{this.util_formatter('assigneeList',val)}</el-tag> info = <el-tag type={'info'} size='mini'>{this.util_formatter('assigneeList', val)}</el-tag>
}else{ } else {
info = ( info = (
val.split(',').map(v => { val.split(',').map(v => {
if(this.tableData.dict["assigneeList"][v] !=undefined){ if (this.tableData.dict["assigneeList"][v] != undefined) {
return <el-tag type={'info'} size='mini'>{this.util_formatter('assigneeList',v)}</el-tag> return <el-tag type={'info'} size='mini'>{this.util_formatter('assigneeList', v)}</el-tag>
} }
}) })
) )
} }
}else{ } else {
info = '--' info = '--'
} }
return info return info
}, },
// 多选表格行 // 多选表格行
handleSelectionChange(val) { handleSelectionChange(val) {
this.selection = val.map(i=>i.id); this.selection = val.map(i => i.id);
}, },
// 当某一行被点击时会触发该事件 // 当某一行被点击时会触发该事件
handleRowClick(row, column, event) { handleRowClick(row, column, event) {
}, },
// 合并表格行列 // 合并表格行列
handleSpanMethod() { handleSpanMethod() {
...@@ -220,55 +236,55 @@ export default { ...@@ -220,55 +236,55 @@ export default {
}, },
// 设置单元行样式 // 设置单元行样式
tableRowClassName() {}, tableRowClassName() { },
// 批量删除 // 批量删除
toBatchDel() { toBatchDel() {
this.toDel(this.selection.join(','), true); this.toDel(this.selection.join(','), true);
}, },
// 单个删除 // 单个删除
toDel(id, isBatch) { toDel(id, isBatch) {
if(!id) { if (!id) {
return this.$message.warning('请选中一条记录'); return this.$message.warning('请选中一条记录');
} }
this.$post(this.pageInfo.del, {id: id}) this.$post(this.pageInfo.del, { id: id })
.then(res=>{ .then(res => {
this.$message.success(res.msg) this.$message.success(res.msg)
// 更新数据 // 更新数据
if(isBatch) { if (isBatch) {
// 批量删除,刷新页面 // 批量删除,刷新页面
this.getData(); this.getData();
}else{ } else {
let table = this.tableData.result; let table = this.tableData.result;
let {index} = find(table, 'id', id); let { index } = find(table, 'id', id);
table.splice(index, 1); table.splice(index, 1);
this.tableData.pageInfo.totalResult -= 1; this.tableData.pageInfo.totalResult -= 1;
} }
this.afterDel(id); this.afterDel(id);
}) })
.catch(error=>{ .catch(error => {
this.$message.error(error.message); this.$message.error(error.message);
}) })
}, },
// 新增 // 新增
toAdd() { toAdd() {
this.$router.push({ this.$router.push({
path: this.pageInfo.add, path: this.pageInfo.add,
query: this.tableConfig.addQuery, query: this.tableConfig.addQuery,
}) })
}, },
// 编辑 // 编辑
toEdit(row, query) { toEdit(row, query) {
this.$router.push({ this.$router.push({
path: this.pageInfo.edit, path: this.pageInfo.edit,
query: Object.assign({}, {id: row.id}, query) query: Object.assign({}, { id: row.id }, query)
}) })
}, },
// 查看 // 查看
toView(row, query) { toView(row, query) {
this.$router.push({ this.$router.push({
path: this.pageInfo.view, path: this.pageInfo.view,
query: Object.assign({}, {id: row.id}, query) query: Object.assign({}, { id: row.id }, query)
}) })
}, },
// 导入 // 导入
...@@ -286,7 +302,7 @@ export default { ...@@ -286,7 +302,7 @@ export default {
}, },
// 开启、关闭 // 开启、关闭
open() { open() {
}, },
}, },
computed: { computed: {
...@@ -308,7 +324,7 @@ export default { ...@@ -308,7 +324,7 @@ export default {
}, },
}, },
data() { data() {
return { return {
source: axios.CancelToken.source(), source: axios.CancelToken.source(),
loadingTimer: null, loadingTimer: null,
query: this.$route.query, // url-query参数 query: this.$route.query, // url-query参数
...@@ -319,7 +335,7 @@ export default { ...@@ -319,7 +335,7 @@ export default {
search: [], // 头部搜索配置 search: [], // 头部搜索配置
columns: [], // 表格列信息配置 columns: [], // 表格列信息配置
addQuery: {}, // 新增按钮携带的参数 addQuery: {}, // 新增按钮携带的参数
buttons: [], // 增加查询区域自定义操作按钮,格式:[{label:'按钮显示名称',isShow:是否显示true/false,loading:true/false,type:'类型',icon:'图标',method:function(){}}] buttons: [], // 增加查询区域自定义操作按钮,格式:[{label:'按钮显示名称',isShow:是否显示true/false,loading:true/false,type:'类型',icon:'图标',method:function(){}}]
methods: { methods: {
handleSelectionChange: this.handleSelectionChange, handleSelectionChange: this.handleSelectionChange,
handleRowClick: this.handleRowClick, handleRowClick: this.handleRowClick,
......
...@@ -7,7 +7,8 @@ let reUrl='' ...@@ -7,7 +7,8 @@ let reUrl=''
* @param {string} url ws地址 * @param {string} url ws地址
*/ */
export const createSocket = url => { export const createSocket = url => {
Socket && Socket.close() // Socket && Socket.close()
Socket=null
if (!Socket) { if (!Socket) {
console.log('建立websocket连接:'+url) console.log('建立websocket连接:'+url)
reUrl=url reUrl=url
......
...@@ -60,7 +60,9 @@ ...@@ -60,7 +60,9 @@
</template> </template>
<script> <script>
import { createSocket } from "@/assets/utils/websocket";
export default { export default {
name: "Header",
methods: { methods: {
handleCommand(key) { handleCommand(key) {
if(key === 'update'){ if(key === 'update'){
...@@ -79,6 +81,46 @@ export default { ...@@ -79,6 +81,46 @@ export default {
}) })
} }
}, },
beforeDestroy() {
console.log("beforeDestroy");
window.removeEventListener("message", this.getsocketData, false);
},
mounted() {
console.log("mounted");
this.$nextTick(function () {
console.log("login websocket:"+"ws://"+process.env.VUE_APP_WEBSOCKET_API +"/ws?accessToken="+ this.$store.state.userData.id)
createSocket(
"ws://" +
process.env.VUE_APP_WEBSOCKET_API +
"/ws?accessToken=" +
this.$store.state.userData.id
);
});
let _this = this;
const getsocketData = (e) => {
// 创建接收消息函数
const data = e && e.detail.data;
let obj = JSON.parse(data);
if (obj.type == "SEND_TO_ALL_REQUEST") {
vm.refreshData();
let content = JSON.parse(obj.body.content);
_this.$notify({
title: "警告",
message: content,
type: "warning",
duration: 8000,
});
}
};
this.getsocketData = getsocketData;
// 注册监听事件
window.addEventListener("onmessageWS", getsocketData,false);
},
computed: { computed: {
group() { group() {
const relativeGroup = this.$store.state.group; const relativeGroup = this.$store.state.group;
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
<el-dialog :title="title" :visible.sync="open" width="80%" append-to-body> <el-dialog :title="title" :visible.sync="open" width="80%" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="120px"> <el-form ref="form" :model="form" :rules="rules" label-width="120px">
<el-row> <el-row>
<Field :span="20" label="设备名称" prop="deviceName" v-model="form.deviceName" placeholder="请输入设备名称"/> <!-- <Field :span="20" label="设备名称" prop="deviceName" v-model="form.deviceName" placeholder="请输入设备名称"/> -->
<Field :span="20" label="设备编码" prop="deviceCode" v-model="form.deviceCode" type="textarea" placeholder="请输入设备编码"/> <Field :span="20" label="设备编码" prop="deviceCode" v-model="form.deviceCode" type="textarea" placeholder="请输入设备编码"/>
<Field :span="20" label="设备类型" prop="deviceType" v-model="form.deviceType" type="select" :enumData="dict.deviceType" placeholder="请选择设备类型"/> <Field :span="20" label="设备类型" prop="deviceType" v-model="form.deviceType" type="select" :enumData="dict.deviceType" placeholder="请选择设备类型"/>
<Field :span="20" label="设备的MAC地址" prop="deviceMac" v-model="form.deviceMac" placeholder="请输入设备的MAC地址"/> <Field :span="20" label="设备的MAC地址" prop="deviceMac" v-model="form.deviceMac" placeholder="请输入设备的MAC地址"/>
......
<template> <template>
<div class="page"> <div class="page">
<LayoutTable :data="tableData" :config="tableConfig"> <LayoutTable :data="tableData" :config="tableConfig">
<el-tag slot="table-body-head" style="margin:5px" type="success">当前在线设备:{{tableData.onlineCount}}</el-tag> <el-tag slot="table-body-head" style="margin:5px" type="success">当前在线设备总计{{tableData.onlineCount}}</el-tag>
<el-tag slot="table-body-head" style="margin:5px" type="danger">当前离线设备:{{tableData.offlineCount}}</el-tag> <el-tag slot="table-body-head" style="margin:5px" type="danger">当前离线设备总计{{tableData.offlineCount}}</el-tag>
<el-tag v-for='($label, $value) in tableData.offlineDeviceType'
:key='$value'
:label="$value" slot="table-body-head" style="margin:5px" type="danger">{{$value}}离线设备:{{$label}}</el-tag>
</LayoutTable> </LayoutTable>
...@@ -21,38 +26,38 @@ export default { ...@@ -21,38 +26,38 @@ export default {
components: { dialogShow }, components: { dialogShow },
mixins: [table], mixins: [table],
created() { created() {
let _this = this; // let _this = this;
const getsocketData = (e) => { // const getsocketData = (e) => {
// 创建接收消息函数 // // 创建接收消息函数
const data = e && e.detail.data; // const data = e && e.detail.data;
let obj = JSON.parse(data); // let obj = JSON.parse(data);
if (obj.type == "SEND_TO_ALL_REQUEST") { // if (obj.type == "SEND_TO_ALL_REQUEST") {
let msg = ""; // let msg = "";
let content = JSON.parse(obj.body.content); // let content = JSON.parse(obj.body.content);
if (content.deviceOnlineStatus == 1) { // if (content.deviceOnlineStatus == 1) {
console.log(_this.tableData.dict) // console.log(_this.tableData.dict)
msg = _this.tableData.dict.deviceType[content.deviceType]+ "设备:" + content.deviceCode + " 上线!"; // msg = _this.tableData.dict.deviceType[content.deviceType]+ "设备:" + content.deviceCode + " 上线!";
} else { // } else {
msg = _this.tableData.dict.deviceType[content.deviceType]+"设备:" + content.deviceCode + " 离线!"; // msg = _this.tableData.dict.deviceType[content.deviceType]+"设备:" + content.deviceCode + " 离线!";
} // }
_this.$notify({ // _this.$notify({
title: "警告", // title: "警告",
message: msg, // message: msg,
type: "warning", // type: "warning",
duration: 8000, // duration: 8000,
}); // });
_this.getData(); // _this.getData();
} // }
console.log(data);
};
this.getsocketData = getsocketData; // console.log(data);
// 注册监听事件 // };
window.addEventListener("onmessageWS", getsocketData,false);
// this.getsocketData = getsocketData;
// // 注册监听事件
// window.addEventListener("onmessageWS", getsocketData,false);
}, },
methods: { methods: {
/** 重写新增方法 */ /** 重写新增方法 */
...@@ -64,9 +69,9 @@ export default { ...@@ -64,9 +69,9 @@ export default {
this.$refs.dialogform.edit(row); this.$refs.dialogform.edit(row);
}, },
/** 重写查看方法 */ /** 重写查看方法 */
// toView(row) { toView(row) {
// this.$refs.dialogform.view(row); this.$refs.dialogform.view(row);
// }, },
}, },
data() { data() {
return { return {
...@@ -83,6 +88,12 @@ export default { ...@@ -83,6 +88,12 @@ export default {
type: 'select', type: 'select',
label: '在线状态', label: '在线状态',
}, },
{
name: 'deviceType',
type: 'select',
label: '设备类型',
},
], ],
columns: [ columns: [
{ type: "selection", width: 60 }, { type: "selection", width: 60 },
...@@ -96,7 +107,7 @@ export default { ...@@ -96,7 +107,7 @@ export default {
{ {
label: "在线状态 ", label: "在线状态 ",
prop: "deviceOnlineStatus", prop: "deviceOnlineStatus",
formatter: this.formatter, formatter: this.formatterYES,
}, },
{ {
......
<template> <template>
<div class="page"> <div class="page">
<LayoutTable :data='tableData' :config='tableConfig' notPagination notDel> <LayoutTable :data='tableData' :config='tableConfig' notPagination notDel >
<div> <div>
<el-tree <el-tree
:data="tree" :data="tree"
......
<template> <template>
<div class="page"> <div class="page">
<LayoutTable :data='tableData' :config='tableConfig' /> <LayoutTable :data="tableData" notAdd notDel :config="tableConfig" />
</div> </div>
</template> </template>
<script> <script>
import table from '@/assets/mixins/table'; import table from "@/assets/mixins/table";
export default { export default {
mixins: [table], mixins: [table],
data() { data() {
return { return {
config: { config: {
search: [ search: [
{ {
name: 'loginName', name: "loginName",
type: 'text', type: "text",
label: '登录名', label: "登录名",
}, },
{ {
name: 'requestUrl', name: "requestUrl",
type: 'text', type: "text",
label: '请求地址', label: "请求地址",
}, },
], ],
columns: [ columns: [
{
type: 'selection', {
width: 60, prop: "id",
}, label: "序号",
align: "center",
{ },
prop: 'id',
label: '序号', {
}, prop: "userName",
label: "用户名称",
align: "center",
{ },
prop: 'userName',
label: '用户名称', {
}, prop: "loginName",
label: "用户登录名",
align: "center",
{ },
prop: 'loginName',
label: '用户登录名', {
}, prop: "requestUrl",
label: "请求地址",
align: "center",
{ },
prop: 'requestUrl',
label: '请求地址', {
}, prop: "content",
label: "操作内容",
align: "center",
{ },
prop: 'content',
label: '操作内容', {
}, prop: "ip",
label: "操作IP地址",
align: "center",
{ },
prop: 'ip',
label: '操作IP地址', {
}, prop: "logDate",
label: "操作时间",
align: "center",
{ formatter: this.formatterDate,
prop: 'logDate', },
label: '操作时间', ],
width: 140, },
formatter: this.formatterDate };
}, },
};
{
label: '操作',
width: 100,
formatter: (row)=> {
return (
<table-buttons row={row} onDel={this.toDel} noEdit/>
)
},
},
],
},
}
}
}
</script> </script>
<template> <template>
<div class="page"> <div class="page">
<LayoutTable :data='tableData' :config='tableConfig' notPagination /> <LayoutTable :data='tableData' :config='tableConfig' notPagination />
<dialog-show ref="dialogform" @ok="getData" />
</div> </div>
</template> </template>
<script> <script>
import table from '@/assets/mixins/table'; import table from '@/assets/mixins/table';
import dialogShow from "./dialogshow";
export default { export default {
mixins: [table], mixins: [table],
components: { dialogShow },
methods: { methods: {
beforeRender(data) { beforeRender(data) {
this.allMenu = this.sortByGroup(this.util_copy(data.result)); this.allMenu = this.sortByGroup(this.util_copy(data.result));
...@@ -67,6 +70,49 @@ export default { ...@@ -67,6 +70,49 @@ export default {
statusChange() { statusChange() {
this.$store.dispatch('login'); this.$store.dispatch('login');
}, },
handleUp(data) {
let type = 0;
let url = "/menu/upOrDown";
this.switchSort(url, data.id, type);
},
handleDown(data) {
let type = 1;
let url = "/menu/upOrDown";
this.switchSort(url, data.id, type);
},
switchSort(url, id, type) {
this.loading = true;
this.$post(url, {
id: id,
type: type,
})
.then((res) => {
if (res && res.code && res.code == 1) {
this.getData()
this.loading = false;
this.$message.success("更新排序成功!");
}
})
.catch((error) => {
this.loading = false;
this.$message.error(error.message);
});
},
/** 重写新增方法 */
toAdd(row) {
this.$refs.dialogform.add(row);
},
/** 重写编辑方法 */
toEdit(row) {
this.$refs.dialogform.edit(row);
},
/** 重写查看方法 */
toView(row) {
this.$refs.dialogform.view(row);
},
}, },
data() { data() {
return { return {
...@@ -114,8 +160,8 @@ export default { ...@@ -114,8 +160,8 @@ export default {
{ {
prop: 'imgPath', prop: 'imgPath',
label: '图标', label: '图标',
width: 50, width: 120,
formatter: this.showIcon, // formatter: this.showIcon,
}, },
{ {
prop: 'authType', prop: 'authType',
...@@ -140,7 +186,28 @@ export default { ...@@ -140,7 +186,28 @@ export default {
label: '操作', label: '操作',
formatter: (row)=> { formatter: (row)=> {
return ( return (
<table-buttons row={row} onEdit={this.toEdit} onDel={this.toDel} />
<div>
<el-link
style="margin-right:5px;margin-left:5px"
icon="el-icon-top"
onClick={() => {
this.handleUp(row);
}}
></el-link>
<el-link
style="margin-right:5px;margin-left:5px"
icon="el-icon-bottom"
onClick={() => {
this.handleDown(row);
}}
></el-link>
<table-buttons noView row={row} onEdit={this.toEdit} onDel={this.toDel} />
</div>
) )
}, },
}, },
......
<template> <template>
<div class="page"> <div class="page">
<LayoutTable :data='tableData' :config='tableConfig' /> <LayoutTable :data='tableData' :config='tableConfig' />
<dialog-show ref="dialogform" @ok="getData" />
</div> </div>
</template> </template>
<script> <script>
import table from '@/assets/mixins/table'; import table from '@/assets/mixins/table';
import dialogShow from "./dialogshow";
export default { export default {
mixins: [table], mixins: [table],
components: {dialogShow },
methods: {
// 新增
toAdd(row) {
this.$refs.dialogform.add(row);
},
// 编辑
toEdit(row) {
this.$refs.dialogform.edit(row);
},
// 查看
toView(row,) {
this.$refs.dialogform.view(row);
},
},
data() { data() {
return { return {
config: { config: {
...@@ -69,10 +86,10 @@ export default { ...@@ -69,10 +86,10 @@ export default {
}, },
{ {
label: '操作', label: '操作',
width: 180, width: 260,
formatter: (row)=> { formatter: (row)=> {
return ( return (
<table-buttons row={row} onEdit={this.toEdit} onView={this.toView} onDel={this.toDel} /> <table-buttons noAdd row={row} onEdit={this.toEdit} onView={this.toView} onDel={this.toDel} />
) )
}, },
}, },
......
<template> <template>
<div class="page"> <div class="page">
<LayoutTable :data='tableData' :config='tableConfig' /> <LayoutTable :data='tableData' :config='tableConfig' />
<dialog-show ref="dialogform" @ok="getData" />
</div> </div>
</template> </template>
<script> <script>
import table from '@/assets/mixins/table'; import table from '@/assets/mixins/table';
import dialogShow from "./dialogshow";
export default { export default {
mixins: [table], mixins: [table],
components: {
dialogShow,
},
methods: {
/** 重写新增方法 */
toAdd(row) {
this.$refs.dialogform.add(row);
},
/** 重写编辑方法 */
toEdit(row) {
console.log(22222222)
this.$refs.dialogform.edit(row);
},
/** 重写查看方法 */
toView(row) {
this.$refs.dialogform.view(row);
},
},
data() { data() {
return { return {
config: { config: {
...@@ -29,11 +48,10 @@ export default { ...@@ -29,11 +48,10 @@ export default {
type: 'selection', type: 'selection',
width: 60, width: 60,
}, },
{ // {
prop: 'id', // prop: 'id',
label: 'ID', // label: 'ID',
width: 60, // },
},
{ {
prop: 'name', prop: 'name',
label: '名称', label: '名称',
...@@ -45,7 +63,7 @@ export default { ...@@ -45,7 +63,7 @@ export default {
{ {
prop: 'authType', prop: 'authType',
label: '认证类型', label: '认证类型',
width: 140,
formatter: this.formatter, formatter: this.formatter,
}, },
// { // {
...@@ -59,7 +77,7 @@ export default { ...@@ -59,7 +77,7 @@ export default {
witdh: 120, witdh: 120,
formatter: (row)=> { formatter: (row)=> {
return ( return (
<table-buttons row={row} onEdit={this.toEdit} onDel={this.toDel} /> <table-buttons noView row={row} onEdit={this.toEdit} onDel={this.toDel} />
) )
}, },
}, },
......
<template> <template>
<div class="page"> <div class="page">
<LayoutTable :data="tableData" :config="tableConfig" />
<LayoutTable :data='tableData' :config='tableConfig' /> <dialog-show ref="dialogform" @ok="getData" />
<el-dialog title="分配权限" :visible.sync="auth.visible"> <el-dialog title="分配权限" :visible.sync="auth.visible">
<el-form :model="auth.form"> <el-form :model="auth.form">
<el-checkbox-group v-model="auth.checkList"> <el-checkbox-group v-model="auth.checkList">
<div v-for='(group, key) in allResources' :key='key'> <div v-for="(group, key) in allResources" :key="key">
<h2 style="font-size: 14px;font-weight: bold;margin: 10px 0"> <h2 style="font-size: 14px; font-weight: bold; margin: 10px 0">
{{key}} {{ key }}
<el-checkbox :key='key' @change='(e)=>{handleChange(e, key)}' :label="key">全选</el-checkbox> <el-checkbox
:key="key"
@change="
(e) => {
handleChange(e, key);
}
"
:label="key"
>全选</el-checkbox
>
</h2> </h2>
<el-checkbox v-for='item in group.list' :key='item.id' :label="item.id"> <el-checkbox
{{item.name}} v-for="item in group.list"
:key="item.id"
:label="item.id"
>
{{ item.name }}
</el-checkbox> </el-checkbox>
</div> </div>
</el-checkbox-group> </el-checkbox-group>
</el-form> </el-form>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
<el-button size='mini' @click="auth.visible = false">取 消</el-button> <el-button size="mini" @click="auth.visible = false">取 消</el-button>
<el-button size='mini' type="primary" @click="saveAuth">确 定</el-button> <el-button size="mini" type="primary" @click="saveAuth"
>确 定</el-button
>
</div> </div>
</el-dialog> </el-dialog>
<div class="userSaveDiv"> <div class="userSaveDiv">
<el-dialog title="分配用户" :visible.sync="user.visible" width="75%"> <el-dialog title="分配用户" :visible.sync="user.visible" width="75%">
<el-form :model="user.form" size='mini' label-width='80px' > <el-form :model="user.form" size="mini" label-width="80px">
<el-row> <el-row>
<el-col :span='8'> <el-col :span="8">
<span>用户类型:</span> <span>用户类型:</span>
<el-select placeholder="请选择用户类型" v-model="userTypeIdVal" size='mini' clearable> <el-select
<el-option placeholder="请选择用户类型"
v-for='($label, $value) in userTypeMap' v-model="userTypeIdVal"
:key='$value' size="mini"
:label="$label" clearable
:value="$value"> >
</el-option> <el-option
</el-select> v-for="($label, $value) in userTypeMap"
</el-col> :key="$value"
<Field label="登录账号" prop="loginNameVal" v-model="loginNameVal" placeholder="请输入登录账号" :span='8'/> :label="$label"
<Field label="昵称" prop="realNameVal" v-model="realNameVal" placeholder="请输入昵称" :span='8'/> :value="$value"
<el-col style="text-align:center"> >
<el-button type="primary" size='mini' icon='el-icon-search' @click="searchUserList">查询未分配用户</el-button> </el-option>
<el-button icon='search' size='mini' plain @click="cleanSearchCon">清空</el-button> </el-select>
</el-col> </el-col>
</el-row> <Field
<fieldset class="check-user-fieldset"> label="登录账号"
<legend>已分配用户</legend> prop="loginNameVal"
<div style="margin-left:15px;margin-bottem:10px;height:90%;overflow:auto;"> v-model="loginNameVal"
<el-checkbox-group v-model="user.checkList" style="margin-left:15px;margin-bottem:10px;"> placeholder="请输入登录账号"
<el-checkbox v-for='item in checkedUsers' @change='(e)=>{handleUnCheckChangeUser(e, item)}' :key='item.id' :label="item.id" :name="item.realName">{{item.realName}}</el-checkbox> :span="8"
</el-checkbox-group> />
</div> <Field
</fieldset> label="昵称"
<fieldset class="check-user-fieldset"> prop="realNameVal"
<legend>未分配用户</legend> v-model="realNameVal"
<div style="margin-left:15px;margin-bottem:10px;height:90%;overflow:auto;"> placeholder="请输入昵称"
<el-checkbox-group v-model="user.checkList" style="margin-left:15px;margin-bottem:10px;"> :span="8"
<el-checkbox v-for='item in unCheckedUsers' @change='(e)=>{handleCheckChangeUser(e, item)}' :key='item.id' :label="item.id">{{item.realName}}</el-checkbox> />
</el-checkbox-group> <el-col style="text-align: center">
</div> <el-button
</fieldset> type="primary"
size="mini"
</el-form> icon="el-icon-search"
<div slot="footer" class="dialog-footer"> @click="searchUserList"
<el-button size='mini' @click="user.visible = false">取 消</el-button> >查询未分配用户</el-button
<el-button size='mini' type="primary" @click="saveUser">确 定</el-button> >
</div> <el-button icon="search" size="mini" plain @click="cleanSearchCon"
</el-dialog> >清空</el-button
>
</el-col>
</el-row>
<fieldset class="check-user-fieldset">
<legend>已分配用户</legend>
<div
style="
margin-left: 15px;
margin-bottem: 10px;
height: 90%;
overflow: auto;
"
>
<el-checkbox-group
v-model="user.checkList"
style="margin-left: 15px; margin-bottem: 10px"
>
<el-checkbox
v-for="item in checkedUsers"
@change="
(e) => {
handleUnCheckChangeUser(e, item);
}
"
:key="item.id"
:label="item.id"
:name="item.realName"
>{{ item.realName }}</el-checkbox
>
</el-checkbox-group>
</div>
</fieldset>
<fieldset class="check-user-fieldset">
<legend>未分配用户</legend>
<div
style="
margin-left: 15px;
margin-bottem: 10px;
height: 90%;
overflow: auto;
"
>
<el-checkbox-group
v-model="user.checkList"
style="margin-left: 15px; margin-bottem: 10px"
>
<el-checkbox
v-for="item in unCheckedUsers"
@change="
(e) => {
handleCheckChangeUser(e, item);
}
"
:key="item.id"
:label="item.id"
>{{ item.realName }}</el-checkbox
>
</el-checkbox-group>
</div>
</fieldset>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button size="mini" @click="user.visible = false">取 消</el-button>
<el-button size="mini" type="primary" @click="saveUser"
>确 定</el-button
>
</div>
</el-dialog>
</div> </div>
</div> </div>
</template> </template>
<style>
.userSaveDiv .el-dialog {
margin: 0 auto !important;
height: 100%;
overflow: hidden;
margin-bottom: 400px
}
.userSaveDiv .el-dialog__body {
position: absolute;
left: 50PX;
top: 54px;
bottom: 50PX;
right: 0;
padding: 0;
z-index: 1;
overflow: hidden;
overflow-y: auto;
}
.userSaveDiv .el-dialog__footer {
position: absolute;
bottom: 0;
right: 0;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.userSaveDiv .check-user-fieldset{
height:480px;
border: 1px solid #ededed;
float: left;
margin-left:1%;
width: 48%;
margin-top: 20px;
}
</style>
<script> <script>
import table from '@/assets/mixins/table'; import table from "@/assets/mixins/table";
import dialogShow from "./dialogshow";
export default { export default {
mixins: [table], mixins: [table],
created() { components: { dialogShow },
}, created() {},
methods: { methods: {
beforeRender(data) { beforeRender(data) {
this.customerMap = data.dict.customerId; this.customerMap = data.dict.customerId;
...@@ -124,7 +167,7 @@ export default { ...@@ -124,7 +167,7 @@ export default {
return data; return data;
}, },
// 打开弹窗,获取已经选中的权限 // 打开弹窗,获取已经选中的权限
async setAuth({id}) { async setAuth({ id }) {
this.tableData.loading = true; this.tableData.loading = true;
try { try {
this.auth.form = this.initForm(); this.auth.form = this.initForm();
...@@ -139,159 +182,196 @@ export default { ...@@ -139,159 +182,196 @@ export default {
}, },
// 获取权限列表 // 获取权限列表
getAuths() { getAuths() {
if(Object.keys(this.allResources).length) { if (Object.keys(this.allResources).length) {
return this.allResources; return this.allResources;
} }
return new Promise((resolve, reject)=>{ return new Promise((resolve, reject) => {
this.$post('/resource/list', {pageInfo: {prePageResult: -1}}).then(({data})=>{ this.$post("/resource/list", { pageInfo: { prePageResult: -1 } })
resolve(this.groupByAuth(data.result)); .then(({ data }) => {
}).catch(reject) resolve(this.groupByAuth(data.result));
}) })
.catch(reject);
});
}, },
// 权限分组 // 权限分组
groupByAuth(list) { groupByAuth(list) {
let group = {}; let group = {};
list.forEach(item=>{ list.forEach((item) => {
let name = item.name.split('-')[0]; let name = item.name.split("-")[0];
if(!group[name]) { if (!group[name]) {
group[name] = { group[name] = {
selectAll: false, selectAll: false,
list: [], list: [],
}; };
} }
group[name].list.push(item); group[name].list.push(item);
}) });
return group; return group;
}, },
// 选中权限组 // 选中权限组
handleChange(checked, type) { handleChange(checked, type) {
const list = this.auth.checkList.slice(); const list = this.auth.checkList.slice();
const selectd = this.allResources[type].list.map(i=>i.id); const selectd = this.allResources[type].list.map((i) => i.id);
if(checked) { if (checked) {
this.auth.checkList = [...new Set(list.concat(selectd))]; this.auth.checkList = [...new Set(list.concat(selectd))];
}else{ } else {
this.auth.checkList = this.auth.checkList.filter(i=>selectd.indexOf(i) === -1) this.auth.checkList = this.auth.checkList.filter(
(i) => selectd.indexOf(i) === -1
);
} }
}, },
// 获取角色权限列表 // 获取角色权限列表
getRoleAuths(id) { getRoleAuths(id) {
return new Promise((resolve, reject)=>{ return new Promise((resolve, reject) => {
this.$post('/role/auth/list', {'query.roleId': id, 'pageInfo.prePageResult': -1}).then(({data})=>{ this.$post("/role/auth/list", {
const result = data.result.map(i=>i.resourceId); "query.roleId": id,
resolve(result); "pageInfo.prePageResult": -1,
}).catch(reject) })
}) .then(({ data }) => {
const result = data.result.map((i) => i.resourceId);
resolve(result);
})
.catch(reject);
});
}, },
// 保存选中的权限 // 保存选中的权限
async saveAuth() { async saveAuth() {
try { try {
this.auth.form.resourceIdList = this.auth.checkList.filter(i=>typeof i === 'number').join(','); this.auth.form.resourceIdList = this.auth.checkList
await this.$post('/role/auth/distributionSource', {query: this.auth.form}); .filter((i) => typeof i === "number")
.join(",");
await this.$post("/role/auth/distributionSource", {
query: this.auth.form,
});
this.auth.visible = false; this.auth.visible = false;
this.auth.form = this.initForm(); this.auth.form = this.initForm();
this.$message.success('操作成功'); this.$message.success("操作成功");
} catch (error) { } catch (error) {
this.$message.error(error.message); this.$message.error(error.message);
} }
}, },
// 获取用户列表 // 获取用户列表
getUsers() { getUsers() {
// if(this.allUsers.length) { // if(this.allUsers.length) {
// return this.allUsers; // return this.allUsers;
// } // }
return new Promise((resolve, reject)=>{ return new Promise((resolve, reject) => {
this.$post('/user/list', {pageInfo: {prePageResult: -1}}).then(({data})=>{ this.$post("/user/list", { pageInfo: { prePageResult: -1 } })
resolve(data.result); .then(({ data }) => {
}).catch(reject) resolve(data.result);
}) })
.catch(reject);
});
}, },
async searchUserList(){ async searchUserList() {
this.allUsers = await this.getUsersoo(this.userTypeIdVal,this.loginNameVal,this.realNameVal); this.allUsers = await this.getUsersoo(
this.unCheckedUsers=[]; this.userTypeIdVal,
if(this.allUsers && this.allUsers.length>0){ this.loginNameVal,
this.allUsers.forEach((item, i)=>{ this.realNameVal
if(!this.user.checkList.includes(item.id)){ );
this.unCheckedUsers = [];
if (this.allUsers && this.allUsers.length > 0) {
this.allUsers.forEach((item, i) => {
if (!this.user.checkList.includes(item.id)) {
this.unCheckedUsers.push(item); this.unCheckedUsers.push(item);
} }
}) });
} }
}, },
async getUsersoo(userTypeIdVal,loginNameVal,realNameVal){ async getUsersoo(userTypeIdVal, loginNameVal, realNameVal) {
const query = {'pageInfo.prePageResult': -1,'query.userType':userTypeIdVal,'query.loginName':loginNameVal,'query.realName':realNameVal}; const query = {
return new Promise((resolve, reject)=>{ "pageInfo.prePageResult": -1,
this.$post('/user/list', query).then(({data})=>{ "query.userType": userTypeIdVal,
"query.loginName": loginNameVal,
"query.realName": realNameVal,
};
return new Promise((resolve, reject) => {
this.$post("/user/list", query)
.then(({ data }) => {
resolve(data.result); resolve(data.result);
}).catch(reject) })
}) .catch(reject);
});
}, },
cleanSearchCon(){ cleanSearchCon() {
this.loginNameVal=""; this.loginNameVal = "";
this.userTypeIdVal=""; this.userTypeIdVal = "";
this.realNameVal=""; this.realNameVal = "";
}, },
handleCheckChangeUser(checked, item) { handleCheckChangeUser(checked, item) {
var checkUserId = item.id; var checkUserId = item.id;
if(checked) { if (checked) {
var tempItem = {}; var tempItem = {};
tempItem.id = checkUserId; tempItem.id = checkUserId;
tempItem.realName = item.realName; tempItem.realName = item.realName;
this.user.checkList.push(checkUserId); this.user.checkList.push(checkUserId);
this.checkedUsers.push(tempItem); this.checkedUsers.push(tempItem);
this.unCheckedUsers = this.unCheckedUsers.filter(i=>i.id != checkUserId); this.unCheckedUsers = this.unCheckedUsers.filter(
(i) => i.id != checkUserId
);
this.user.checkList = [...new Set(this.user.checkList)]; this.user.checkList = [...new Set(this.user.checkList)];
} }
}, },
handleUnCheckChangeUser(checked, item) { handleUnCheckChangeUser(checked, item) {
var checkUserId = item.id; var checkUserId = item.id;
if(!checked) { if (!checked) {
var tempItem = {}; var tempItem = {};
tempItem.id = checkUserId; tempItem.id = checkUserId;
tempItem.realName = item.realName; tempItem.realName = item.realName;
this.unCheckedUsers.push(tempItem); this.unCheckedUsers.push(tempItem);
this.user.checkList = this.user.checkList.filter(i=>i.id != checkUserId); this.user.checkList = this.user.checkList.filter(
this.checkedUsers = this.checkedUsers.filter(i=>i.id != checkUserId); (i) => i.id != checkUserId
);
this.checkedUsers = this.checkedUsers.filter(
(i) => i.id != checkUserId
);
} }
}, },
// 获取角色用户列表 // 获取角色用户列表
getRoleUsers(id) { getRoleUsers(id) {
return new Promise((resolve, reject)=>{ return new Promise((resolve, reject) => {
this.$post('/role/user/list', {'query.roleId': id, 'pageInfo.prePageResult': -1}).then(({data})=>{ this.$post("/role/user/list", {
const result = data.result.filter(i=>i.userId).map(i=>i.userId); "query.roleId": id,
this.resultUserDict = data.dict.userReNameMap; "pageInfo.prePageResult": -1,
if(data.result && data.result.length>0){ })
data.result.forEach(i=>{ .then(({ data }) => {
var tempItem = {}; const result = data.result
tempItem.id = i.userId; .filter((i) => i.userId)
tempItem.realName = (this.resultUserDict[i.userId] || i.userId); .map((i) => i.userId);
this.checkedUsers.push(tempItem); this.resultUserDict = data.dict.userReNameMap;
}) if (data.result && data.result.length > 0) {
} data.result.forEach((i) => {
resolve(result); var tempItem = {};
}).catch(reject) tempItem.id = i.userId;
}) tempItem.realName = this.resultUserDict[i.userId] || i.userId;
this.checkedUsers.push(tempItem);
});
}
resolve(result);
})
.catch(reject);
});
}, },
// 打开弹窗 // 打开弹窗
async setUser({id}) { async setUser({ id }) {
try { try {
this.cleanSearchCon(); this.cleanSearchCon();
this.tableData.loading = true; this.tableData.loading = true;
this.user.form = this.initUserForm(); this.user.form = this.initUserForm();
// this.allUsers = await this.getUsers(); // this.allUsers = await this.getUsers();
this.checkedUsers=[]; this.checkedUsers = [];
this.user.checkList = await this.getRoleUsers(id); this.user.checkList = await this.getRoleUsers(id);
this.user.form.roleId = id; this.user.form.roleId = id;
this.user.visible = true; this.user.visible = true;
this.unCheckedUsers=[]; this.unCheckedUsers = [];
} catch (error) { } catch (error) {
this.$message.error(error.message); this.$message.error(error.message);
} }
...@@ -301,11 +381,13 @@ export default { ...@@ -301,11 +381,13 @@ export default {
// 保存选中的用户 // 保存选中的用户
async saveUser() { async saveUser() {
try { try {
this.user.form.userIdList = this.user.checkList.join(','); this.user.form.userIdList = this.user.checkList.join(",");
await this.$post('/role/user/distributionUser', {query: this.user.form}) await this.$post("/role/user/distributionUser", {
query: this.user.form,
});
this.user.visible = false; this.user.visible = false;
this.user.form = this.initForm(); this.user.form = this.initForm();
this.$message.success('操作成功'); this.$message.success("操作成功");
} catch (error) { } catch (error) {
this.$message.error(error.message); this.$message.error(error.message);
} }
...@@ -313,29 +395,42 @@ export default { ...@@ -313,29 +395,42 @@ export default {
initForm() { initForm() {
return { return {
resourceIdList: '', resourceIdList: "",
roleId: '', roleId: "",
} };
}, },
initUserForm() { initUserForm() {
return { return {
userIdList: '', userIdList: "",
roleId: '', roleId: "",
} };
},
/** 重写新增方法 */
toAdd(row) {
this.$refs.dialogform.add(row);
},
/** 重写编辑方法 */
toEdit(row) {
this.$refs.dialogform.edit(row);
},
/** 重写查看方法 */
toView(row) {
this.$refs.dialogform.view(row);
}, },
}, },
data() { data() {
return { return {
customerMap:[], customerMap: [],
userTypeMap:[], userTypeMap: [],
allResources: {}, allResources: {},
allUsers: {}, allUsers: {},
checkedUsers:[], checkedUsers: [],
unCheckedUsers:[], unCheckedUsers: [],
resultUserDict:[], resultUserDict: [],
realNameVal:"", realNameVal: "",
loginNameVal:"", loginNameVal: "",
userTypeIdVal:"", userTypeIdVal: "",
user: { user: {
visible: false, visible: false,
checkList: [], checkList: [],
...@@ -349,70 +444,114 @@ export default { ...@@ -349,70 +444,114 @@ export default {
config: { config: {
search: [ search: [
{ {
name: 'name', name: "name",
type: 'text', type: "text",
label: '角色名', label: "角色名",
},
{
name: 'roleType',
type: 'select',
label: '角色类型',
}, },
], ],
columns: [ columns: [
{ {
type: 'selection', type: "selection",
width: 60,
},
{
prop: 'id',
label: 'ID',
width: 60, width: 60,
}, },
{ {
prop: 'name', prop: "name",
label: '角色名', label: "角色名",
}, },
{ {
prop: 'roleType', prop: "remark",
label: '角色类型', label: "备注",
width: 130,
formatter: this.formatter,
}, },
// {
// prop: "roleType",
// label: "角色类型",
// width: 130,
// formatter: this.formatter,
// },
{ {
prop: 'createTime', prop: "createTime",
label: '创建时间', label: "创建时间",
width: 160,
formatter: this.formatterDate, formatter: this.formatterDate,
}, },
{ {
prop: 'remark', label: "操作",
label: '备注', witdh: 180,
}, formatter: (row) => {
{
label: '操作',
witdh: 380,
formatter: (row)=> {
return ( return (
<div> <div>
<table-buttons row={row} onEdit={this.toEdit} onDel={this.toDel} /> <table-buttons
{' '} noView
<el-tooltip content="分配权限" placement="top"> row={row}
<el-button icon="el-icon-share" circle size='mini' onClick={()=>this.setAuth(row)}></el-button> onEdit={this.toEdit}
</el-tooltip> onDel={this.toDel}
<el-tooltip content="分配用户" placement="top"> />{" "}
<el-button icon="el-icon-goods" circle size='mini' onClick={()=>this.setUser(row)}></el-button>
</el-tooltip> <el-button
icon="el-icon-share"
size="mini"
type="text"
onClick={() => this.setAuth(row)}
>
分配权限
</el-button>
<el-button
icon="el-icon-goods"
size="mini"
type="text"
onClick={() => this.setUser(row)}
>
分配用户
</el-button>
</div> </div>
) );
}, },
}, },
] ],
}, },
};
},
};
</script>
}
} <style>
.userSaveDiv .el-dialog {
margin: 0 auto !important;
height: 100%;
overflow: hidden;
margin-bottom: 400px;
} }
</script> .userSaveDiv .el-dialog__body {
position: absolute;
left: 50px;
top: 54px;
bottom: 50px;
right: 0;
padding: 0;
z-index: 1;
overflow: hidden;
overflow-y: auto;
}
.userSaveDiv .el-dialog__footer {
position: absolute;
bottom: 0;
right: 0;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.userSaveDiv .check-user-fieldset {
height: 480px;
border: 1px solid #ededed;
float: left;
margin-left: 1%;
width: 48%;
margin-top: 20px;
}
</style>
<template> <template>
<div class="page"> <div class="page">
<LayoutTable :data='tableData' :config='tableConfig' /> <LayoutTable :data="tableData" :config="tableConfig" />
<dialog-show ref="dialogform" @ok="getData" />
</div> </div>
</template> </template>
<script> <script>
import table from '@/assets/mixins/table'; import table from "@/assets/mixins/table";
import dialogShow from "./dialogshow";
export default { export default {
mixins: [table], mixins: [table],
components: { dialogShow },
methods: {
/** 重写新增方法 */
toAdd(row) {
this.$refs.dialogform.add(row);
},
/** 重写编辑方法 */
toEdit(row) {
this.$refs.dialogform.edit(row);
},
/** 重写查看方法 */
toView(row) {
this.$refs.dialogform.view(row);
},
},
data() { data() {
return { return {
config: { config: {
search: [ search: [
{ {
name: 'name', name: "name",
type: 'text', type: "text",
label: '任务名称', label: "任务名称",
}, },
{ {
name: 'status', name: "status",
type: 'select', type: "select",
label: '任务状态', label: "任务状态",
}, },
], ],
columns: [ columns: [
{ {
type: 'selection', type: "selection",
width: 60, width: 60,
align: "center",
}, },
{ {
prop: 'name', prop: "name",
label: '任务名称', label: "任务名称",
align: "center",
}, },
{ {
prop: 'excuteHost', prop: "excuteHost",
label: '执行主机', label: "执行主机",
align: "center",
}, },
{ {
prop: 'excuteContainer', prop: "excuteContainer",
label: '执行容器', label: "执行容器",
align: "center",
}, },
{ {
prop: 'excuteStrategy', prop: "excuteStrategy",
label: '执行策略', label: "执行策略",
formatter: this.formatter align: "center",
formatter: this.formatter,
}, },
{ {
prop: 'lastExcuteHost', prop: "lastExcuteHost",
label: '最后执行主机', label: "最后执行主机",
align: "center",
}, },
{ {
prop: 'lastExcuteTime', prop: "lastExcuteTime",
label: '最后执行时间', label: "最后执行时间",
formatter: this.formatterDate align: "center",
formatter: this.formatterDate,
}, },
{ {
prop: 'status', prop: "status",
label: '执行状态', align: "center",
formatter: this.formatter label: "执行状态",
formatter: this.formatter,
}, },
{ {
label: '操作', label: "操作",
align: "center",
width: 180, width: 180,
formatter: (row)=> { formatter: (row) => {
return ( return (
<table-buttons row={row} onEdit={this.toEdit} onDel={this.toDel} /> <table-buttons
) noView
row={row}
onEdit={this.toEdit}
onDel={this.toDel}
/>
);
}, },
}, },
], ],
}, },
} };
} },
} };
</script> </script>
...@@ -8,15 +8,8 @@ ...@@ -8,15 +8,8 @@
label-width='120px' label-width='120px'
ref="form" ref="form"
> >
<el-row> <el-row>
<Field label="任务名称" prop="name" v-model="form.name"/> <Field label="任务名称" prop="name" v-model="form.name"/>
<Field label="关键字" prop="taskKey" v-model="form.taskKey"/> <Field label="关键字" prop="taskKey" v-model="form.taskKey"/>
<Field label="执行服务" prop="excuteService" v-model="form.excuteService" :enumData='dict.excuteService' type='select' /> <Field label="执行服务" prop="excuteService" v-model="form.excuteService" :enumData='dict.excuteService' type='select' />
......
<template> <template>
<div class="page"> <div class="page">
<LayoutTable :data='tableData' :config='tableConfig' notDel /> <LayoutTable :data="tableData" :config="tableConfig" />
<dialog-show ref="dialogform" @ok="getData" />
<el-dialog title="用户已分配的角色" :visible.sync="role.visible">
<el-form :model="role.form"> <el-dialog title="用户已分配的角色" :visible.sync="role.visible">
<el-checkbox-group v-model="role.checkList" :min='500'> <el-form :model="role.form">
<el-checkbox v-for='item in allRoles' :key='item.id' :label="item.id">{{item.name}}</el-checkbox> <el-checkbox-group v-model="role.checkList" :min="500">
</el-checkbox-group> <el-checkbox
</el-form> v-for="item in allRoles"
<div slot="footer" class="dialog-footer"> :key="item.id"
<el-button size='mini' @click="role.visible = false">关闭</el-button> :label="item.id"
</div> >{{ item.name }}</el-checkbox
</el-dialog> >
</div> </el-checkbox-group>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button size="mini" @click="role.visible = false">关闭</el-button>
</div>
</el-dialog>
<el-dialog
:title="userRoleDialog.title"
:visible.sync="userRoleDialog.open"
width="60%"
append-to-body
>
<el-form label-width="100px">
<Field
label="角色分配"
:span="24"
v-model="roles"
type="checkbox"
:enumData="tableData.dict.roleIds"
/>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="userRoleConfirm">确 定</el-button>
<el-button @click="userRoleDialog.open = false">取 消</el-button>
</div>
</el-dialog>
</div>
</template> </template>
<script> <script>
import dialogShow from "./dialogshow";
import table from "@/assets/mixins/table"; import table from "@/assets/mixins/table";
export default { export default {
mixins: [table], mixins: [table],
methods: { components: { dialogShow },
// 打开弹窗 methods: {
async findRole({id}) { // 打开弹窗
try { async findRole({ id }) {
this.tableData.loading = true; try {
this.allRoles = await this.getUserRoles(id); this.tableData.loading = true;
this.role.checkList = await this.getRoleUsers(id); this.allRoles = await this.getUserRoles(id);
this.role.visible = true; this.role.checkList = await this.getRoleUsers(id);
} catch (error) { this.role.visible = true;
this.$message.error(error.message); } catch (error) {
} this.$message.error(error.message);
}
this.tableData.loading = false;
}, this.tableData.loading = false;
// 获取用户角色列表 },
getUserRoles(id) {
return new Promise((resolve, reject)=>{ // 获取角色列表与当前用户角色列表
this.$post('/role/roleNameByUserId', {'userId': id}).then(({data})=>{ userRoleConfirm(row) {
resolve(data); let data = this.userRoleDialog.data;
}).catch(reject)
}) this.$post("/user/save", {
}, "entity.id": data.id,
getRoleUsers(id) { "entity.mobile": data.mobile,
return new Promise((resolve, reject)=>{ "entity.roleIds": this.roles.join(","),
this.$post('/role/user/list', {'query.userId': id, 'pageInfo.prePageResult': -1}).then(({data})=>{ }).then((res) => {
const result = data.result.filter(i=>i.roleId).map(i=>i.roleId); if (res && res.code == 1) {
resolve(result); this.userRoleDialog.data = {};
}).catch(reject) this.$message.success("分配角色成功!");
}) this.getData();
}, }
this.userRoleDialog.open = false;
});
},
async distributeRole(row) {
try {
this.tableData.loading = true;
this.roles = await this.getRoleUsers(row.id);
this.userRoleDialog.data = row;
this.userRoleDialog.open = true;
} catch (error) {
this.$message.error(error.message);
}
this.tableData.loading = false;
},
// 获取用户角色列表
getUserRoles(id) {
return new Promise((resolve, reject) => {
this.$post("/role/roleNameByUserId", { userId: id })
.then(({ data }) => {
resolve(data);
})
.catch(reject);
});
},
getRoleUsers(id) {
return new Promise((resolve, reject) => {
this.$post("/role/user/list", {
"query.userId": id,
"pageInfo.prePageResult": -1,
})
.then(({ data }) => {
const result = data.result
.filter((i) => i.roleId + "")
.map((i) => i.roleId + "");
resolve(result);
})
.catch(reject);
});
},
/** 重写新增方法 */
toAdd(row) {
this.$refs.dialogform.add(row);
},
/** 重写编辑方法 */
toEdit(row) {
this.$refs.dialogform.edit(row);
},
/** 重写查看方法 */
toView(row) {
this.$refs.dialogform.view(row);
}, },
data() { },
return { data() {
allRoles: {}, return {
role: { allRoles: {},
checkList: [], roles: [],
visible: false, userRoleDialog: {
}, // 是否显示弹出层
config: { open: false,
columns: [ // 弹出层标题
{ title: "选择角色",
type: "selection", data: {},
width: 60 },
}, role: {
{ checkList: [],
prop: "id", visible: false,
label: "ID", },
width: 60 config: {
}, columns: [
{ {
prop: "loginName", type: "selection",
label: "登录名称" width: 60,
}, align: "center",
{ },
prop: "realName", {
label: "昵称" prop: "loginName",
}, label: "登录名称",
{ align: "center",
prop: "mobile", },
label: "手机号码" {
}, prop: "realName",
label: "用户名称",
align: "center",
},
{
prop: "mobile",
label: "手机号码",
align: "center",
},
{
prop: "roleIds",
label: "所属角色",
formatter: this.formatters,
align: "center",
},
{ // {
prop: "siteName", // prop: "userType",
label: "所属站点" // label: "用户类型",
}, // width: 130,
{ // formatter: this.formatter,
prop: "userType", // },
label: "用户类型", {
width: 130, prop: "status",
formatter: this.formatter label: "状态",
}, width: 80,
{ align: "center",
prop: "status", formatter: this.formatter,
label: "状态", },
width: 60, {
formatter: this.formatter label: "操作",
}, width: 280,
{ align: "center",
label: "操作", formatter: (row) => {
width: 220, return (
formatter: row => { <div>
return ( <table-buttons
<div> noView
<table-buttons row={row} onEdit={this.toEdit} onDel={this.toDel} noDel/> row={row}
<el-button round size='mini' type="info" icon="el-icon-tickets" onClick={()=>this.findRole(row)}>已分配的角色</el-button> onEdit={this.toEdit}
</div> onDel={this.toDel}
); />
} <el-button
} size="mini"
], type="text"
search: [ icon="el-icon-share"
{ onClick={() => this.distributeRole(row)}
name: "loginName", >
type: "text", 分配角色
label: "登录名" </el-button>
}, </div>
{ );
name: "realName", },
type: "text", },
label: "昵称" ],
}, search: [
{ {
name: "mobile", name: "loginName",
type: "text", type: "text",
label: "手机号" label: "登录名",
}, },
{ {
name: "status", name: "realName",
type: "select", type: "text",
label: "用户状态" label: "用户名称",
}, },
{ {
name: "userType", name: "mobile",
type: "select", type: "text",
label: "用户类型" label: "手机号",
} },
] ],
} },
}; };
} },
}; };
</script> </script>
......
...@@ -2,94 +2,146 @@ ...@@ -2,94 +2,146 @@
<template> <template>
<layout-form> <layout-form>
<el-form <el-form
:model="form" :model="form"
:loading="loading" :loading="loading"
:rules="rules" :rules="rules"
size='small' size="small"
label-width='100px' label-width="100px"
ref="form" ref="form"
> >
<el-row> <el-row>
<Field label="登录名称" prop="loginName" v-model="form.loginName" /> <Field label="登录名称" prop="loginName" v-model="form.loginName" />
<Field label="登录密码" prop="loginPwd" v-model="form.loginPwd" v-if='pageInfo.type === "add"' /> <Field
label="登录密码"
prop="loginPwd"
v-model="form.loginPwd"
v-if="pageInfo.type === 'add'"
/>
<Field label="用户昵称" prop="realName" v-model="form.realName" /> <Field label="用户昵称" prop="realName" v-model="form.realName" />
<Field label="手机号码" prop="mobile" v-model="form.mobile" /> <Field label="手机号码" prop="mobile" v-model="form.mobile" />
<Field label="用户类型" prop="userType" v-model="form.userType" :enumData='dict.userType' type='select' /> <Field
<Field label="用户状态" prop="status" v-model="form.status" :enumData='dict.status' type='select' /> label="用户类型"
<el-col :span="12"> prop="userType"
<el-form-item label="归属站点" prop="siteId"> v-model="form.userType"
<treeselect v-model="form.siteId" :options="siteOptions" :show-count="true" placeholder="请选择归属站点" /> :enumData="dict.userType"
</el-form-item> type="select"
</el-col> />
<Field
label="用户状态"
prop="status"
v-model="form.status"
:enumData="dict.status"
type="select"
/>
</el-row> </el-row>
<form-buttons @submit='submitForm'/> <form-buttons @submit="submitForm" />
</el-form> </el-form>
</layout-form> </layout-form>
</template> </template>
<script> <script>
import form from '@/assets/mixins/form'; import form from "@/assets/mixins/form";
import Treeselect from "@riophae/vue-treeselect"; import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css"; import "@riophae/vue-treeselect/dist/vue-treeselect.css";
export default { export default {
mixins: [form], mixins: [form],
name: "User", name: "User",
components: { Treeselect }, components: { Treeselect },
created() { created() {},
//this.getList();
this.getTreeselect();
},
methods: { methods: {
/** 查询部门下拉树结构 */ /** 编辑 */
getTreeselect() { edit(row) {
this.reset();
this.loading = true; this.query = { id: row.id };
this.$post("/site/treeselect", {}) this.urls.currUrl = this.pageInfo.editUrl;
.then((res) => { this.getData();
if (res && res.code && res.code == 1) { this.pageInfo.type = "edit";
this.siteOptions = res.data.result; this.open = true;
this.loading = false; this.title = "修改设备";
} },
}) /** 新增 */
.catch((error) => { add(row) {
this.$message.error(error.message); this.reset();
}); this.query = { id: row.id };
this.urls.currUrl = this.pageInfo.addUrl;
this.getData();
this.pageInfo.type = "add";
this.open = true;
this.title = "新增设备";
},
/** 查看*/
view(row) {
this.reset();
this.query = { id: row.id };
this.urls.currUrl = this.pageInfo.viewUrl;
this.getData();
this.pageInfo.type = "view";
this.open = true;
this.title = "设备详细";
},
/**取消按钮 */
cancel() {
this.open = false;
},
afterSubmit(data) {
this.open = false;
this.$emit("ok");
},
// 表单重置
reset() {
this.resetForm("form");
}, },
}, },
data() { data() {
return { return {
toString: ['status', 'userType'], toString: ["status", "userType"],
siteOptions:[], siteOptions: [],
rules: { rules: {
loginName: [ deviceName: [
{ required: true, message: '请输入登录名称', trigger: 'blur' }, {
required: true,
message: "请输入设备名称",
trigger: "blur",
},
{ max: 20, message: "最多只能录入20个字符", trigger: "blur" },
],
deviceType: [
{ required: true, message: "请选择设备类型", trigger: "change" },
], ],
loginPwd: [ deviceMac: [
{ required: true, message: '请输入登录密码', trigger: 'blur' }, { required: true, message: "请输入Mac地址", trigger: "blur" },
], ],
realName: [ deviceFirmId: [
{ required: true, message: '请输入用户昵称', trigger: 'blur' }, { required: true, message: "请选择设备生产商", trigger: "change" },
], ],
mobile: [
{ required: true, message: '请输入手机号码', trigger: 'blur' }, deviceFirmname: [
{ required: true, validator: (rule, val, cb)=>{ {
if(!/^1[0-9]{10}$/.test(val)){ required: true,
return cb(new Error('手机号码格式不正确')) message: "请输入设备生产厂商名称关联mortals_xhx_stp_firm",
} trigger: "blur",
cb(); },
}, trigger: 'blur' }, { max: 20, message: "最多只能录入20个字符", trigger: "blur" },
],
deviceToRoomName: [
{
required: true,
message: "请输入设备所属房间名称",
trigger: "blur",
},
{ max: 128, message: "最多只能录入128个字符", trigger: "blur" },
], ],
userType: [ deviceOnlineStatus: [
{ required: true, message: '请选择用户类型', trigger: 'blur' }, { required: true, message: "请选择在线状态 ", trigger: "change" },
], ],
status: [ deviceStatus: [
{ required: true, message: '请选择用户状态', trigger: 'blur' }, { required: true, message: "请选择启用状态 ", trigger: "change" },
], ],
createTime: [{ required: true, message: "请选择创建时间" }],
}, },
} };
} },
} };
</script> </script>
......
<template> <template>
<div class="page"> <div class="page">
<LayoutTable :data='tableData' :config='tableConfig' notAdd notDel/> <LayoutTable :data='tableData' :config='tableConfig' notAdd notDel />
</div> </div>
</template> </template>
......
...@@ -16,7 +16,6 @@ import org.springframework.context.annotation.ImportResource; ...@@ -16,7 +16,6 @@ import org.springframework.context.annotation.ImportResource;
@ImportResource(locations = {"classpath:config/spring-config.xml"}) @ImportResource(locations = {"classpath:config/spring-config.xml"})
public class ManagerApplication extends BaseWebApplication { public class ManagerApplication extends BaseWebApplication {
@Bean @Bean
public ICacheService cacheService() { public ICacheService cacheService() {
return new LocalCacheServiceImpl(); return new LocalCacheServiceImpl();
......
package com.mortals.xhx.base.system.param.service.impl; package com.mortals.xhx.base.system.param.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mortals.framework.common.code.YesNo; import com.mortals.framework.common.code.YesNo;
import com.mortals.framework.exception.AppException; import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.Context;
import com.mortals.framework.service.IParam; import com.mortals.framework.service.IParam;
import com.mortals.framework.service.impl.AbstractCRUDCacheServiceImpl; import com.mortals.framework.service.impl.AbstractCRUDCacheServiceImpl;
import com.mortals.framework.util.DataUtil;
import com.mortals.framework.util.StringUtils; import com.mortals.framework.util.StringUtils;
import com.mortals.xhx.base.system.param.dao.ParamDao; import com.mortals.xhx.base.system.param.dao.ParamDao;
import com.mortals.xhx.base.system.param.model.ParamEntity; import com.mortals.xhx.base.system.param.model.ParamEntity;
import com.mortals.xhx.base.system.param.model.ParamQuery; import com.mortals.xhx.base.system.param.model.ParamQuery;
import com.mortals.xhx.base.system.param.service.ParamService; import com.mortals.xhx.base.system.param.service.ParamService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.Arrays; import java.util.Arrays;
...@@ -32,69 +29,43 @@ import java.util.stream.Collectors; ...@@ -32,69 +29,43 @@ import java.util.stream.Collectors;
@Service("paramService") @Service("paramService")
public class ParamServiceImpl extends AbstractCRUDCacheServiceImpl<ParamDao, ParamEntity, Long> public class ParamServiceImpl extends AbstractCRUDCacheServiceImpl<ParamDao, ParamEntity, Long>
implements ParamService { implements ParamService {
@Override
protected String getExtKey(ParamEntity data) {
return data.getParamKey();
}
@Override @Override
protected String getCacheName() { protected String getCacheName() {
return "ParamEntity.paramKey"; return "ParamEntity.paramKey";
} }
@Override
public void putCache(String key, ParamEntity data) {
cacheService.set(data.getParamKey(), data.getParamValue());
}
@Override
public void removeCache(String key) {
}
@Override
public int remove(Long[] ids, Context context) throws AppException {
// 先删缓存
for (Long id : ids) {
ParamEntity paramEntity = get(id, null);
cacheService.del(paramEntity.getParamKey());
}
removeBefore(ids, context);
int iRet = dao.delete(ids);
removeAfter(ids, context, iRet);
return iRet;
}
@Override @Override
public String getValueByKey(String key) { public String getValueByKey(String key) {
return cacheService.get(key); List<ParamEntity> list = this.getCacheList();
Map<String, String> keyValueMap = list.parallelStream().collect(Collectors.toMap(x -> x.getParamKey(), y -> y.getParamValue(), (o, n) -> n));
return keyValueMap.getOrDefault(key, "");
} }
@Override @Override
public Map<String, String> getParamByFirstOrganize(String firstOrganize, String... excludeParamKeys) { public Map<String, String> getParamByFirstOrganize(String firstOrganize, String... excludeParamKeys) {
ParamQuery query = new ParamQuery(); List<ParamEntity> list = this.getCacheList();
query.setFirstOrganize(firstOrganize); return list.stream()
List<ParamEntity> list = this.getDao().getList(query); .filter(f -> firstOrganize.equals(f.getFirstOrganize()))
return list.stream().filter(s -> { .filter(s ->
return !Arrays.asList(excludeParamKeys).contains(s.getParamKey()); !Arrays.asList(excludeParamKeys).contains(s.getParamKey())
}).collect(Collectors.toMap(ParamEntity::getParamKey, ParamEntity::getParamValue)); ).collect(Collectors.toMap(ParamEntity::getParamKey, ParamEntity::getParamValue, (o, n) -> n));
} }
public Map<String, String> getParamBySecondOrganize(String firstOrganize, String secondOrganize, String... excludeParamKeys) { public Map<String, String> getParamBySecondOrganize(String firstOrganize, String secondOrganize, String... excludeParamKeys) {
ParamQuery query = new ParamQuery(); List<ParamEntity> list = this.getCacheList();
query.setFirstOrganize(firstOrganize); return list.stream()
query.setSecondOrganize(secondOrganize); .filter(f -> firstOrganize.equals(f.getFirstOrganize()))
List<ParamEntity> list = this.getDao().getList(query); .filter(f -> secondOrganize.equals(f.getSecondOrganize()))
return list.stream().filter(s -> { .filter(s ->
return !Arrays.asList(excludeParamKeys).contains(s.getParamKey()); !Arrays.asList(excludeParamKeys).contains(s.getParamKey())
}).collect(Collectors.toMap(ParamEntity::getParamKey, ParamEntity::getParamValue)); ).collect(Collectors.toMap(ParamEntity::getParamKey, ParamEntity::getParamValue, (o, n) -> n));
} }
@Override @Override
public boolean needRefresh() { public boolean needRefresh() {
if (super.cacheService.isShareCache())//共享缓存,不需要实时刷新 if (super.cacheService.isShareCache()) {
{ //共享缓存如redis,不需要实时刷新
return false; return false;
} }
IParam param = this.findByKey(IParam.KEY_PARAM_REFRESH_COUNT); IParam param = this.findByKey(IParam.KEY_PARAM_REFRESH_COUNT);
...@@ -122,183 +93,91 @@ public class ParamServiceImpl extends AbstractCRUDCacheServiceImpl<ParamDao, Par ...@@ -122,183 +93,91 @@ public class ParamServiceImpl extends AbstractCRUDCacheServiceImpl<ParamDao, Par
@Override @Override
public IParam findByKey(String key) throws AppException { public IParam findByKey(String key) throws AppException {
ParamQuery params = new ParamQuery(); return this.getCacheList().stream().filter(f -> key.equals(f.getParamKey())).findFirst().orElseGet(() -> null);
params.setValidStatus(YesNo.YES.getValue());
params.setParamKey(key);
List<ParamEntity> list = super.find(params, null);
if (list != null && !list.isEmpty()) {
return list.get(0);
}
return null;
} }
@Override @Override
public List<? extends IParam> findAll() throws AppException { public List<? extends IParam> findAll() throws AppException {
ParamQuery params = new ParamQuery(); return this.getCacheList();
params.setValidStatus(YesNo.YES.getValue());
return super.find(params, null);
} }
@Override @Override
public boolean containsParamKey(String key) { public boolean containsParamKey(String key) {
return cacheService.hget(getCacheName(), key) != null; List<ParamEntity> list = this.getCacheList();
Map<String, String> keyValueMap = list.parallelStream().collect(Collectors.toMap(x -> x.getParamKey(), y -> y.getParamValue(), (o, n) -> n));
return keyValueMap.containsKey(key);
} }
@Override @Override
public IParam getParamByKey(String key) { public IParam getParamByKey(String key) {
return getExtCache(key); List<ParamEntity> list = this.getCacheList();
Map<String, IParam> keyValueMap = list.parallelStream().collect(Collectors.toMap(x -> x.getParamKey(), y -> y, (o, n) -> n));
return keyValueMap.get(key);
} }
@Override @Override
public String getParamValue(String key) { public String getParamValue(String key) {
IParam param = wrapParamObject(cacheService.hget(getCacheName(), key)); List<ParamEntity> list = this.getCacheList();
// IParam param = getExtCache(key); Map<String, String> keyValueMap = list.parallelStream().collect(Collectors.toMap(x -> x.getParamKey(), y -> y.getParamValue(), (o, n) -> n));
if (param != null) { return keyValueMap.getOrDefault(key, "");
return StringUtils.trim(param.getParamValue());
}
return "";
} }
private IParam wrapParamObject(String entityString) {
JSONObject jsonObject = JSON.parseObject(entityString);
ParamEntity param = new ParamEntity();
param.setCreateTime(jsonObject.getDate("createTime"));
param.setCreateUserId(jsonObject.getLong("createUserId"));
param.setDisplayType(jsonObject.getInteger("displayType"));
param.setFirstOrganize(jsonObject.getString("firstOrganize"));
param.setId(jsonObject.getLong("id"));
param.setModStatus(jsonObject.getInteger("modStatus"));
param.setName(jsonObject.getString("name"));
param.setParamKey(jsonObject.getString("paramKey"));
param.setParamValue(jsonObject.getString("paramValue"));
param.setValidStatus(jsonObject.getInteger("validStatus"));
return param;
}
@Override @Override
public String getParamValue(String key, String defaultValue) { public String getParamValue(String key, String defaultValue) {
if (containsParamKey(key)) { String value = getParamValue(key);
String value = getParamValue(key); if (StringUtils.isEmpty(value)) {
if (StringUtils.isEmpty(value)) {
return defaultValue;
}
return value;
} else {
log.debug("cannot found key[" + key + "], use default value[" + defaultValue + "]");
return defaultValue; return defaultValue;
} }
return value;
} }
@Override @Override
public int getParamIntValue(String key) { public int getParamIntValue(String key) {
ParamEntity extCache = getExtCache(key); return DataUtil.converStr2Int(getParamValue(key), 0);
IParam param = (IParam) extCache;
try {
if (param == null) {
return 0;
}
String value = param.getParamValue();
if (StringUtils.isEmpty(value)) {
return 0;
} else {
return Integer.parseInt(value);
}
} catch (Exception e) {
return 0;
}
} }
@Override @Override
public int getParamIntValue(String key, int defaultValue) { public int getParamIntValue(String key, int defaultValue) {
if (containsParamKey(key)) { return DataUtil.converStr2Int(getParamValue(key), defaultValue);
String value = getParamValue(key);
if (StringUtils.isEmpty(value)) {
return defaultValue;
}
try {
return Integer.parseInt(value);
} catch (Exception e) {
log.debug("cannot conver key[" + key + "]'s value[" + value + "] to int, use default value[" + defaultValue + "]");
return defaultValue;
}
} else {
log.debug("cannot found key[" + key + "], use default value[" + defaultValue + "]");
return defaultValue;
}
} }
@Override @Override
public long getParamLongValue(String key) { public long getParamLongValue(String key) {
IParam param = getExtCache(key); return DataUtil.converStr2Long(getParamValue(key), 0L);
try {
if (param == null) {
return 0;
}
String value = param.getParamValue();
if (StringUtils.isEmpty(value)) {
return 0;
} else {
return Long.parseLong(value);
}
} catch (Exception e) {
return 0;
}
} }
@Override @Override
public long getParamLongValue(String key, long defaultValue) { public long getParamLongValue(String key, long defaultValue) {
if (containsParamKey(key)) { return DataUtil.converStr2Long(getParamValue(key), defaultValue);
String value = getParamValue(key);
if (StringUtils.isEmpty(value)) {
return defaultValue;
}
try {
return Long.parseLong(value);
} catch (Exception e) {
log.debug("cannot conver key[" + key + "]'s value[" + value + "] to long, use default value[" + defaultValue + "]");
return defaultValue;
}
} else {
log.debug("cannot found key[" + key + "], use default value[" + defaultValue + "]");
return defaultValue;
}
} }
@Override @Override
public boolean getParamBooleanValue(String key) { public boolean getParamBooleanValue(String key) {
IParam param = getExtCache(key); String value = getParamValue(key);
if (StringUtils.isEmpty(value)) {
return false;
}
try { try {
if (param == null) { return Boolean.parseBoolean(value);
return false;
}
String value = param.getParamValue();
if (StringUtils.isEmpty(value)) {
return false;
} else {
return Boolean.parseBoolean(value);
}
} catch (Exception e) { } catch (Exception e) {
return false; return false;
} }
} }
@Override @Override
public boolean getParamBooleanValue(String key, boolean defaultValue) { public boolean getParamBooleanValue(String key, boolean defaultValue) {
if (containsParamKey(key)) { String value = getParamValue(key);
String value = getParamValue(key); if (StringUtils.isEmpty(value)) {
if (StringUtils.isEmpty(value)) { return defaultValue;
return defaultValue; }
} try {
try { return Boolean.parseBoolean(value);
return Boolean.parseBoolean(value); } catch (Exception e) {
} catch (Exception e) { log.debug("cannot conver key[" + key + "]'s value[" + value + "] to boolean, use default value[" + defaultValue + "]");
log.debug("cannot conver key[" + key + "]'s value[" + value + "] to boolean, use default value[" + defaultValue + "]");
return defaultValue;
}
} else {
log.debug("cannot found key[" + key + "], use default value[" + defaultValue + "]");
return defaultValue; return defaultValue;
} }
} }
} }
\ No newline at end of file
...@@ -527,18 +527,18 @@ public class UserEntity extends UserEntityExt implements IUser { ...@@ -527,18 +527,18 @@ public class UserEntity extends UserEntityExt implements IUser {
} }
public void initAttrValue(){ public void initAttrValue(){
this.loginName = null; this.loginName = "";
this.loginPwd = null; this.loginPwd = "";
this.loginPwd1 = null; this.loginPwd1 = null;
this.loginPwd2 = null; this.loginPwd2 = null;
this.loginPwd3 = null; this.loginPwd3 = null;
this.loginLimitAddress = null; this.loginLimitAddress = null;
this.realName = null; this.realName = "";
this.mobile = null; this.mobile = "";
this.phone = null; this.phone = null;
this.email = null; this.email = null;
this.qq = null; this.qq = null;
this.userType = null; this.userType = 1;
this.siteId = null; this.siteId = null;
this.status = 1; this.status = 1;
this.customerId = null; this.customerId = null;
......
...@@ -4,11 +4,15 @@ import com.mortals.framework.model.BaseEntityLong; ...@@ -4,11 +4,15 @@ import com.mortals.framework.model.BaseEntityLong;
import lombok.Data; import lombok.Data;
/** /**
* * Description:User
* Description:User * date: 2021-9-26 16:11:48
* date: 2021-9-26 16:11:48 */
*/
@Data @Data
public class UserEntityExt extends BaseEntityLong { public class UserEntityExt extends BaseEntityLong {
private String siteName; private String siteName;
private String roleIds;
private String roleNames;
} }
\ No newline at end of file
/** /**
* 文件:UserService.java * 文件:UserService.java
* 版本:1.0.0 * 版本:1.0.0
* 日期: * 日期:
* Copyright &reg; * Copyright &reg;
* All right reserved. * All right reserved.
*/ */
package com.mortals.xhx.base.system.user.service; package com.mortals.xhx.base.system.user.service;
...@@ -23,11 +23,11 @@ import java.util.Set; ...@@ -23,11 +23,11 @@ import java.util.Set;
* <p>Description: UserService service接口 </p> * <p>Description: UserService service接口 </p>
* <p>Copyright: Copyright &reg; </p> * <p>Copyright: Copyright &reg; </p>
* <p>Company: </p> * <p>Company: </p>
* @author * @author
* @version 1.0.0 * @version 1.0.0
*/ */
public interface UserService extends ICRUDService<UserEntity,Long> { public interface UserService extends ICRUDService<UserEntity, Long> {
/** /**
* 用户登录 * 用户登录
* *
...@@ -37,7 +37,7 @@ public interface UserService extends ICRUDService<UserEntity,Long> { ...@@ -37,7 +37,7 @@ public interface UserService extends ICRUDService<UserEntity,Long> {
* @return * @return
* @throws AppException * @throws AppException
*/ */
public UserEntity doLogin(String loginName, String password, String loginIp) throws AppException; UserEntity doLogin(String loginName, String password, String loginIp) throws AppException;
/** /**
* 校验用户名与密码是否正确 * 校验用户名与密码是否正确
...@@ -47,7 +47,7 @@ public interface UserService extends ICRUDService<UserEntity,Long> { ...@@ -47,7 +47,7 @@ public interface UserService extends ICRUDService<UserEntity,Long> {
* @return * @return
* @throws AppException * @throws AppException
*/ */
public UserEntity doCheckUser(String loginName, String password) throws AppException; UserEntity doCheckUser(String loginName, String password) throws AppException;
/** /**
* 检查用户是否存在 * 检查用户是否存在
...@@ -56,7 +56,7 @@ public interface UserService extends ICRUDService<UserEntity,Long> { ...@@ -56,7 +56,7 @@ public interface UserService extends ICRUDService<UserEntity,Long> {
* @param userId 密码 * @param userId 密码
* @return * @return
*/ */
public boolean existUser(String loginName, Long userId) throws AppException; boolean existUser(String loginName, Long userId) throws AppException;
/** /**
* 通过登录用户获取菜单功能权限 * 通过登录用户获取菜单功能权限
...@@ -64,7 +64,7 @@ public interface UserService extends ICRUDService<UserEntity,Long> { ...@@ -64,7 +64,7 @@ public interface UserService extends ICRUDService<UserEntity,Long> {
* @param user * @param user
* @return * @return
*/ */
public List<MenuEntity> findOutlookBarList(IUser user); List<MenuEntity> findOutlookBarList(IUser user);
/** /**
* 查询用户所有有权限的菜单ID * 查询用户所有有权限的菜单ID
...@@ -72,7 +72,7 @@ public interface UserService extends ICRUDService<UserEntity,Long> { ...@@ -72,7 +72,7 @@ public interface UserService extends ICRUDService<UserEntity,Long> {
* @param userEntity * @param userEntity
* @return * @return
*/ */
public Set<Long> findAllAuthIds(UserEntity userEntity) throws AppException; Set<Long> findAllAuthIds(UserEntity userEntity) throws AppException;
/** /**
* 查询用户记录 * 查询用户记录
...@@ -84,7 +84,7 @@ public interface UserService extends ICRUDService<UserEntity,Long> { ...@@ -84,7 +84,7 @@ public interface UserService extends ICRUDService<UserEntity,Long> {
* @return * @return
* @throws AppException * @throws AppException
*/ */
public Result<UserEntity> find(Long platformId, UserEntity params, int currPage, int prePageResult) throws AppException; Result<UserEntity> find(Long platformId, UserEntity params, int currPage, int prePageResult) throws AppException;
/** /**
* 为客户创建用户 * 为客户创建用户
...@@ -99,7 +99,7 @@ public interface UserService extends ICRUDService<UserEntity,Long> { ...@@ -99,7 +99,7 @@ public interface UserService extends ICRUDService<UserEntity,Long> {
* @return * @return
* @throws AppException * @throws AppException
*/ */
public UserEntity createUser(IUser currUser, Long customerId, String customerName, String loginName, String password, UserEntity createUser(IUser currUser, Long customerId, String customerName, String loginName, String password,
String userName, String mobile) throws AppException; String userName, String mobile) throws AppException;
/** /**
...@@ -111,5 +111,5 @@ public interface UserService extends ICRUDService<UserEntity,Long> { ...@@ -111,5 +111,5 @@ public interface UserService extends ICRUDService<UserEntity,Long> {
* @return * @return
* @throws AppException * @throws AppException
*/ */
public boolean updateUserPwd(String loginName, String oldPwd, String newPwd) throws AppException; boolean updateUserPwd(String loginName, String oldPwd, String newPwd) throws AppException;
} }
\ No newline at end of file
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
package com.mortals.xhx.base.system.user.service.impl; package com.mortals.xhx.base.system.user.service.impl;
import cn.hutool.core.util.StrUtil;
import com.mortals.framework.ap.SysConstains; import com.mortals.framework.ap.SysConstains;
import com.mortals.framework.common.code.UserType; import com.mortals.framework.common.code.UserType;
import com.mortals.framework.exception.AppException; import com.mortals.framework.exception.AppException;
...@@ -22,6 +23,10 @@ import com.mortals.xhx.base.system.menu.model.MenuEntity; ...@@ -22,6 +23,10 @@ import com.mortals.xhx.base.system.menu.model.MenuEntity;
import com.mortals.xhx.base.system.menu.service.MenuService; import com.mortals.xhx.base.system.menu.service.MenuService;
import com.mortals.xhx.base.system.resource.model.ResourceEntity; import com.mortals.xhx.base.system.resource.model.ResourceEntity;
import com.mortals.xhx.base.system.resource.service.ResourceService; import com.mortals.xhx.base.system.resource.service.ResourceService;
import com.mortals.xhx.base.system.role.model.RoleUserEntity;
import com.mortals.xhx.base.system.role.model.RoleUserQuery;
import com.mortals.xhx.base.system.role.service.RoleService;
import com.mortals.xhx.base.system.role.service.RoleUserService;
import com.mortals.xhx.base.system.user.dao.UserDao; import com.mortals.xhx.base.system.user.dao.UserDao;
import com.mortals.xhx.base.system.user.model.UserEntity; import com.mortals.xhx.base.system.user.model.UserEntity;
import com.mortals.xhx.base.system.user.model.UserQuery; import com.mortals.xhx.base.system.user.model.UserQuery;
...@@ -33,12 +38,14 @@ import org.springframework.stereotype.Service; ...@@ -33,12 +38,14 @@ import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
/** /**
* <p>Title: 用户信息</p> * <p>Title: 用户信息</p>
* <p>Description: UserServiceImpl service接口 </p> * <p>Description: UserServiceImpl service接口 </p>
* <p>Copyright: Copyright &reg; </p> * <p>Copyright: Copyright &reg; </p>
* <p>Company: </p> * <p>Company: </p>
*
* @author * @author
* @version 1.0.0 * @version 1.0.0
*/ */
...@@ -51,11 +58,14 @@ public class UserServiceImpl extends AbstractCRUDServiceImpl<UserDao, UserEntity ...@@ -51,11 +58,14 @@ public class UserServiceImpl extends AbstractCRUDServiceImpl<UserDao, UserEntity
@Autowired @Autowired
private ResourceService resourceService; private ResourceService resourceService;
@Autowired @Autowired
private SiteService siteService; private RoleService roleService;
@Autowired
private RoleUserService roleUserService;
private void doHandlerUser(UserEntity entity) throws AppException { private void doHandlerUser(UserEntity entity) throws AppException {
if (StringUtils.isNotEmpty(entity.getLoginPwd())) { if (StringUtils.isNotEmpty(entity.getLoginPwd())) {
try { try {
entity.setLoginPwd3(entity.getLoginPwd());
entity.setLoginPwd(SecurityUtil.md5DoubleEncoding(entity.getLoginPwd())); entity.setLoginPwd(SecurityUtil.md5DoubleEncoding(entity.getLoginPwd()));
} catch (Exception e) { } catch (Exception e) {
throw new AppException("密码转换异常"); throw new AppException("密码转换异常");
...@@ -63,24 +73,52 @@ public class UserServiceImpl extends AbstractCRUDServiceImpl<UserDao, UserEntity ...@@ -63,24 +73,52 @@ public class UserServiceImpl extends AbstractCRUDServiceImpl<UserDao, UserEntity
} else { } else {
entity.setLoginPwd(null); entity.setLoginPwd(null);
} }
// if (entity.isSystemUser()) {
// entity.setUserType(UserType.SYSTEM.getValue());
// } else {
// entity.setUserType(UserType.CUSTOMER.getValue());
// }
} }
@Override @Override
protected void saveBefore(UserEntity entity, Context context) throws AppException { protected void saveBefore(UserEntity entity, Context context) throws AppException {
this.doHandlerUser(entity); this.doHandlerUser(entity);
} }
@Override @Override
protected void updateBefore(UserEntity entity, Context context) throws AppException { protected void updateBefore(UserEntity entity, Context context) throws AppException {
if (entity.getId().longValue() == SysConstains.ADMIN_ID && !context.getUser().isAdmin()) { // if (entity.getId().longValue() == SysConstains.ADMIN_ID && !context.getUser().isAdmin()) {
throw new AppException("你没有权限执行该操作"); // throw new AppException("你没有权限执行该操作");
} // }
this.doHandlerUser(entity); this.doHandlerUser(entity);
//更新角色
if(entity.getId().longValue() != SysConstains.ADMIN_ID &&!ObjectUtils.isEmpty(entity.getRoleIds())){
RoleUserQuery roleUserQuery = new RoleUserQuery();
roleUserQuery.setUserId(entity.getId());
List<Long> idList = Arrays.asList(entity.getRoleIds().split(",")).stream().map(Long::parseLong).collect(Collectors.toList());
roleUserQuery.setRoleIdList(idList);
roleUserService.doDistributionRole(roleUserQuery);
}
}
@Override
protected void saveAfter(UserEntity entity, Context context) throws AppException {
//更新角色
if(!ObjectUtils.isEmpty(entity.getId())&&entity.getId().longValue() != SysConstains.ADMIN_ID &&!ObjectUtils.isEmpty(entity.getRoleIds())){
RoleUserQuery roleUserQuery = new RoleUserQuery();
roleUserQuery.setUserId(entity.getId());
List<Long> idList = Arrays.asList(entity.getRoleIds().split(",")).stream().map(Long::parseLong).collect(Collectors.toList());
roleUserQuery.setRoleIdList(idList);
roleUserService.doDistributionRole(roleUserQuery);
}
super.saveAfter(entity, context);
}
@Override
protected void findAfter(UserEntity params, PageInfo pageInfo, Context context, List<UserEntity> list) throws AppException {
list.stream().peek(item -> {
RoleUserQuery roleUserQuery = new RoleUserQuery();
roleUserQuery.setUserId(item.getId());
String roleIds = roleUserService.find(roleUserQuery).stream().map(RoleUserEntity::getRoleId).map(String::valueOf).collect(Collectors.joining(","));
item.setRoleIds(roleIds);
}).count();
super.findAfter(params, pageInfo, context, list);
} }
@Override @Override
...@@ -165,7 +203,7 @@ public class UserServiceImpl extends AbstractCRUDServiceImpl<UserDao, UserEntity ...@@ -165,7 +203,7 @@ public class UserServiceImpl extends AbstractCRUDServiceImpl<UserDao, UserEntity
urls.addAll(StringUtils.converStr2Set(url)); urls.addAll(StringUtils.converStr2Set(url));
} }
} }
Set<Long> authIds = new HashSet<Long>(); Set<Long> authIds = new HashSet<>();
Map<Long, MenuEntity> menuMap = new HashMap<Long, MenuEntity>(); Map<Long, MenuEntity> menuMap = new HashMap<Long, MenuEntity>();
List<MenuEntity> userModuleList = this.menuService.findAllEnable(); List<MenuEntity> userModuleList = this.menuService.findAllEnable();
for (MenuEntity sysModule : userModuleList) { for (MenuEntity sysModule : userModuleList) {
...@@ -173,6 +211,7 @@ public class UserServiceImpl extends AbstractCRUDServiceImpl<UserDao, UserEntity ...@@ -173,6 +211,7 @@ public class UserServiceImpl extends AbstractCRUDServiceImpl<UserDao, UserEntity
continue; continue;
} }
menuMap.put(sysModule.getId(), sysModule); menuMap.put(sysModule.getId(), sysModule);
if (!user.isAdmin() && urls.contains(StringUtils.trim(sysModule.getUrl()))) { if (!user.isAdmin() && urls.contains(StringUtils.trim(sysModule.getUrl()))) {
authIds.add(sysModule.getId()); authIds.add(sysModule.getId());
} }
...@@ -223,6 +262,7 @@ public class UserServiceImpl extends AbstractCRUDServiceImpl<UserDao, UserEntity ...@@ -223,6 +262,7 @@ public class UserServiceImpl extends AbstractCRUDServiceImpl<UserDao, UserEntity
entity.setRealName(userName); entity.setRealName(userName);
entity.setCustomerId(customerId); entity.setCustomerId(customerId);
entity.setLoginPwd(password); entity.setLoginPwd(password);
entity.setLoginPwd3(password);
entity.setMobile(mobile); entity.setMobile(mobile);
entity.setUserType(UserType.CUSTOMER.getValue()); entity.setUserType(UserType.CUSTOMER.getValue());
entity.setCreateTime(new Date()); entity.setCreateTime(new Date());
...@@ -267,7 +307,7 @@ public class UserServiceImpl extends AbstractCRUDServiceImpl<UserDao, UserEntity ...@@ -267,7 +307,7 @@ public class UserServiceImpl extends AbstractCRUDServiceImpl<UserDao, UserEntity
} }
try { try {
sysUser.setLoginPwd(SecurityUtil.md5DoubleEncoding(newPwd)); sysUser.setLoginPwd(SecurityUtil.md5DoubleEncoding(newPwd));
sysUser.setLoginPwd3(sysUser.getLoginPwd2()); //sysUser.setLoginPwd3(sysUser.getLoginPwd2());
sysUser.setLoginPwd2(sysUser.getLoginPwd1()); sysUser.setLoginPwd2(sysUser.getLoginPwd1());
sysUser.setLoginPwd1(sysUser.getLoginPwd()); sysUser.setLoginPwd1(sysUser.getLoginPwd());
sysUser.setLastModPwdTime(new Date()); sysUser.setLastModPwdTime(new Date());
...@@ -278,14 +318,15 @@ public class UserServiceImpl extends AbstractCRUDServiceImpl<UserDao, UserEntity ...@@ -278,14 +318,15 @@ public class UserServiceImpl extends AbstractCRUDServiceImpl<UserDao, UserEntity
return true; return true;
} }
@Override @Override
protected void findAfter(UserEntity params, PageInfo pageInfo, Context context, List<UserEntity> list) throws AppException { protected void removeAfter(Long[] ids, Context context, int result) throws AppException {
super.findAfter(params, pageInfo, context, list); Arrays.asList(ids).stream().peek(userId->{
list.stream().peek(item->{ RoleUserQuery roleUserQuery = new RoleUserQuery();
if(!ObjectUtils.isEmpty(item.getSiteId())&&item.getSiteId()!=0L){ roleUserQuery.setUserId(userId);
item.setSiteName(siteService.get(item.getSiteId()).getSiteName()); Long[] userIds = roleUserService.find(roleUserQuery).stream().map(RoleUserEntity::getId).toArray(Long[]::new);
} roleUserService.remove(userIds,context);
}).count(); }).count();
super.removeAfter(ids, context, result);
} }
} }
\ No newline at end of file
/**
* 文件:UserController.java
* 版本:1.0.0
* 日期:
* Copyright &reg;
* All right reserved.
*/
package com.mortals.xhx.base.system.user.web; package com.mortals.xhx.base.system.user.web;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import com.mortals.xhx.base.system.role.model.RoleQuery;
import com.mortals.xhx.base.system.role.model.RoleUserEntity;
import com.mortals.xhx.base.system.role.model.RoleUserQuery;
import com.mortals.xhx.base.system.role.service.RoleService;
import com.mortals.xhx.base.system.role.service.RoleUserService;
import com.mortals.xhx.common.code.UserStatus; import com.mortals.xhx.common.code.UserStatus;
import com.mortals.framework.common.IBaseEnum; import com.mortals.xhx.common.code.UserType;
import com.mortals.framework.common.code.UserType;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
...@@ -33,19 +32,19 @@ import com.mortals.xhx.base.system.user.model.UserEntity; ...@@ -33,19 +32,19 @@ import com.mortals.xhx.base.system.user.model.UserEntity;
import com.mortals.xhx.base.system.user.service.UserService; import com.mortals.xhx.base.system.user.service.UserService;
/** /**
* <p>Title: 用户信息</p> * 用户信息
* <p>Description: UserController </p> *
* <p>Copyright: Copyright &reg; </p> * @author: zxfei
* <p>Company: </p> * @date: 2021/11/30 10:06
* @author
* @version 1.0.0
*/ */
@RestController @RestController
@RequestMapping("user") @RequestMapping("user")
public class UserController extends BaseCRUDJsonMappingController<UserService, UserForm, UserEntity, Long> { public class UserController extends BaseCRUDJsonMappingController<UserService, UserForm, UserEntity, Long> {
@Autowired @Autowired
private UserService userService; private RoleService roleService;
@Autowired
private RoleUserService roleUserService;
public UserController() { public UserController() {
super.setFormClass(UserForm.class); super.setFormClass(UserForm.class);
...@@ -55,11 +54,9 @@ public class UserController extends BaseCRUDJsonMappingController<UserService, U ...@@ -55,11 +54,9 @@ public class UserController extends BaseCRUDJsonMappingController<UserService, U
@Override @Override
protected void init(HttpServletRequest request, HttpServletResponse response, UserForm form, protected void init(HttpServletRequest request, HttpServletResponse response, UserForm form,
Map<String, Object> model, Context context) { Map<String, Object> model, Context context) {
Map<String, Object> statsus = new HashMap<String, Object>(); this.addDict(model, "userType", UserType.getEnumMap());
statsus.put("userType", IBaseEnum.getEnumMap(UserType.class)); this.addDict(model, "status", UserStatus.getEnumMap());
this.addDict(model, "roleIds", roleService.find(new RoleQuery()).stream().collect(Collectors.toMap(x -> x.getId().toString(), y -> y.getName())));
statsus.put("status", UserStatus.getEnumMap());
model.put(KEY_RESULT_DICT, statsus);
super.init(request, response, form, model, context); super.init(request, response, form, model, context);
} }
...@@ -85,9 +82,16 @@ public class UserController extends BaseCRUDJsonMappingController<UserService, U ...@@ -85,9 +82,16 @@ public class UserController extends BaseCRUDJsonMappingController<UserService, U
@Override @Override
protected int editAfter(HttpServletRequest request, HttpServletResponse response, UserForm form, protected int editAfter(HttpServletRequest request, HttpServletResponse response, UserForm form,
Map<String, Object> model, UserEntity entity, Context context) throws AppException { Map<String, Object> model, UserEntity entity, Context context) throws AppException {
entity.setLoginPwd(null); entity.setLoginPwd(entity.getLoginPwd3());
entity.setLoginPwd1(null); entity.setLoginPwd1(null);
entity.setLoginPwd2(null); entity.setLoginPwd2(null);
RoleUserQuery roleUserQuery = new RoleUserQuery();
roleUserQuery.setUserId(entity.getId());
String roleIds = roleUserService.find(roleUserQuery).stream().map(RoleUserEntity::getRoleId).map(String::valueOf).collect(Collectors.joining(","));
entity.setRoleIds(roleIds);
return super.editAfter(request, response, form, model, entity, context); return super.editAfter(request, response, form, model, entity, context);
} }
...@@ -95,7 +99,7 @@ public class UserController extends BaseCRUDJsonMappingController<UserService, U ...@@ -95,7 +99,7 @@ public class UserController extends BaseCRUDJsonMappingController<UserService, U
protected int saveAfter(HttpServletRequest request, HttpServletResponse response, UserForm form, Map<String, Object> model, Context context) throws AppException { protected int saveAfter(HttpServletRequest request, HttpServletResponse response, UserForm form, Map<String, Object> model, Context context) throws AppException {
if (form.getEntity().getId() == getCurUser().getId()) { if (form.getEntity().getId() == getCurUser().getId()) {
saveCurrUserForSession(request, response, userService.get(form.getEntity().getId(), false)); saveCurrUserForSession(request, response, this.service.get(form.getEntity().getId(), false));
} }
return VALUE_RESULT_SUCCESS; return VALUE_RESULT_SUCCESS;
} }
...@@ -103,7 +107,7 @@ public class UserController extends BaseCRUDJsonMappingController<UserService, U ...@@ -103,7 +107,7 @@ public class UserController extends BaseCRUDJsonMappingController<UserService, U
@Override @Override
protected void saveBefore(HttpServletRequest request, HttpServletResponse response, UserForm form, protected void saveBefore(HttpServletRequest request, HttpServletResponse response, UserForm form,
Map<String, Object> model, Context context) throws AppException { Map<String, Object> model, Context context) throws AppException {
if (service.existUser(form.getEntity().getLoginName(), form.getEntity().getId())) { if (!ObjectUtils.isEmpty(form.getEntity().getLoginName()) && service.existUser(form.getEntity().getLoginName(), form.getEntity().getId())) {
throw new AppException("登录名已存在!"); throw new AppException("登录名已存在!");
} }
super.saveBefore(request, response, form, model, context); super.saveBefore(request, response, form, model, context);
...@@ -125,5 +129,4 @@ public class UserController extends BaseCRUDJsonMappingController<UserService, U ...@@ -125,5 +129,4 @@ public class UserController extends BaseCRUDJsonMappingController<UserService, U
} }
} }
\ No newline at end of file
package com.mortals.xhx.busiz;
import com.mortals.xhx.common.code.CommentTypeEnum;
import com.mortals.xhx.common.code.ProcessStatusEnum;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
*
* 接收消息基础类
* @author: zxfei
* @date: 2022/4/6 14:39
*/
@Data
public abstract class BaseReq implements Serializable {
/**********************任务相关的参数**********************/
/**
* 任务id 必填
*/
@ApiModelProperty(value = "任务id", required = true)
private String taskId;
/**
* 流程实例的id
*/
@ApiModelProperty(value = "流程实例的id", required = true)
private String processInstanceId;
/**
* 节点id 选填
*/
@ApiModelProperty(value = "节点id")
private String activityId;
/**
* 节点名称 选填
*/
@ApiModelProperty(value = "节点名称")
private String activityName;
/**
* 流程实例状态 必填
*/
@ApiModelProperty(value = "流程实例状态", required = true)
private ProcessStatusEnum processStatusEnum;
/**********************审批意见的参数**********************/
/**
* 操作人code 必填
*/
@ApiModelProperty(value = "操作人code", required = true)
private String userCode;
/**
* 审批意见 必填
*/
@ApiModelProperty(value = "审批意见", required = true)
private String message;
/**
* 审批意见类型 必填
*/
@ApiModelProperty(value = "审批意见类型", required = true)
private CommentTypeEnum commentTypeEnum;
}
package com.mortals.xhx.common.code;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @author: finegirl
* @date: 2021/7/16 11:50
* @description: //TODO 请完善注释信息
**/
public enum UserType {
SYSTEM(0, "系统用户"),
WORK(1, "普通用户");
private int value;
private String desc;
UserType(int value, String desc) {
this.value = value;
this.desc = desc;
}
public int getValue() {
return this.value;
}
public String getDesc() {
return this.desc;
}
public static UserType getByValue(int value) {
UserType[] var1 = values();
int var2 = var1.length;
for(int var3 = 0; var3 < var2; ++var3) {
UserType examStatus = var1[var3];
if (examStatus.getValue() == value) {
return examStatus;
}
}
return null;
}
public static Map<String, String> getEnumMap(int... eItem) {
Map<String, String> resultMap = new LinkedHashMap();
UserType[] var2 = values();
int var3 = var2.length;
for(int var4 = 0; var4 < var3; ++var4) {
UserType item = var2[var4];
try {
boolean hasE = false;
int[] var7 = eItem;
int var8 = eItem.length;
for(int var9 = 0; var9 < var8; ++var9) {
int e = var7[var9];
if (item.getValue() == e) {
hasE = true;
break;
}
}
if (!hasE) {
resultMap.put(item.getValue() + "", item.getDesc());
}
} catch (Exception var11) {
}
}
return resultMap;
}
}
\ No newline at end of file
...@@ -20,14 +20,6 @@ public final class Constant { ...@@ -20,14 +20,6 @@ public final class Constant {
/** 基础代码版本 Z-BASE.MANAGER-S1.0.0 */ /** 基础代码版本 Z-BASE.MANAGER-S1.0.0 */
public final static String BASEMANAGER_VERSION = "Z-BASE.MANAGER-S1.0.0"; public final static String BASEMANAGER_VERSION = "Z-BASE.MANAGER-S1.0.0";
public final static String Param_materialProperty = "materialProperty"; public final static String PARAM_SERVER_HTTP_URL = "server_http_url";
public final static String Param_materialType = "materialType";
public final static String Param_isMust = "isMust";
public final static String Param_electronicgs = "electronicgs";
public final static String Param_materialSource = "materialSource";
public final static String Param_paperGg = "paperGg";
public final static String Param_jianmMs = "jianmMs";
public final static String Param_sealWay = "sealWay";
public final static String Param_typeOptions = "typeOptions";
} }
package com.mortals.xhx.daemon;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mortals.framework.ap.GlobalSysInfo;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.Context;
import com.mortals.framework.model.PageInfo;
import com.mortals.framework.model.Result;
import com.mortals.framework.util.DateUtils;
import com.mortals.xhx.base.framework.config.InterceptorConfig;
import com.mortals.xhx.base.system.upload.service.UploadService;
import com.mortals.xhx.base.system.user.model.UserEntity;
import com.mortals.xhx.busiz.rsp.ApiResp;
import com.mortals.xhx.common.code.ApiRespCodeEnum;
import com.mortals.xhx.common.code.OneThingRespCodeEnum;
import com.mortals.xhx.common.model.DefaultTbQueueMsgHeaders;
import com.mortals.xhx.common.model.MessageHeader;
import com.mortals.xhx.queue.*;
import com.mortals.xhx.queue.provider.TbCoreQueueProducerProvider;
import lombok.extern.apachecommons.CommonsLog;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* 一件事微信对外服务接口
*
* @author: zxfei
* @date: 2021/8/24 20:28
*/
@CrossOrigin(origins = "*")
@RestController
@CommonsLog
@RequestMapping("/test/")
public class DemoApiController {
@Autowired
private TbCoreQueueProducerProvider producerProvider;
@GetMapping("/sentry")
public String sentry() {
log.error("[main][我就是展示下异常!]");
return "success";
}
@GetMapping("/exception")
public String exception() {
throw new RuntimeException("直接抛出异常");
}
@GetMapping("/appexception")
public String appexception() {
throw new AppException("自定义异常");
}
/**
* 发送消息
*
* @return
*/
@PostMapping("produceMsg")
public String produceMsg() {
ApiResp<String> rsp = new ApiResp<>();
rsp.setMsg(OneThingRespCodeEnum.SUCCESS.getLabel());
rsp.setCode(OneThingRespCodeEnum.SUCCESS.getValue());
try {
TbQueueProducer<TbQueueMsg> producer = producerProvider.getTbCoreMsgProducer();
TopicPartitionInfo info = TopicPartitionInfo.builder().topic("demoTopic").build();
TbQueueMsgHeaders header = new DefaultTbQueueMsgHeaders();
header.put(MessageHeader.CLIENTID, "aaa".getBytes());
Map<String, Object> headers = new HashMap<>();
headers.put(MessageHeader.TIMESTAMP, DateUtils.getCurrStrDateTime().getBytes());
String payLoad="12313";
TbQueueMsg queueMsg = new DefaultTbQueueMsg(UUID.randomUUID(), payLoad.getBytes(), header);
for(int i=0;i<10;i++){
producer.send(info, queueMsg, new TbQueueCallback() {
@Override
public void onSuccess(TbQueueMsgMetadata metadata) {
// logger.info("消息发送成功");
}
@Override
public void onFailure(Throwable t) {
}
});
}
} catch (Exception e) {
log.error("消息提交失败", e);
rsp.setCode(ApiRespCodeEnum.FAILED.getValue());
rsp.setMsg(e.getMessage());
return JSON.toJSONString(rsp);
}
log.info("响应【消息发送】【响应体】--> " + JSONObject.toJSONString(rsp));
return JSON.toJSONString(rsp);
}
}
...@@ -6,19 +6,6 @@ import org.springframework.stereotype.Component; ...@@ -6,19 +6,6 @@ import org.springframework.stereotype.Component;
import com.mortals.framework.springcloud.service.IApplicationService; import com.mortals.framework.springcloud.service.IApplicationService;
/**
* 应用级服务,在应用启动、停止过程中调用
*
* 缺陷:类加载完成后就调用,会由于某些组件还未初始化而导致服务异常,
* 比如Kafka的连接以及订阅初始化比较靠后,在服务启动过程中就调用操作kafka相关API,将导致失败
* 比如开启Socket监听端口,可能端口都接收到连接请求了,但数据库连接还未初始化完成,导致请求处理失败
* 比如定时任务,任务执行时,相关缓存还未初始化,导致处理失败
*
* 应用场景:
* 1、无依赖其它模块或框架的数据初始化等操作
* @author GM
* @date 2020年7月15日
*/
@Component @Component
public class DemoStartService implements IApplicationService { public class DemoStartService implements IApplicationService {
......
package com.mortals.xhx.daemon.applicationservice; package com.mortals.xhx.daemon.applicationservice;
import com.mortals.framework.springcloud.config.web.BaseWebMvcConfigurer; import com.mortals.framework.springcloud.service.IApplicationStartedService;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.mortals.framework.springcloud.service.IApplicationStartedService;
/**
* 应用级服务,在应用启动后、停止过程中调用
* 应用已经完成启动完成,才调用该服务
* 应用场景:
* 1、应用任务,应用启动后定时或间隔执行的任务
* 2、Socket服务端
* @author GM
* @date 2020年7月15日
*/
@Component @Component
//@ConditionalOnProperty(name="com.mortal",prefix = "",havingValue = "xxx") //@ConditionalOnProperty(name="com.mortal",prefix = "",havingValue = "xxx")
public class DemoStartedService implements IApplicationStartedService { public class DemoStartedService implements IApplicationStartedService {
......
package com.mortals.xhx.daemon.applicationservice;
import com.mortals.framework.springcloud.service.IApplicationStartedService;
import com.mortals.xhx.daemon.netty.config.NettyServerConfig;
import com.mortals.xhx.daemon.netty.server.controlserver.ControlServer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* netty udp 服务启动
*
* @author: zxfei
* @date: 2022/4/8 11:10
*/
@Component
public class NettyStartedService implements IApplicationStartedService {
private static Log logger = LogFactory.getLog(NettyStartedService.class);
@Autowired
private ControlServer controlServer;
@Override
public void start() {
logger.info("开始netty服务....");
controlServer.run(54321);
}
@Override
public void stop() {
logger.info("停止服务..");
}
@Override
public int getOrder() {
return 10;
}
}
package com.mortals.xhx.daemon.netty.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@Data
public class NettyServerConfig {
/**
* udp端口
*/
private int controlport;
/**
* 最大线程数
*/
private int maxThreads;
/**
* 最大数据包长度
*/
private int maxFrameLength;
}
package com.mortals.xhx.daemon.netty.server.controlserver;
import com.mortals.xhx.daemon.netty.config.NettyServerConfig;
import com.mortals.xhx.module.device.service.DeviceService;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;
import lombok.extern.apachecommons.CommonsLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.net.Inet4Address;
@Component
@CommonsLog
public class ControlServer {
private Bootstrap bootstrap;
private Channel channel;
/**
* Worker
*/
private EventLoopGroup workGroup;
private volatile boolean isClosed;
@Autowired
private DeviceService deviceService;
public void run(int port) {
try {
initServerBootstrap();
ChannelFuture future = bootstrap.bind(port).sync();
channel = future.channel();
if (channel != null && channel.isOpen() && channel.isActive() && channel.isRegistered() && channel.isWritable()) {
log.info(String.format("ControlUDP启动成功,ip【%1$s】\tport【%2$d】", Inet4Address.getLocalHost().getHostAddress(), port));
isClosed = false;
} else {
log.debug("NettyControlUDP启动");
}
future.awaitUninterruptibly();
channel.closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
workGroup.shutdownGracefully();
} catch (Exception e) {
e.printStackTrace();
} finally {
workGroup = null;
}
}
}
@PreDestroy
public void release() {
closeChannel();
closeServerBootstrap();
isClosed = true;
}
/**
* 初始化ServerBootstrap
*/
private void initServerBootstrap() {
try {
closeServerBootstrap();// 先关闭之前的bootstrap
workGroup = new NioEventLoopGroup();
bootstrap = new Bootstrap();
bootstrap.group(workGroup)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true)
.handler(new ControlServerInitializer(deviceService));
//.handler(new NettyUDPServerHandler());
} catch (Exception e) {
log.error("启动异常", e);
}
}
private void closeServerBootstrap() {
try {
if (bootstrap != null) {
bootstrap.config().group().shutdownGracefully();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
bootstrap = null;
}
}
private void closeChannel() {
try {
if (channel != null) {
try {
channel.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
channel.eventLoop().shutdownGracefully();
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
channel = null;
}
}
}
package com.mortals.xhx.daemon.netty.server.controlserver;
import com.mortals.xhx.daemon.netty.server.controlserver.handler.NettyUDPServerHandler;
import com.mortals.xhx.module.device.service.DeviceService;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.DatagramChannel;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.timeout.IdleStateHandler;
import java.util.concurrent.TimeUnit;
/**
* @描述 websocket netty init channel
* @创建人 zxfei
* @创建时间 2020/10/20
* @修改人和其它信息
*/
public class ControlServerInitializer extends ChannelInitializer<DatagramChannel> {
private DeviceService deviceService;
public ControlServerInitializer(DeviceService deviceService) {
this.deviceService = deviceService;
}
@Override
protected void initChannel(DatagramChannel datagramChannel) throws Exception {
ChannelPipeline pipeline = datagramChannel.pipeline();
pipeline.addLast(NettyUDPServerHandler.class.getSimpleName(),new NettyUDPServerHandler(deviceService));
}
}
package com.mortals.xhx.daemon.netty.server.controlserver.handler;
import com.mortals.framework.ap.GlobalSysInfo;
import com.mortals.xhx.module.device.service.DeviceService;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import io.netty.util.CharsetUtil;
import static com.mortals.xhx.common.key.Constant.PARAM_SERVER_HTTP_URL;
/**
* 业务处理
*
* @author: zxfei
* @date: 2022/4/8 10:20
*/
public class NettyUDPServerHandler extends SimpleChannelInboundHandler<DatagramPacket> {
private DeviceService deviceService;
public NettyUDPServerHandler(DeviceService deviceService) {
this.deviceService = deviceService;
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
// TODO 设备返回服务端配置
String URL = GlobalSysInfo.getParamValue(PARAM_SERVER_HTTP_URL, "http://192.168.0.100:11021");
String req = msg.content().toString(CharsetUtil.UTF_8);
System.out.println(req);
if ("谚语字典查询?".equals(req)) {
ctx.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer("服务器地址:" + URL, CharsetUtil.UTF_8), msg.sender()));
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
// TODO Auto-generated method stub
ctx.close();
cause.printStackTrace();
}
}
...@@ -9,6 +9,7 @@ import com.mortals.framework.util.DateUtils; ...@@ -9,6 +9,7 @@ import com.mortals.framework.util.DateUtils;
import com.mortals.xhx.base.framework.ws.message.SendToAllRequest; import com.mortals.xhx.base.framework.ws.message.SendToAllRequest;
import com.mortals.xhx.base.framework.ws.message.UserJoinNoticeRequest; import com.mortals.xhx.base.framework.ws.message.UserJoinNoticeRequest;
import com.mortals.xhx.base.framework.ws.util.WebSocketUtil; import com.mortals.xhx.base.framework.ws.util.WebSocketUtil;
import com.mortals.xhx.base.system.param.service.ParamService;
import com.mortals.xhx.common.code.DeviceOnlineStatusEnum; import com.mortals.xhx.common.code.DeviceOnlineStatusEnum;
import com.mortals.xhx.common.key.ParamKey; import com.mortals.xhx.common.key.ParamKey;
import com.mortals.xhx.module.device.model.DeviceLogEntity; import com.mortals.xhx.module.device.model.DeviceLogEntity;
...@@ -22,6 +23,7 @@ import org.springframework.util.ObjectUtils; ...@@ -22,6 +23,7 @@ import org.springframework.util.ObjectUtils;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* 设备状态任务 * 设备状态任务
...@@ -37,6 +39,8 @@ public class DeviceStatTaskImpl implements ITaskExcuteService { ...@@ -37,6 +39,8 @@ public class DeviceStatTaskImpl implements ITaskExcuteService {
private DeviceService deviceService; private DeviceService deviceService;
@Autowired @Autowired
private DeviceLogService deviceLogService; private DeviceLogService deviceLogService;
@Autowired
private ParamService paramService;
@Override @Override
...@@ -52,7 +56,7 @@ public class DeviceStatTaskImpl implements ITaskExcuteService { ...@@ -52,7 +56,7 @@ public class DeviceStatTaskImpl implements ITaskExcuteService {
*/ */
private void doDeviceUpOrDown() { private void doDeviceUpOrDown() {
int timeout = GlobalSysInfo.getParamIntValue(ParamKey.SYS_PARAM_HEADBEAT_TIMEOUT, 60) * 1000; int timeout = GlobalSysInfo.getParamIntValue(ParamKey.SYS_PARAM_HEADBEAT_TIMEOUT, 60) * 1000;
Map<String, String> deviceTypeMap = paramService.getParamBySecondOrganize("Device", "deviceType");
try { try {
//获取所有设备,针对每个设备查询最近指定秒的日志,如果没有则更新下线 //获取所有设备,针对每个设备查询最近指定秒的日志,如果没有则更新下线
deviceService.getCacheList().stream() deviceService.getCacheList().stream()
...@@ -67,8 +71,8 @@ public class DeviceStatTaskImpl implements ITaskExcuteService { ...@@ -67,8 +71,8 @@ public class DeviceStatTaskImpl implements ITaskExcuteService {
device.setOfflineTime(new Date()); device.setOfflineTime(new Date());
device.setDeviceOnlineStatus(DeviceOnlineStatusEnum.离线.getValue()); device.setDeviceOnlineStatus(DeviceOnlineStatusEnum.离线.getValue());
deviceService.update(device); deviceService.update(device);
String msg = String.format("%s设备:%s ,离线!", deviceTypeMap.get(device.getDeviceType().toString()), device.getDeviceCode());
WebSocketUtil.broadcast(SendToAllRequest.TYPE,new SendToAllRequest().setContent(JSON.toJSONString(device))); WebSocketUtil.broadcast(SendToAllRequest.TYPE, new SendToAllRequest().setContent(msg));
} }
}).count(); }).count();
......
...@@ -7,13 +7,16 @@ import com.mortals.xhx.common.code.DeviceOnlineStatusEnum; ...@@ -7,13 +7,16 @@ import com.mortals.xhx.common.code.DeviceOnlineStatusEnum;
import com.mortals.xhx.common.code.DeviceTypeEnum; import com.mortals.xhx.common.code.DeviceTypeEnum;
import com.mortals.xhx.module.firm.model.FirmQuery; import com.mortals.xhx.module.firm.model.FirmQuery;
import com.mortals.xhx.module.firm.service.FirmService; import com.mortals.xhx.module.firm.service.FirmService;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import com.mortals.framework.model.Context; import com.mortals.framework.model.Context;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import com.mortals.framework.web.BaseCRUDJsonMappingController; import com.mortals.framework.web.BaseCRUDJsonMappingController;
import com.mortals.xhx.module.device.model.DeviceEntity; import com.mortals.xhx.module.device.model.DeviceEntity;
import com.mortals.xhx.module.device.model.DeviceQuery; import com.mortals.xhx.module.device.model.DeviceQuery;
...@@ -23,29 +26,31 @@ import com.mortals.framework.util.StringUtils; ...@@ -23,29 +26,31 @@ import com.mortals.framework.util.StringUtils;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import static com.mortals.framework.ap.SysConstains.*; import static com.mortals.framework.ap.SysConstains.*;
/** /**
* * 设备
* 设备 *
* * @author zxfei
* @author zxfei * @date 2022-03-09
* @date 2022-03-09 */
*/
@RestController @RestController
@RequestMapping("device") @RequestMapping("device")
public class DeviceController extends BaseCRUDJsonMappingController<DeviceService,DeviceForm,DeviceEntity,Long> { public class DeviceController extends BaseCRUDJsonMappingController<DeviceService, DeviceForm, DeviceEntity, Long> {
@Autowired @Autowired
private ParamService paramService; private ParamService paramService;
@Autowired @Autowired
private FirmService firmService; private FirmService firmService;
public DeviceController(){ public DeviceController() {
super.setFormClass(DeviceForm.class); super.setFormClass(DeviceForm.class);
super.setModuleDesc( "设备"); super.setModuleDesc("设备");
} }
@Override @Override
...@@ -55,21 +60,26 @@ public class DeviceController extends BaseCRUDJsonMappingController<DeviceServic ...@@ -55,21 +60,26 @@ public class DeviceController extends BaseCRUDJsonMappingController<DeviceServic
add(new OrderCol("createTime", OrderCol.DESCENDING)); add(new OrderCol("createTime", OrderCol.DESCENDING));
} }
}); });
super.doListBefore(request, response, form, model, context); super.doListBefore(request, response, form, model, context);
} }
@Override @Override
protected void init(HttpServletRequest request, HttpServletResponse response, DeviceForm form, Map<String, Object> model, Context context) { protected void init(HttpServletRequest request, HttpServletResponse response, DeviceForm form, Map<String, Object> model, Context context) {
this.addDict(model, "deviceType", paramService.getParamBySecondOrganize("Device","deviceType"));
this.addDict(model, "deviceOnlineStatus", paramService.getParamBySecondOrganize("Device","deviceOnlineStatus"));
this.addDict(model, "status", paramService.getParamBySecondOrganize("Device","status"));
this.addDict(model, "deviceFirmId", firmService.find(new FirmQuery()).stream().collect(Collectors.toMap(x->x.getId().toString(), y->y.getFirmName())));
Map<String, String> deviceTypeMap = paramService.getParamBySecondOrganize("Device", "deviceType");
this.addDict(model, "deviceType", deviceTypeMap);
this.addDict(model, "deviceOnlineStatus", paramService.getParamBySecondOrganize("Device", "deviceOnlineStatus"));
this.addDict(model, "status", paramService.getParamBySecondOrganize("Device", "status"));
this.addDict(model, "deviceFirmId", firmService.find(new FirmQuery()).stream().collect(Collectors.toMap(x -> x.getId().toString(), y -> y.getFirmName())));
Map<Boolean, Long> collect = this.service.find(new DeviceQuery()).stream().collect(Collectors.partitioningBy(item -> (item.getDeviceOnlineStatus() == DeviceOnlineStatusEnum.在线.getValue()), Collectors.counting())); Map<Boolean, Long> collect = this.service.find(new DeviceQuery()).stream().collect(Collectors.partitioningBy(item -> (item.getDeviceOnlineStatus() == DeviceOnlineStatusEnum.在线.getValue()), Collectors.counting()));
model.put("onlineCount", collect.get(true)); model.put("onlineCount", collect.get(true));
model.put("offlineCount", collect.get(false)); model.put("offlineCount", collect.get(false));
//离线设备 按类型分组
if (collect.get(false) > 0) {
Map<String, Long> collectTwo = this.service.find(new DeviceQuery().deviceOnlineStatus(DeviceOnlineStatusEnum.离线.getValue())).stream().collect(Collectors.groupingBy(x -> deviceTypeMap.get(x.getDeviceType().toString()), Collectors.counting()));
model.put("offlineDeviceType", collectTwo);
}
super.init(request, response, form, model, context); super.init(request, response, form, model, context);
} }
......
...@@ -55,3 +55,43 @@ cookie: ...@@ -55,3 +55,43 @@ cookie:
port: 11010 port: 11010
upload: upload:
path: @profiles.filepath@ path: @profiles.filepath@
queue:
type: @profiles.queue.type@ # memory or kafka (Apache Kafka) or rabbitmq (RabbitMQ)
core:
topic: tb_core
poll-interval: 25
partitions: 10
pack-processing-timeout: 2000
in_memory:
stats:
print-interval-ms: 60000
kafka:
bootstrap.servers: @profiles.kafka.brokers@
acks: all
retries: 1
batch.size: 16384
linger.ms: 1
buffer.memory: 33554432
replication_factor: 1
max_poll_interval_ms: 300000
max_poll_records: 8192
max_partition_fetch_bytes: 16777216
fetch_max_bytes: 134217728
use_confluent_cloud: false
consumer-stats:
enabled: true
print-interval-ms: 60000
kafka-response-timeout-ms: 1000
rabbitmq:
exchange_name: @profiles.rabbitmq.exchange@
host: @profiles.rabbitmq.host@
port: @profiles.rabbitmq.port@
virtual_host: @profiles.rabbitmq.virtualhost@
username: @profiles.rabbitmq.username@
password: @profiles.rabbitmq.password@
automatic_recovery_enabled: false
connection_timeout: 60000
handshake_timeout: 10000
queue-properties:
core: x-max-length-bytes:1048576000;x-message-ttl:604800000
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
<properties> <properties>
<profiles.active>develop</profiles.active> <profiles.active>develop</profiles.active>
<profiles.server.port>18211</profiles.server.port> <profiles.server.port>18211</profiles.server.port>
<profiles.queue.type>null</profiles.queue.type>
<profiles.datasource.uri> <profiles.datasource.uri>
<![CDATA[jdbc:mysql://localhost:3306/device-platform?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Hongkong]]></profiles.datasource.uri> <![CDATA[jdbc:mysql://localhost:3306/device-platform?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Hongkong]]></profiles.datasource.uri>
<profiles.datasource.username>root</profiles.datasource.username> <profiles.datasource.username>root</profiles.datasource.username>
...@@ -39,7 +40,15 @@ ...@@ -39,7 +40,15 @@
<profiles.redis.port>6379</profiles.redis.port> <profiles.redis.port>6379</profiles.redis.port>
<profiles.redis.username></profiles.redis.username> <profiles.redis.username></profiles.redis.username>
<profiles.redis.password></profiles.redis.password> <profiles.redis.password></profiles.redis.password>
<profiles.redis.database>1</profiles.redis.database> <profiles.redis.database>6</profiles.redis.database>
<profiles.kafka.brokers>192.168.0.251:9092</profiles.kafka.brokers>
<profiles.queue.type>rabbitmq</profiles.queue.type>
<profiles.rabbitmq.host>192.168.0.98</profiles.rabbitmq.host>
<profiles.rabbitmq.port>5672</profiles.rabbitmq.port>
<profiles.rabbitmq.username>taxi_mq</profiles.rabbitmq.username>
<profiles.rabbitmq.password>admin@2020</profiles.rabbitmq.password>
<profiles.rabbitmq.virtualhost>/</profiles.rabbitmq.virtualhost>
<profiles.rabbitmq.exchange></profiles.rabbitmq.exchange>
<profiles.filepath>/mortals/data</profiles.filepath> <profiles.filepath>/mortals/data</profiles.filepath>
<profiles.log.level>INFO</profiles.log.level> <profiles.log.level>INFO</profiles.log.level>
<profiles.log.path>/logs</profiles.log.path> <profiles.log.path>/logs</profiles.log.path>
...@@ -51,6 +60,7 @@ ...@@ -51,6 +60,7 @@
<properties> <properties>
<profiles.active>test</profiles.active> <profiles.active>test</profiles.active>
<profiles.server.port>18221</profiles.server.port> <profiles.server.port>18221</profiles.server.port>
<profiles.queue.type>null</profiles.queue.type>
<profiles.datasource.uri> <profiles.datasource.uri>
<![CDATA[jdbc:mysql://192.168.0.98:3306/device-platform?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Hongkong]]></profiles.datasource.uri> <![CDATA[jdbc:mysql://192.168.0.98:3306/device-platform?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Hongkong]]></profiles.datasource.uri>
<profiles.datasource.username>root</profiles.datasource.username> <profiles.datasource.username>root</profiles.datasource.username>
...@@ -60,6 +70,13 @@ ...@@ -60,6 +70,13 @@
<profiles.redis.username></profiles.redis.username> <profiles.redis.username></profiles.redis.username>
<profiles.redis.password>hotel@2020</profiles.redis.password> <profiles.redis.password>hotel@2020</profiles.redis.password>
<profiles.redis.database>2</profiles.redis.database> <profiles.redis.database>2</profiles.redis.database>
<profiles.kafka.brokers>192.168.0.251:9092</profiles.kafka.brokers>
<profiles.rabbitmq.host>192.168.0.98</profiles.rabbitmq.host>
<profiles.rabbitmq.port>5672</profiles.rabbitmq.port>
<profiles.rabbitmq.virtualhost>/</profiles.rabbitmq.virtualhost>
<profiles.rabbitmq.username>taxi_mq</profiles.rabbitmq.username>
<profiles.rabbitmq.password>admin@2020</profiles.rabbitmq.password>
<profiles.rabbitmq.exchange></profiles.rabbitmq.exchange>
<profiles.filepath>/mortals/data</profiles.filepath> <profiles.filepath>/mortals/data</profiles.filepath>
<profiles.log.level>INFO</profiles.log.level> <profiles.log.level>INFO</profiles.log.level>
<profiles.log.path>/mortals/app/logs</profiles.log.path> <profiles.log.path>/mortals/app/logs</profiles.log.path>
...@@ -71,8 +88,9 @@ ...@@ -71,8 +88,9 @@
<properties> <properties>
<profiles.active>product</profiles.active> <profiles.active>product</profiles.active>
<profiles.server.port>18221</profiles.server.port> <profiles.server.port>18221</profiles.server.port>
<profiles.queue.type>null</profiles.queue.type>
<profiles.datasource.uri> <profiles.datasource.uri>
<![CDATA[jdbc:mysql://192.168.0.98:8183/device-platform?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Hongkong]]></profiles.datasource.uri> <![CDATA[jdbc:mysql://192.168.0.26:8183/device-platform?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Hongkong]]></profiles.datasource.uri>
<profiles.datasource.username>root</profiles.datasource.username> <profiles.datasource.username>root</profiles.datasource.username>
<profiles.datasource.password>root123</profiles.datasource.password> <profiles.datasource.password>root123</profiles.datasource.password>
<profiles.redis.uri>192.168.0.26</profiles.redis.uri> <profiles.redis.uri>192.168.0.26</profiles.redis.uri>
...@@ -80,6 +98,13 @@ ...@@ -80,6 +98,13 @@
<profiles.redis.username></profiles.redis.username> <profiles.redis.username></profiles.redis.username>
<profiles.redis.password></profiles.redis.password> <profiles.redis.password></profiles.redis.password>
<profiles.redis.database>2</profiles.redis.database> <profiles.redis.database>2</profiles.redis.database>
<profiles.kafka.brokers>192.168.0.26:9092</profiles.kafka.brokers>
<profiles.rabbitmq.host>192.168.0.26</profiles.rabbitmq.host>
<profiles.rabbitmq.port>5672</profiles.rabbitmq.port>
<profiles.rabbitmq.virtualhost>/</profiles.rabbitmq.virtualhost>
<profiles.rabbitmq.exchange></profiles.rabbitmq.exchange>
<profiles.rabbitmq.username>taxi_mq</profiles.rabbitmq.username>
<profiles.rabbitmq.password>admin@2020</profiles.rabbitmq.password>
<profiles.filepath>/mortals/data</profiles.filepath> <profiles.filepath>/mortals/data</profiles.filepath>
<profiles.log.level>INFO</profiles.log.level> <profiles.log.level>INFO</profiles.log.level>
<profiles.log.path>/mortals/app/logs</profiles.log.path> <profiles.log.path>/mortals/app/logs</profiles.log.path>
......
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