From c56f07a61741c5a83991fe8708c25b67ab95203f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B0=A2=E6=B4=AA=E9=BE=99?= <599179587@qq.com> Date: Wed, 5 Jul 2017 09:56:34 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + nb-configuration.xml | 19 + pom.xml | 213 ++++++ .../java/com/ifish/API/CheckSumBuilder.java | 51 ++ src/main/java/com/ifish/API/GwellApi.java | 225 +++++++ src/main/java/com/ifish/API/JiGuangPush.java | 14 + src/main/java/com/ifish/API/Mail.java | 206 ++++++ .../ifish/Interceptor/CheckSumBuilder.java | 52 ++ .../com/ifish/Interceptor/IfishException.java | 28 + .../SecurityValidateInterceptor.java | 79 +++ .../java/com/ifish/bean/LiveRoomPageInfo.java | 209 ++++++ src/main/java/com/ifish/bean/PageResult.java | 88 +++ .../java/com/ifish/bean/Tbl_Activa_Code.java | 127 ++++ src/main/java/com/ifish/bean/Tbl_Device.java | 508 ++++++++++++++ .../com/ifish/bean/Tbl_Device_Statistics.java | 630 ++++++++++++++++++ .../java/com/ifish/bean/Tbl_Device_User.java | 293 ++++++++ .../com/ifish/bean/Tbl_HardWare_Type.java | 437 ++++++++++++ .../java/com/ifish/bean/Tbl_Live_Message.java | 231 +++++++ .../java/com/ifish/bean/Tbl_Live_Room.java | 317 +++++++++ .../java/com/ifish/bean/Tbl_Push_List.java | 465 +++++++++++++ src/main/java/com/ifish/bean/Tbl_User.java | 557 ++++++++++++++++ src/main/java/com/ifish/bean/Tbl_Vender.java | 270 ++++++++ .../java/com/ifish/config/MybatisConfig.java | 86 +++ .../java/com/ifish/config/RedisConfig.java | 58 ++ .../java/com/ifish/config/RootConfig.java | 26 + .../com/ifish/config/WebAppInitializer.java | 46 ++ src/main/java/com/ifish/config/WebConfig.java | 71 ++ .../java/com/ifish/controller/Device.java | 142 ++++ src/main/java/com/ifish/controller/Index.java | 23 + .../java/com/ifish/controller/LiveRoom.java | 107 +++ src/main/java/com/ifish/controller/Login.java | 46 ++ .../com/ifish/controller/PushMessage.java | 65 ++ src/main/java/com/ifish/enums/GwellEnum.java | 41 ++ .../java/com/ifish/enums/PushTypeEnum.java | 58 ++ src/main/java/com/ifish/enums/ResultEnum.java | 66 ++ .../com/ifish/enums/SubDirectoryEnum.java | 45 ++ .../java/com/ifish/helper/DeviceHelper.java | 592 ++++++++++++++++ .../java/com/ifish/helper/DeviceHelperI.java | 124 ++++ .../java/com/ifish/helper/FastDFSClient.java | 145 ++++ .../java/com/ifish/helper/FastDFSClientI.java | 55 ++ .../com/ifish/helper/HardWareTypeHelper.java | 66 ++ .../com/ifish/helper/HardWareTypeHelperI.java | 34 + .../java/com/ifish/helper/LiveRoomHelper.java | 429 ++++++++++++ .../com/ifish/helper/LiveRoomHelperI.java | 62 ++ .../com/ifish/helper/PushMessageHelper.java | 110 +++ .../com/ifish/helper/PushMessageHelperI.java | 33 + .../java/com/ifish/helper/RedisHelper.java | 172 +++++ .../java/com/ifish/helper/RedisHelperI.java | 69 ++ .../java/com/ifish/helper/UserHelper.java | 473 +++++++++++++ .../java/com/ifish/helper/UserHelperI.java | 53 ++ .../com/ifish/mapper/Tbl_Device_Mapper.java | 199 ++++++ .../ifish/mapper/Tbl_Device_MapperSql.java | 269 ++++++++ .../mapper/Tbl_Hardware_Type_Mapper.java | 38 ++ .../ifish/mapper/Tbl_Live_Room_Mapper.java | 112 ++++ .../ifish/mapper/Tbl_Push_List_Mapper.java | 63 ++ .../ifish/mapper/Tbl_Push_List_MapperSql.java | 30 + .../com/ifish/mapper/Tbl_User_Mapper.java | 79 +++ .../com/ifish/mapper/Tbl_User_MapperSql.java | 101 +++ .../java/com/ifish/util/IfishFilePath.java | 109 +++ src/main/java/com/ifish/util/IfishUtil.java | 470 +++++++++++++ .../java/com/ifish/util/JdbcProperties.java | 61 ++ src/main/java/com/ifish/util/RedisKey.java | 73 ++ src/main/resources/fdfs_client_ifish7.conf | 7 + .../resources/fdfs_client_zhangxinyanv5.conf | 8 + src/main/resources/jdbc.properties | 40 ++ src/main/resources/property.properties | 36 + src/main/webapp/META-INF/context.xml | 2 + .../WEB-INF/lib/fastdfs-client-java-1.25.jar | Bin 0 -> 91061 bytes src/main/webapp/index.jsp | 13 + 69 files changed, 10027 insertions(+) create mode 100644 .gitignore create mode 100644 nb-configuration.xml create mode 100644 pom.xml create mode 100644 src/main/java/com/ifish/API/CheckSumBuilder.java create mode 100644 src/main/java/com/ifish/API/GwellApi.java create mode 100644 src/main/java/com/ifish/API/JiGuangPush.java create mode 100644 src/main/java/com/ifish/API/Mail.java create mode 100644 src/main/java/com/ifish/Interceptor/CheckSumBuilder.java create mode 100644 src/main/java/com/ifish/Interceptor/IfishException.java create mode 100644 src/main/java/com/ifish/Interceptor/SecurityValidateInterceptor.java create mode 100644 src/main/java/com/ifish/bean/LiveRoomPageInfo.java create mode 100644 src/main/java/com/ifish/bean/PageResult.java create mode 100644 src/main/java/com/ifish/bean/Tbl_Activa_Code.java create mode 100644 src/main/java/com/ifish/bean/Tbl_Device.java create mode 100644 src/main/java/com/ifish/bean/Tbl_Device_Statistics.java create mode 100644 src/main/java/com/ifish/bean/Tbl_Device_User.java create mode 100644 src/main/java/com/ifish/bean/Tbl_HardWare_Type.java create mode 100644 src/main/java/com/ifish/bean/Tbl_Live_Message.java create mode 100644 src/main/java/com/ifish/bean/Tbl_Live_Room.java create mode 100644 src/main/java/com/ifish/bean/Tbl_Push_List.java create mode 100644 src/main/java/com/ifish/bean/Tbl_User.java create mode 100644 src/main/java/com/ifish/bean/Tbl_Vender.java create mode 100644 src/main/java/com/ifish/config/MybatisConfig.java create mode 100644 src/main/java/com/ifish/config/RedisConfig.java create mode 100644 src/main/java/com/ifish/config/RootConfig.java create mode 100644 src/main/java/com/ifish/config/WebAppInitializer.java create mode 100644 src/main/java/com/ifish/config/WebConfig.java create mode 100644 src/main/java/com/ifish/controller/Device.java create mode 100644 src/main/java/com/ifish/controller/Index.java create mode 100644 src/main/java/com/ifish/controller/LiveRoom.java create mode 100644 src/main/java/com/ifish/controller/Login.java create mode 100644 src/main/java/com/ifish/controller/PushMessage.java create mode 100644 src/main/java/com/ifish/enums/GwellEnum.java create mode 100644 src/main/java/com/ifish/enums/PushTypeEnum.java create mode 100644 src/main/java/com/ifish/enums/ResultEnum.java create mode 100644 src/main/java/com/ifish/enums/SubDirectoryEnum.java create mode 100644 src/main/java/com/ifish/helper/DeviceHelper.java create mode 100644 src/main/java/com/ifish/helper/DeviceHelperI.java create mode 100644 src/main/java/com/ifish/helper/FastDFSClient.java create mode 100644 src/main/java/com/ifish/helper/FastDFSClientI.java create mode 100644 src/main/java/com/ifish/helper/HardWareTypeHelper.java create mode 100644 src/main/java/com/ifish/helper/HardWareTypeHelperI.java create mode 100644 src/main/java/com/ifish/helper/LiveRoomHelper.java create mode 100644 src/main/java/com/ifish/helper/LiveRoomHelperI.java create mode 100644 src/main/java/com/ifish/helper/PushMessageHelper.java create mode 100644 src/main/java/com/ifish/helper/PushMessageHelperI.java create mode 100644 src/main/java/com/ifish/helper/RedisHelper.java create mode 100644 src/main/java/com/ifish/helper/RedisHelperI.java create mode 100644 src/main/java/com/ifish/helper/UserHelper.java create mode 100644 src/main/java/com/ifish/helper/UserHelperI.java create mode 100644 src/main/java/com/ifish/mapper/Tbl_Device_Mapper.java create mode 100644 src/main/java/com/ifish/mapper/Tbl_Device_MapperSql.java create mode 100644 src/main/java/com/ifish/mapper/Tbl_Hardware_Type_Mapper.java create mode 100644 src/main/java/com/ifish/mapper/Tbl_Live_Room_Mapper.java create mode 100644 src/main/java/com/ifish/mapper/Tbl_Push_List_Mapper.java create mode 100644 src/main/java/com/ifish/mapper/Tbl_Push_List_MapperSql.java create mode 100644 src/main/java/com/ifish/mapper/Tbl_User_Mapper.java create mode 100644 src/main/java/com/ifish/mapper/Tbl_User_MapperSql.java create mode 100644 src/main/java/com/ifish/util/IfishFilePath.java create mode 100644 src/main/java/com/ifish/util/IfishUtil.java create mode 100644 src/main/java/com/ifish/util/JdbcProperties.java create mode 100644 src/main/java/com/ifish/util/RedisKey.java create mode 100644 src/main/resources/fdfs_client_ifish7.conf create mode 100644 src/main/resources/fdfs_client_zhangxinyanv5.conf create mode 100644 src/main/resources/jdbc.properties create mode 100644 src/main/resources/property.properties create mode 100644 src/main/webapp/META-INF/context.xml create mode 100644 src/main/webapp/WEB-INF/lib/fastdfs-client-java-1.25.jar create mode 100644 src/main/webapp/index.jsp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c8b241f --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +target/* \ No newline at end of file diff --git a/nb-configuration.xml b/nb-configuration.xml new file mode 100644 index 0000000..99174dc --- /dev/null +++ b/nb-configuration.xml @@ -0,0 +1,19 @@ + + + + + + 1.6-web + Tomcat + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..989defd --- /dev/null +++ b/pom.xml @@ -0,0 +1,213 @@ + + 4.0.0 + + com.ifish + ifish_english + 1.0-SNAPSHOT + war + + ifish_english + + + ${project.build.directory}/endorsed + UTF-8 + + + + + org.csource + fastdfs-client-java + 1.25 + system + ${basedir}/src/main/webapp/WEB-INF/lib/fastdfs-client-java-1.25.jar + + + cn.jpush.api + jpush-client + 3.2.17 + + + org.apache.commons + commons-lang3 + 3.5 + jar + + + org.codehaus.jackson + jackson-mapper-asl + 1.9.13 + jar + + + com.alibaba + fastjson + 1.2.28 + jar + + + org.springframework.data + spring-data-redis + 1.8.4.RELEASE + jar + + + org.apache.commons + commons-pool2 + 2.4.2 + jar + + + redis.clients + jedis + 2.9.0 + jar + + + c3p0 + c3p0 + 0.9.1.2 + jar + + + javax + javaee-web-api + 6.0 + provided + + + + org.springframework + spring-context + 4.3.9.RELEASE + + + + org.springframework + spring-beans + 4.3.9.RELEASE + + + + org.springframework + spring-core + 4.3.9.RELEASE + + + + org.springframework + spring-web + 4.3.9.RELEASE + + + + org.springframework + spring-webmvc + 4.3.8.RELEASE + jar + + + + org.springframework + spring-jdbc + 4.3.9.RELEASE + + + + org.mybatis + mybatis + 3.4.4 + + + + org.mybatis + mybatis-spring + 1.3.1 + + + cn.jpush.api + jiguang-common + 1.0.3 + + + io.netty + netty-all + 4.1.6.Final + compile + + + com.google.code.gson + gson + 2.3 + + + org.slf4j + slf4j-api + 1.7.13 + jar + + + + + org.slf4j + slf4j-log4j12 + 1.7.7 + + + log4j + log4j + 1.2.17 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.6 + 1.6 + + ${endorsed.dir} + + + + + org.apache.maven.plugins + maven-war-plugin + 2.1.1 + + false + + + + org.apache.maven.plugins + maven-dependency-plugin + 2.1 + + + validate + + copy + + + ${endorsed.dir} + true + + + javax + javaee-endorsed-api + 6.0 + jar + + + + + + + + + + diff --git a/src/main/java/com/ifish/API/CheckSumBuilder.java b/src/main/java/com/ifish/API/CheckSumBuilder.java new file mode 100644 index 0000000..5494209 --- /dev/null +++ b/src/main/java/com/ifish/API/CheckSumBuilder.java @@ -0,0 +1,51 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.API; + +import java.security.MessageDigest; + +/** + * + * @author Administrator + */ +public class CheckSumBuilder { + + // 计算并获取CheckSum + public static String getCheckSum(String appSecret, String nonce, String curTime) { + return encode("sha1", appSecret + nonce + curTime); + } + + // 计算并获取md5值 + public static String getMD5(String requestBody) { + return encode("md5", requestBody); + } + + private static String encode(String algorithm, String value) { + if (value == null) { + return null; + } + try { + MessageDigest messageDigest + = MessageDigest.getInstance(algorithm); + messageDigest.update(value.getBytes()); + return getFormattedText(messageDigest.digest()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static String getFormattedText(byte[] bytes) { + int len = bytes.length; + StringBuilder buf = new StringBuilder(len * 2); + for (int j = 0; j < len; j++) { + buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]); + buf.append(HEX_DIGITS[bytes[j] & 0x0f]); + } + return buf.toString(); + } + + private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; +} diff --git a/src/main/java/com/ifish/API/GwellApi.java b/src/main/java/com/ifish/API/GwellApi.java new file mode 100644 index 0000000..690505b --- /dev/null +++ b/src/main/java/com/ifish/API/GwellApi.java @@ -0,0 +1,225 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.API; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.ifish.enums.GwellEnum; + +/** + * + * @author Administrator + */ +public class GwellApi { + + private static Logger log = LoggerFactory.getLogger(GwellApi.class); + + /** + * 注册 + * + * @param phoneNumber + * @return + */ + public static Map Register(String phoneNumber) { + String email = getEmail(phoneNumber); + String pwd = getPwd(phoneNumber); + Map map = new HashMap(); + URL url = null; + HttpURLConnection httpurlconnection = null; + try { + if (url == null) { + url = new URL("http://api1.cloudlinks.cn/Users/RegisterCheck.ashx"); + } + if (httpurlconnection == null) { + //以post方式请求 + httpurlconnection = (HttpURLConnection) url.openConnection(); + httpurlconnection.setReadTimeout(30000); + httpurlconnection.setConnectTimeout(30000); + //是否输入参数 + httpurlconnection.setDoOutput(true); + //提交模式 + httpurlconnection.setRequestMethod("POST"); + } + StringBuffer params = new StringBuffer(); + params.append("Email=" + email + "&"); + params.append("Pwd=" + pwd + "&"); + params.append("RePwd=" + pwd + "&"); + params.append("VersionFlag=1&"); + params.append("CountryCode=&"); + params.append("IgnoreSafeWarning=1"); + OutputStream out = httpurlconnection.getOutputStream(); + out.write(params.toString().getBytes()); + out.flush(); + out.close(); + //获取响应代码 + int code = httpurlconnection.getResponseCode(); + if (code == 200) { + //获取页面内容 + InputStream in = httpurlconnection.getInputStream(); + BufferedReader breader = new BufferedReader(new InputStreamReader(in, "utf-8")); + String jsonStr = ""; + String str = breader.readLine(); + while (str != null) { + jsonStr += str; + str = breader.readLine(); + } + breader.close(); + in.close(); + //System.out.println(jsonStr); + JSONObject json = JSON.parseObject(jsonStr); + String error_code = json.getString("error_code"); + //注册成功 + if (error_code.equals("0")) { + String P2PVerifyCode1 = json.getString("P2PVerifyCode1"); + String P2PVerifyCode2 = json.getString("P2PVerifyCode2"); + String UserID = json.getString("UserID"); + map.put("result", GwellEnum.success.getKey()); + map.put("P2PVerifyCode1", P2PVerifyCode1); + map.put("P2PVerifyCode2", P2PVerifyCode2); + map.put("UserID", UserID); + return map; + } //邮箱已被注册 + else if (error_code.equals("7")) { + String error = json.getString("error"); + map.put("result", GwellEnum.repeat.getKey()); + map.put("error", error); + } //失败 + else if (error_code.equals("1")) { + //发送邮件 + Mail.send(phoneNumber + "注册技威失败了", "注册技威失败!错误信息:" + jsonStr); + String error = json.getString("error"); + map.put("result", GwellEnum.fail.getKey()); + map.put("error", error); + return map; + } + } + } catch (Exception e) { + e.printStackTrace(); + log.error(e.toString()); + } finally { + if (httpurlconnection != null) { + httpurlconnection.disconnect(); + } + } + return map; + } + + /** + * 登陆 + * + * @param phoneNumber + * @return + */ + public static Map Login(String phoneNumber) { + String email = getEmail(phoneNumber); + String pwd = getPwd(phoneNumber); + Map map = new HashMap(); + URL url = null; + HttpURLConnection httpurlconnection = null; + try { + if (url == null) { + url = new URL("http://api1.cloudlinks.cn/Users/LoginCheck.ashx"); + } + if (httpurlconnection == null) { + //以post方式请求 + httpurlconnection = (HttpURLConnection) url.openConnection(); + httpurlconnection.setReadTimeout(30000); + httpurlconnection.setConnectTimeout(30000); + //是否输入参数 + httpurlconnection.setDoOutput(true); + //提交模式 + httpurlconnection.setRequestMethod("POST"); + } + StringBuffer params = new StringBuffer(); + params.append("User=" + email + "&"); + params.append("Pwd=" + pwd + "&"); + params.append("VersionFlag=1&"); + params.append("AppVersion=3014666&"); + params.append("AppOS=3"); + OutputStream out = httpurlconnection.getOutputStream(); + out.write(params.toString().getBytes()); + out.flush(); + out.close(); + //获取响应代码 + int code = httpurlconnection.getResponseCode(); + if (code == 200) { + //获取页面内容 + InputStream in = httpurlconnection.getInputStream(); + BufferedReader breader = new BufferedReader(new InputStreamReader(in, "utf-8")); + String jsonStr = ""; + String str = breader.readLine(); + while (str != null) { + jsonStr += str; + str = breader.readLine(); + } + breader.close(); + in.close(); + //System.out.println(jsonStr); + JSONObject json = JSON.parseObject(jsonStr); + String error_code = json.getString("error_code"); + if (error_code.equals("0")) { + String P2PVerifyCode1 = json.getString("P2PVerifyCode1"); + String P2PVerifyCode2 = json.getString("P2PVerifyCode2"); + String UserID = json.getString("UserID"); + map.put("result", GwellEnum.success.getKey()); + map.put("P2PVerifyCode1", P2PVerifyCode1); + map.put("P2PVerifyCode2", P2PVerifyCode2); + map.put("UserID", UserID); + return map; + } else { + String error = json.getString("error"); + map.put("result", GwellEnum.fail.getKey()); + map.put("error", error); + return map; + } + } + } catch (Exception e) { + log.error(e.toString()); + } finally { + if (httpurlconnection != null) { + httpurlconnection.disconnect(); + } + } + return map; + } + + /** + * 获取用户名 + * + * @param phoneNumber + * @return + */ + public static String getEmail(String phoneNumber) { + String email = "ifish7" + phoneNumber + "@ifish7.com"; + return email; + } + + /** + * 获取密码 + * + * @param phoneNumber + * @return + */ + public static String getPwd(String phoneNumber) { + String pwd = CheckSumBuilder.getMD5("ifish" + phoneNumber); + return pwd; + } + + public static void main(String[] args) { + Register("15216102193"); + } + +} diff --git a/src/main/java/com/ifish/API/JiGuangPush.java b/src/main/java/com/ifish/API/JiGuangPush.java new file mode 100644 index 0000000..e0d5079 --- /dev/null +++ b/src/main/java/com/ifish/API/JiGuangPush.java @@ -0,0 +1,14 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.API; + +/** + * + * @author Administrator + */ +public class JiGuangPush { + +} diff --git a/src/main/java/com/ifish/API/Mail.java b/src/main/java/com/ifish/API/Mail.java new file mode 100644 index 0000000..c3c3f6b --- /dev/null +++ b/src/main/java/com/ifish/API/Mail.java @@ -0,0 +1,206 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.API; + +import java.util.Properties; +import javax.mail.BodyPart; +import javax.mail.Message; +import javax.mail.Multipart; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeBodyPart; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMultipart; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @author Administrator + */ +public class Mail { + + private MimeMessage mimeMsg; //MIME邮件对象 + private Session session; //邮件会话对象 + private Properties props; //系统属性 + private Multipart mp; //Multipart对象,邮件内容,标题,附件等内容均添加到其中后再生成MimeMessage对象 + private static boolean needAuth = true;//smtp是否需要认证 + private static boolean isDebug = false;//是否开启调试 + //smtp认证用户名和密码 + private static String smtp = "smtp.qq.com";//SMTP服务器 + private static String username = "service@ifish7.com"; + private static String password = "Ifish72015"; + private static String from = "service@ifish7.com"; + //private static String to = "fun@ifish7.com"; + private static String to = "help@ifish7.com"; + private static Logger log = LoggerFactory.getLogger(Mail.class); + + /** + * Constructor + * + * @param smtp 邮件发送服务器 + */ + public Mail(String smtp) { + setSmtpHost(smtp); + createMimeMessage(); + } + + /** + * 设置邮件发送服务器 + * + * @param hostName String + */ + public void setSmtpHost(String hostName) { + if (props == null) { + props = System.getProperties(); //获得系统属性对象 + } + //设置SMTP主机 + props.put("mail.smtp.host", hostName); + //设置SMTP是否需要验证 + props.put("mail.smtp.auth", needAuth); + props.put("mail.smtp.starttls.enable", needAuth); + } + + /** + * 创建MIME邮件对象 + * + * @return + */ + public boolean createMimeMessage() { + try { + session = Session.getDefaultInstance(props, null); //获得邮件会话对象 + } catch (Exception e) { + log.error("获取邮件会话对象时发生错误!" + e.toString()); + return false; + } + try { + mimeMsg = new MimeMessage(session); //创建MIME邮件对象 + mp = new MimeMultipart(); + return true; + } catch (Exception e) { + log.error("创建MIME邮件对象失败!" + e.toString()); + return false; + } + } + + /** + * 设置邮件主题 + * + * @param mailSubject + * @return + */ + public boolean setSubject(String mailSubject) { + try { + mimeMsg.setSubject(mailSubject); + return true; + } catch (Exception e) { + log.error("设置邮件主题失败" + e.toString()); + return false; + } + } + + /** + * 设置邮件正文 + * + * @param mailBody String + */ + public boolean setBody(String mailBody) { + try { + BodyPart bp = new MimeBodyPart(); + bp.setContent(mailBody, "text/html;charset=GBK"); + mp.addBodyPart(bp); + return true; + } catch (Exception e) { + log.error("设置邮件正文失败" + e.toString()); + return false; + } + } + + /** + * 设置发信人 + * + * @param from String + */ + public boolean setFrom(String from) { + try { + mimeMsg.setFrom(new InternetAddress(from)); //设置发信人 + return true; + } catch (Exception e) { + log.error("设置发信人失败" + e.toString()); + return false; + } + } + + /** + * 设置收信人 + * + * @param to String + */ + public boolean setTo(String to) { + try { + mimeMsg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to)); + return true; + } catch (Exception e) { + log.error("设置收信人失败" + e.toString()); + return false; + } + } + + /** + * 发送邮件 + */ + public boolean sendOut() { + try { + mimeMsg.setContent(mp); + mimeMsg.saveChanges(); + Session mailSession = Session.getInstance(props, null); + mailSession.setDebug(isDebug); + Transport transport = mailSession.getTransport("smtp"); + transport.connect((String) props.get("mail.smtp.host"), username, password); + transport.sendMessage(mimeMsg, mimeMsg.getRecipients(Message.RecipientType.TO)); + //transport.send(mimeMsg); + transport.close(); + return true; + } catch (Exception e) { + log.error("发送邮件失败" + e.toString()); + return false; + } + } + + /** + * 调用sendOut方法完成邮件发送 + * + * @param smtp + * @param from + * @param to + * @param subject + * @param content + * @param username + * @param password + * @return boolean + */ + public static boolean send(String subject, String content) { + Mail theMail = new Mail(smtp); + + if (!theMail.setSubject(subject)) { + return false; + } + if (!theMail.setFrom(from)) { + return false; + } + if (!theMail.setTo(to)) { + return false; + } + if (!theMail.setBody(content)) { + return false; + } + if (!theMail.sendOut()) { + return false; + } + return true; + } +} diff --git a/src/main/java/com/ifish/Interceptor/CheckSumBuilder.java b/src/main/java/com/ifish/Interceptor/CheckSumBuilder.java new file mode 100644 index 0000000..2545bb2 --- /dev/null +++ b/src/main/java/com/ifish/Interceptor/CheckSumBuilder.java @@ -0,0 +1,52 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.Interceptor; + +import java.security.MessageDigest; + +/** + * + * @author Administrator + */ +public class CheckSumBuilder { + + // 计算并获取CheckSum + public static String getCheckSum(String appSecret, String nonce, String curTime) { + return encode("sha1", appSecret + nonce + curTime); + } + + // 计算并获取md5值 + public static String getMD5(String requestBody) { + return encode("md5", requestBody); + } + + private static String encode(String algorithm, String value) { + if (value == null) { + return null; + } + try { + MessageDigest messageDigest + = MessageDigest.getInstance(algorithm); + messageDigest.update(value.getBytes()); + return getFormattedText(messageDigest.digest()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static String getFormattedText(byte[] bytes) { + int len = bytes.length; + StringBuilder buf = new StringBuilder(len * 2); + for (int j = 0; j < len; j++) { + buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]); + buf.append(HEX_DIGITS[bytes[j] & 0x0f]); + } + return buf.toString(); + } + + private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + +} diff --git a/src/main/java/com/ifish/Interceptor/IfishException.java b/src/main/java/com/ifish/Interceptor/IfishException.java new file mode 100644 index 0000000..a9d5e6a --- /dev/null +++ b/src/main/java/com/ifish/Interceptor/IfishException.java @@ -0,0 +1,28 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.Interceptor; + +import com.ifish.enums.ResultEnum; + +/** + * + * @author Administrator + */ +public class IfishException extends RuntimeException { + + private static final long serialVersionUID = 4182058914725642218L; + + private String result; + + public IfishException(ResultEnum resultEnum) { + super(resultEnum.getValue()); + this.result = resultEnum.getKey(); + } + + public String getResult() { + return result; + } +} diff --git a/src/main/java/com/ifish/Interceptor/SecurityValidateInterceptor.java b/src/main/java/com/ifish/Interceptor/SecurityValidateInterceptor.java new file mode 100644 index 0000000..67ef91e --- /dev/null +++ b/src/main/java/com/ifish/Interceptor/SecurityValidateInterceptor.java @@ -0,0 +1,79 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.Interceptor; + +import com.ifish.enums.ResultEnum; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.apache.commons.lang3.StringUtils; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +/** + * + * @author Administrator + */ +public class SecurityValidateInterceptor extends HandlerInterceptorAdapter { + + public SecurityValidateInterceptor(boolean devModel) { + this.devModel = devModel; + } + + //appKey(ifishAppKey1)MD5 + private final String ifishAppKey = "5fc7bdada110e3a6eefd3065b8d8d995"; + //appSecret(ifishAppSecret1)MD5前12位 + private final String ifishAppSecret = "9596b393ab0f"; + //开发模式 + private boolean devModel = false; + + //不需要验证的url + private static List urlList = new ArrayList(); + + //添加不需要验证url + static { + urlList.add("/user/"); + urlList.add("/updateUser/"); + urlList.add("/pageList/"); + urlList.add("/information/v3/findCommentsByUeditorId.do"); + urlList.add("/information/v3/saveComment.do"); + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { + //开发模式 + if (!devModel) { + + String url = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getServletPath(); + //部分url不需要拦截器进行验证 + for (String string : urlList) { + if (url.contains(string)) { + return true; + } + } + + String nonce = request.getHeader("nonce"); + String appKey = request.getHeader("appKey"); + String curTime = request.getHeader("curTime"); + String checkSum = request.getHeader("checkSum"); + //校验参数完整性 + if (StringUtils.isNotBlank(checkSum) && StringUtils.isNotBlank(appKey) && StringUtils.isNotBlank(nonce) && StringUtils.isNotBlank(curTime)) { + //校验appKey + if (appKey.equals(ifishAppKey)) { + //计算md5 + String md5Sum = CheckSumBuilder.getMD5(ifishAppSecret + nonce + curTime); + if (md5Sum.equals(checkSum)) { + return true; + } + } + } + throw new IfishException(ResultEnum.error400); + } + return true; + } + +} diff --git a/src/main/java/com/ifish/bean/LiveRoomPageInfo.java b/src/main/java/com/ifish/bean/LiveRoomPageInfo.java new file mode 100644 index 0000000..be768b4 --- /dev/null +++ b/src/main/java/com/ifish/bean/LiveRoomPageInfo.java @@ -0,0 +1,209 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.bean; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + * + * @author Administrator + */ +public class LiveRoomPageInfo implements Serializable { + + private static final long serialVersionUID = 2438713198151455034L; + //直播间ID + private Integer roomId; + //用户ID + private Integer userId; + //用户类型 + private String userType; + //昵称 + private String nickName; + //用户头像 + private String userImg; + //用户最后一次登录时间 + private Date loginTime; + //摄像头ID + private String cameraId; + //直播间名称 + private String roomName; + //直播宣言 + private String roomDesc; + //人气值 + private Integer popularityValue; + //活跃度 + private String liveness; + //直播天数 + private Integer numberDays; + //距离 + private Double distance; + //创建时间 + private Date createTime; + //评论数 + private Integer pinglunNum; + //点赞数量 + private Integer zanNum; + //是否点过赞 + private String isZan; + //打赏金币数量 + private BigDecimal totalGoldValue; + //等级 + private Integer gradeNum; + + public Integer getRoomId() { + return roomId; + } + + public void setRoomId(Integer roomId) { + this.roomId = roomId; + } + + public String getNickName() { + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + public String getCameraId() { + return cameraId; + } + + public void setCameraId(String cameraId) { + this.cameraId = cameraId; + } + + public String getRoomName() { + return roomName; + } + + public void setRoomName(String roomName) { + this.roomName = roomName; + } + + public String getRoomDesc() { + return roomDesc; + } + + public void setRoomDesc(String roomDesc) { + this.roomDesc = roomDesc; + } + + public Integer getPopularityValue() { + return popularityValue; + } + + public void setPopularityValue(Integer popularityValue) { + this.popularityValue = popularityValue; + } + + public Integer getNumberDays() { + return numberDays; + } + + public void setNumberDays(Integer numberDays) { + this.numberDays = numberDays; + } + + public Double getDistance() { + return distance; + } + + public void setDistance(Double distance) { + this.distance = distance; + } + + public String getUserImg() { + return userImg; + } + + public void setUserImg(String userImg) { + this.userImg = userImg; + } + + public String getLiveness() { + return liveness; + } + + public void setLiveness(String liveness) { + this.liveness = liveness; + } + + public Date getLoginTime() { + return loginTime; + } + + public void setLoginTime(Date loginTime) { + this.loginTime = loginTime; + } + + public Integer getUserId() { + return userId; + } + + public void setUserId(Integer userId) { + this.userId = userId; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public String getUserType() { + return userType; + } + + public void setUserType(String userType) { + this.userType = userType; + } + + public Integer getPinglunNum() { + return pinglunNum; + } + + public void setPinglunNum(Integer pinglunNum) { + this.pinglunNum = pinglunNum; + } + + public String getIsZan() { + return isZan; + } + + public void setIsZan(String isZan) { + this.isZan = isZan; + } + + public Integer getGradeNum() { + return gradeNum; + } + + public void setGradeNum(Integer gradeNum) { + this.gradeNum = gradeNum; + } + + public Integer getZanNum() { + return zanNum; + } + + public void setZanNum(Integer zanNum) { + this.zanNum = zanNum; + } + + public BigDecimal getTotalGoldValue() { + return totalGoldValue; + } + + public void setTotalGoldValue(BigDecimal totalGoldValue) { + this.totalGoldValue = totalGoldValue; + } +} diff --git a/src/main/java/com/ifish/bean/PageResult.java b/src/main/java/com/ifish/bean/PageResult.java new file mode 100644 index 0000000..253c84e --- /dev/null +++ b/src/main/java/com/ifish/bean/PageResult.java @@ -0,0 +1,88 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.bean; + +import java.util.List; + +/** + * + * @author Administrator + */ +public class PageResult implements java.io.Serializable { + + private static final long serialVersionUID = 1L; + private int totalCount = 0; + private int pageSize = 10; + private int pageNo = 1; + private int DEF_COUNT = 10; + private List list; + + public PageResult() { + + } + + public PageResult(int pageNo, int pageSize, int totalCount) { + setTotalCount(totalCount); + setPageSize(pageSize); + setPageNo(pageNo); + } + + public PageResult(int pageNo, int pageSize, int totalCount, List list) { + setTotalCount(totalCount); + setPageSize(pageSize); + setPageNo(pageNo); + this.list = list; + } + + public void setTotalCount(int totalCount) { + if (totalCount < 0) { + this.totalCount = 0; + } else { + this.totalCount = totalCount; + } + } + + public int getTotalCount() { + return totalCount; + } + + public void setPageSize(int pageSize) { + if (pageSize < 1) { + this.pageSize = DEF_COUNT; + } else { + this.pageSize = pageSize; + } + } + + public int getPageSize() { + return pageSize; + } + + public void setPageNo(int pageNo) { + if (pageNo < 1) { + this.pageNo = 1; + } else { + this.pageNo = pageNo; + } + } + + public int getPageNo() { + return pageNo; + } + + public int getFirstResult() { + return (pageNo - 1) * pageSize; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + +} diff --git a/src/main/java/com/ifish/bean/Tbl_Activa_Code.java b/src/main/java/com/ifish/bean/Tbl_Activa_Code.java new file mode 100644 index 0000000..20e487a --- /dev/null +++ b/src/main/java/com/ifish/bean/Tbl_Activa_Code.java @@ -0,0 +1,127 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.bean; + +import java.util.Date; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * 摄像头激活码(tbl_activa_code) + * + * @author bianj + * @version 1.0.0 2017-07-03 + */ +@Entity +@Table(name = "tbl_activa_code") +public class Tbl_Activa_Code implements java.io.Serializable { + + /** + * 版本号 + */ + private static final long serialVersionUID = -2477544371712460934L; + + /** + * 激活码 + */ + @Id + @Column(name = "active_code", unique = true, nullable = false, length = 50) + private String activeCode; + + /** + * 批次号 + */ + @Column(name = "batch_code", nullable = true, length = 50) + private String batchCode; + + /** + * + */ + @Column(name = "is_used", nullable = true, length = 1) + private String isUsed; + + /** + * + */ + @Column(name = "create_time", nullable = true) + private Date createTime; + + /** + * 获取激活码 + * + * @return 激活码 + */ + public String getActiveCode() { + return this.activeCode; + } + + /** + * 设置激活码 + * + * @param activeCode 激活码 + */ + public void setActiveCode(String activeCode) { + this.activeCode = activeCode; + } + + /** + * 获取批次号 + * + * @return 批次号 + */ + public String getBatchCode() { + return this.batchCode; + } + + /** + * 设置批次号 + * + * @param batchCode 批次号 + */ + public void setBatchCode(String batchCode) { + this.batchCode = batchCode; + } + + /** + * 获取 + * + * @return + */ + public String getIsUsed() { + return this.isUsed; + } + + /** + * 设置 + * + * @param isUsed + * + */ + public void setIsUsed(String isUsed) { + this.isUsed = isUsed; + } + + /** + * 获取 + * + * @return + */ + public Date getCreateTime() { + return this.createTime; + } + + /** + * 设置 + * + * @param createTime + * + */ + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } +} diff --git a/src/main/java/com/ifish/bean/Tbl_Device.java b/src/main/java/com/ifish/bean/Tbl_Device.java new file mode 100644 index 0000000..ffcb840 --- /dev/null +++ b/src/main/java/com/ifish/bean/Tbl_Device.java @@ -0,0 +1,508 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.bean; + +import java.util.Date; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * 设备详情表(tbl_device) + * + * @author Administrator + */ +@Entity +@Table(name = "tbl_device") +public class Tbl_Device implements java.io.Serializable { + + /** + * 版本号 + */ + private static final long serialVersionUID = 3405700970095511149L; + + /** + * 设备Id + */ + @Id + @Column(name = "device_id", unique = true, nullable = false, length = 10) + private Integer deviceId; + + /** + * 服务器IP + */ + @Column(name = "server_ip", nullable = true, length = 50) + private String serverIp; + + /** + * 设备IP + */ + @Column(name = "device_ip", nullable = true, length = 50) + private String deviceIp; + + /** + * 是否为摄像头:1是,0否 + */ + @Column(name = "is_camera", nullable = true, length = 1) + private String isCamera; + + /** + * 设备Mac地址 + */ + @Column(name = "mac_address", unique = true, nullable = true, length = 50) + private String macAddress; + + /** + * 登陆时间 + */ + @Column(name = "login_time", nullable = true) + private Date loginTime; + + /** + * 是否在黑名单:1不在、0在 + */ + @Column(name = "is_blacklist", nullable = true, length = 1) + private String isBlacklist; + + /** + * 设备型号 + */ + @Column(name = "hardware_type", nullable = true, length = 10) + private String hardwareType; + + /** + * 是否推送 + */ + @Column(name = "on_off", nullable = true, length = 1) + private String onOff; + + /** + * 今天是否提醒:1提醒、0不提醒 + */ + @Column(name = "today_remind", nullable = true, length = 1) + private String todayRemind; + + /** + * 是否开启换水提醒:1开启、0不开启 + */ + @Column(name = "water_remind", nullable = true, length = 1) + private String waterRemind; + + /** + * 换水提醒日期 + */ + @Column(name = "remind_date", nullable = true) + private Date remindDate; + + /** + * 换水周期 + */ + @Column(name = "remind_cycle", nullable = true, length = 10) + private Integer remindCycle; + + /** + * 电子厂代码 + */ + @Column(name = "factory_code", nullable = true, length = 20) + private String factoryCode; + + /** + * 鱼缸场代码 + */ + @Column(name = "brand_code", nullable = true, length = 20) + private String brandCode; + + /** + * 摄像头ID + */ + @Column(name = "camera_id", nullable = true, length = 20) + private String cameraId; + + /** + * 创建时间 + */ + @Column(name = "create_time", nullable = true) + private Date createTime; + + /** + * 摄像头激活码 + */ + @Column(name = "active_code", nullable = true, length = 50) + private String activeCode; + + /** + * 摄像头激活时间 + */ + @Column(name = "active_time", nullable = true) + private Date activeTime; + + /** + * 修改时间 + */ + @Column(name = "update_time", nullable = true) + private Date updateTime; + + /** + * 获取设备Id + * + * @return 设备Id + */ + public Integer getDeviceId() { + return this.deviceId; + } + + /** + * 设置设备Id + * + * @param deviceId 设备Id + */ + public void setDeviceId(Integer deviceId) { + this.deviceId = deviceId; + } + + /** + * 获取服务器IP + * + * @return 服务器IP + */ + public String getServerIp() { + return this.serverIp; + } + + /** + * 设置服务器IP + * + * @param serverIp 服务器IP + */ + public void setServerIp(String serverIp) { + this.serverIp = serverIp; + } + + /** + * 获取设备IP + * + * @return 设备IP + */ + public String getDeviceIp() { + return this.deviceIp; + } + + /** + * 设置设备IP + * + * @param deviceIp 设备IP + */ + public void setDeviceIp(String deviceIp) { + this.deviceIp = deviceIp; + } + + /** + * 获取是否为摄像头:1是,0否 + * + * @return 是否为摄像头:1是 + */ + public String getIsCamera() { + return this.isCamera; + } + + /** + * 设置是否为摄像头:1是,0否 + * + * @param isCamera 是否为摄像头:1是,0否 + */ + public void setIsCamera(String isCamera) { + this.isCamera = isCamera; + } + + /** + * 获取设备Mac地址 + * + * @return 设备Mac地址 + */ + public String getMacAddress() { + return this.macAddress; + } + + /** + * 设置设备Mac地址 + * + * @param macAddress 设备Mac地址 + */ + public void setMacAddress(String macAddress) { + this.macAddress = macAddress; + } + + /** + * 获取登陆时间 + * + * @return 登陆时间 + */ + public Date getLoginTime() { + return this.loginTime; + } + + /** + * 设置登陆时间 + * + * @param loginTime 登陆时间 + */ + public void setLoginTime(Date loginTime) { + this.loginTime = loginTime; + } + + /** + * 获取是否在黑名单:1不在、0在 + * + * @return 是否在黑名单 + */ + public String getIsBlacklist() { + return this.isBlacklist; + } + + /** + * 设置是否在黑名单:1不在、0在 + * + * @param isBlacklist 是否在黑名单:1不在、0在 + */ + public void setIsBlacklist(String isBlacklist) { + this.isBlacklist = isBlacklist; + } + + /** + * 获取设备型号 + * + * @return 设备型号 + */ + public String getHardwareType() { + return this.hardwareType; + } + + /** + * 设置设备型号 + * + * @param hardwareType 设备型号 + */ + public void setHardwareType(String hardwareType) { + this.hardwareType = hardwareType; + } + + /** + * 获取是否推送 + * + * @return 是否推送 + */ + public String getOnOff() { + return this.onOff; + } + + /** + * 设置是否推送 + * + * @param onOff 是否推送 + */ + public void setOnOff(String onOff) { + this.onOff = onOff; + } + + /** + * 获取今天是否提醒:1提醒、0不提醒 + * + * @return 今天是否提醒 + */ + public String getTodayRemind() { + return this.todayRemind; + } + + /** + * 设置今天是否提醒:1提醒、0不提醒 + * + * @param todayRemind 今天是否提醒:1提醒、0不提醒 + */ + public void setTodayRemind(String todayRemind) { + this.todayRemind = todayRemind; + } + + /** + * 获取是否开启换水提醒:1开启、0不开启 + * + * @return 是否开启换水提醒 + */ + public String getWaterRemind() { + return this.waterRemind; + } + + /** + * 设置是否开启换水提醒:1开启、0不开启 + * + * @param waterRemind 是否开启换水提醒:1开启、0不开启 + */ + public void setWaterRemind(String waterRemind) { + this.waterRemind = waterRemind; + } + + /** + * 获取换水提醒日期 + * + * @return 换水提醒日期 + */ + public Date getRemindDate() { + return this.remindDate; + } + + /** + * 设置换水提醒日期 + * + * @param remindDate 换水提醒日期 + */ + public void setRemindDate(Date remindDate) { + this.remindDate = remindDate; + } + + /** + * 获取换水周期 + * + * @return 换水周期 + */ + public Integer getRemindCycle() { + return this.remindCycle; + } + + /** + * 设置换水周期 + * + * @param remindCycle 换水周期 + */ + public void setRemindCycle(Integer remindCycle) { + this.remindCycle = remindCycle; + } + + /** + * 获取电子厂代码 + * + * @return 电子厂代码 + */ + public String getFactoryCode() { + return this.factoryCode; + } + + /** + * 设置电子厂代码 + * + * @param factoryCode 电子厂代码 + */ + public void setFactoryCode(String factoryCode) { + this.factoryCode = factoryCode; + } + + /** + * 获取鱼缸场代码 + * + * @return 鱼缸场代码 + */ + public String getBrandCode() { + return this.brandCode; + } + + /** + * 设置鱼缸场代码 + * + * @param brandCode 鱼缸场代码 + */ + public void setBrandCode(String brandCode) { + this.brandCode = brandCode; + } + + /** + * 获取摄像头ID + * + * @return 摄像头ID + */ + public String getCameraId() { + return this.cameraId; + } + + /** + * 设置摄像头ID + * + * @param cameraId 摄像头ID + */ + public void setCameraId(String cameraId) { + this.cameraId = cameraId; + } + + /** + * 获取创建时间 + * + * @return 创建时间 + */ + public Date getCreateTime() { + return this.createTime; + } + + /** + * 设置创建时间 + * + * @param createTime 创建时间 + */ + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + /** + * 获取摄像头激活码 + * + * @return 摄像头激活码 + */ + public String getActiveCode() { + return this.activeCode; + } + + /** + * 设置摄像头激活码 + * + * @param activeCode 摄像头激活码 + */ + public void setActiveCode(String activeCode) { + this.activeCode = activeCode; + } + + /** + * 获取摄像头激活时间 + * + * @return 摄像头激活时间 + */ + public Date getActiveTime() { + return this.activeTime; + } + + /** + * 设置摄像头激活时间 + * + * @param activeTime 摄像头激活时间 + */ + public void setActiveTime(Date activeTime) { + this.activeTime = activeTime; + } + + /** + * 获取修改时间 + * + * @return 修改时间 + */ + public Date getUpdateTime() { + return this.updateTime; + } + + /** + * 设置修改时间 + * + * @param updateTime 修改时间 + */ + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } +} diff --git a/src/main/java/com/ifish/bean/Tbl_Device_Statistics.java b/src/main/java/com/ifish/bean/Tbl_Device_Statistics.java new file mode 100644 index 0000000..a5df6aa --- /dev/null +++ b/src/main/java/com/ifish/bean/Tbl_Device_Statistics.java @@ -0,0 +1,630 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.bean; + +import java.util.Date; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * 设备统计信息表(tbl_device_statistics) + * + * @author bianj + * @version 1.0.0 2017-06-29 + */ +@Entity +@Table(name = "tbl_device_statistics") +public class Tbl_Device_Statistics implements java.io.Serializable { + + /** + * 版本号 + */ + private static final long serialVersionUID = 1215383532220649875L; + + /** + * id + */ + @Id + @Column(name = "id", unique = true, nullable = false, length = 10) + private Integer id; + + /** + * 设备ID + */ + @Id + @Column(name = "device_id", unique = true, nullable = false, length = 10) + private Integer deviceId; + + /** + * 设备MAC地址 + */ + @Column(name = "mac_address", nullable = true, length = 50) + private String macAddress; + + /** + * 登陆次数 + */ + @Column(name = "login_count", nullable = true, length = 11) + private int loginCount; + + /** + * 最后登陆时间 + */ + @Column(name = "login_time", nullable = true) + private Date loginTime; + + /** + * 首次激活时间 + */ + @Column(name = "first_activate", nullable = true) + private Date firstActivate; + + /** + * 创建时间 + */ + @Column(name = "create_time", nullable = true) + private Date createTime; + + /** + * 是否收费 + */ + @Column(name = "is_charge", nullable = true, length = 1) + private String isCharge; + + /** + * sdk版本 + */ + @Column(name = "sdk_version", nullable = true, length = 10) + private String sdkVersion; + + /** + * sdk时间 + */ + @Column(name = "sdk_time", nullable = true) + private Date sdkTime; + + /** + * 分配日期 + */ + @Column(name = "create_date", nullable = true) + private Date createDate; + + /** + * 是否升级 + */ + @Column(name = "is_upgrade", nullable = true, length = 1) + private String isUpgrade; + + /** + * 更新版本 + */ + @Column(name = "upgrade_version", nullable = true, length = 10) + private String upgradeVersion; + + /** + * 更新时间 + */ + @Column(name = "upgrade_time", nullable = true) + private Date upgradeTime; + + /** + * 授权时间 + */ + @Column(name = "authorize_time", nullable = true) + private Date authorizeTime; + + /** + * 编号 + */ + @Column(name = "create_code", nullable = true, length = 50) + private String createCode; + + /** + * MCU启动次数 + */ + @Column(name = "mcu_count", nullable = true, length = 10) + private Integer mcuCount; + + /** + * 模块启动次数 + */ + @Column(name = "module_count", nullable = true, length = 10) + private Integer moduleCount; + + /** + * 连接路由器次数 + */ + @Column(name = "router_count", nullable = true, length = 10) + private Integer routerCount; + + /** + * 成功连接服务器次数 + */ + @Column(name = "server_count", nullable = true, length = 10) + private Integer serverCount; + + /** + * 尝试连接服务器次数 + */ + @Column(name = "server_try_count", nullable = true, length = 10) + private Integer serverTryCount; + + /** + * mcu版本 + */ + @Column(name = "software_version", nullable = true, length = 10) + private String softwareVersion; + + /** + * 硬件型号 + */ + @Column(name = "hardware_type", nullable = true, length = 10) + private String hardwareType; + + /** + * 电子厂代码 + */ + @Column(name = "factory_code", nullable = true, length = 20) + private String factoryCode; + + /** + * 鱼缸场代码 + */ + @Column(name = "brand_code", nullable = true, length = 20) + private String brandCode; + + /** + * 获取id + * + * @return id + */ + public Integer getId() { + return this.id; + } + + /** + * 设置id + * + * @param id id + */ + public void setId(Integer id) { + this.id = id; + } + + /** + * 获取设备ID + * + * @return 设备ID + */ + public Integer getDeviceId() { + return this.deviceId; + } + + /** + * 设置设备ID + * + * @param deviceId 设备ID + */ + public void setDeviceId(Integer deviceId) { + this.deviceId = deviceId; + } + + /** + * 获取设备MAC地址 + * + * @return 设备MAC地址 + */ + public String getMacAddress() { + return this.macAddress; + } + + /** + * 设置设备MAC地址 + * + * @param macAddress 设备MAC地址 + */ + public void setMacAddress(String macAddress) { + this.macAddress = macAddress; + } + + /** + * 获取登陆次数 + * + * @return 登陆次数 + */ + public Integer getLoginCount() { + return this.loginCount; + } + + /** + * 设置登陆次数 + * + * @param loginCount 登陆次数 + */ + public void setLoginCount(Integer loginCount) { + this.loginCount = loginCount; + } + + /** + * 获取最后登陆时间 + * + * @return 最后登陆时间 + */ + public Date getLoginTime() { + return this.loginTime; + } + + /** + * 设置最后登陆时间 + * + * @param loginTime 最后登陆时间 + */ + public void setLoginTime(Date loginTime) { + this.loginTime = loginTime; + } + + /** + * 获取首次激活时间 + * + * @return 首次激活时间 + */ + public Date getFirstActivate() { + return this.firstActivate; + } + + /** + * 设置首次激活时间 + * + * @param firstActivate 首次激活时间 + */ + public void setFirstActivate(Date firstActivate) { + this.firstActivate = firstActivate; + } + + /** + * 获取创建时间 + * + * @return 创建时间 + */ + public Date getCreateTime() { + return this.createTime; + } + + /** + * 设置创建时间 + * + * @param createTime 创建时间 + */ + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + /** + * 获取是否收费 + * + * @return 是否收费 + */ + public String getIsCharge() { + return this.isCharge; + } + + /** + * 设置是否收费 + * + * @param isCharge 是否收费 + */ + public void setIsCharge(String isCharge) { + this.isCharge = isCharge; + } + + /** + * 获取sdk版本 + * + * @return sdk版本 + */ + public String getSdkVersion() { + return this.sdkVersion; + } + + /** + * 设置sdk版本 + * + * @param sdkVersion sdk版本 + */ + public void setSdkVersion(String sdkVersion) { + this.sdkVersion = sdkVersion; + } + + /** + * 获取sdk时间 + * + * @return sdk时间 + */ + public Date getSdkTime() { + return this.sdkTime; + } + + /** + * 设置sdk时间 + * + * @param sdkTime sdk时间 + */ + public void setSdkTime(Date sdkTime) { + this.sdkTime = sdkTime; + } + + /** + * 获取分配日期 + * + * @return 分配日期 + */ + public Date getCreateDate() { + return this.createDate; + } + + /** + * 设置分配日期 + * + * @param createDate 分配日期 + */ + public void setCreateDate(Date createDate) { + this.createDate = createDate; + } + + /** + * 获取是否升级 + * + * @return 是否升级 + */ + public String getIsUpgrade() { + return this.isUpgrade; + } + + /** + * 设置是否升级 + * + * @param isUpgrade 是否升级 + */ + public void setIsUpgrade(String isUpgrade) { + this.isUpgrade = isUpgrade; + } + + /** + * 获取更新版本 + * + * @return 更新版本 + */ + public String getUpgradeVersion() { + return this.upgradeVersion; + } + + /** + * 设置更新版本 + * + * @param upgradeVersion 更新版本 + */ + public void setUpgradeVersion(String upgradeVersion) { + this.upgradeVersion = upgradeVersion; + } + + /** + * 获取更新时间 + * + * @return 更新时间 + */ + public Date getUpgradeTime() { + return this.upgradeTime; + } + + /** + * 设置更新时间 + * + * @param upgradeTime 更新时间 + */ + public void setUpgradeTime(Date upgradeTime) { + this.upgradeTime = upgradeTime; + } + + /** + * 获取授权时间 + * + * @return 授权时间 + */ + public Date getAuthorizeTime() { + return this.authorizeTime; + } + + /** + * 设置授权时间 + * + * @param authorizeTime 授权时间 + */ + public void setAuthorizeTime(Date authorizeTime) { + this.authorizeTime = authorizeTime; + } + + /** + * 获取编号 + * + * @return 编号 + */ + public String getCreateCode() { + return this.createCode; + } + + /** + * 设置编号 + * + * @param createCode 编号 + */ + public void setCreateCode(String createCode) { + this.createCode = createCode; + } + + /** + * 获取MCU启动次数 + * + * @return MCU启动次数 + */ + public Integer getMcuCount() { + return this.mcuCount; + } + + /** + * 设置MCU启动次数 + * + * @param mcuCount MCU启动次数 + */ + public void setMcuCount(Integer mcuCount) { + this.mcuCount = mcuCount; + } + + /** + * 获取模块启动次数 + * + * @return 模块启动次数 + */ + public Integer getModuleCount() { + return this.moduleCount; + } + + /** + * 设置模块启动次数 + * + * @param moduleCount 模块启动次数 + */ + public void setModuleCount(Integer moduleCount) { + this.moduleCount = moduleCount; + } + + /** + * 获取连接路由器次数 + * + * @return 连接路由器次数 + */ + public Integer getRouterCount() { + return this.routerCount; + } + + /** + * 设置连接路由器次数 + * + * @param routerCount 连接路由器次数 + */ + public void setRouterCount(Integer routerCount) { + this.routerCount = routerCount; + } + + /** + * 获取成功连接服务器次数 + * + * @return 成功连接服务器次数 + */ + public Integer getServerCount() { + return this.serverCount; + } + + /** + * 设置成功连接服务器次数 + * + * @param serverCount 成功连接服务器次数 + */ + public void setServerCount(Integer serverCount) { + this.serverCount = serverCount; + } + + /** + * 获取尝试连接服务器次数 + * + * @return 尝试连接服务器次数 + */ + public Integer getServerTryCount() { + return this.serverTryCount; + } + + /** + * 设置尝试连接服务器次数 + * + * @param serverTryCount 尝试连接服务器次数 + */ + public void setServerTryCount(Integer serverTryCount) { + this.serverTryCount = serverTryCount; + } + + /** + * 获取mcu版本 + * + * @return mcu版本 + */ + public String getSoftwareVersion() { + return this.softwareVersion; + } + + /** + * 设置mcu版本 + * + * @param softwareVersion mcu版本 + */ + public void setSoftwareVersion(String softwareVersion) { + this.softwareVersion = softwareVersion; + } + + /** + * 获取硬件型号 + * + * @return 硬件型号 + */ + public String getHardwareType() { + return this.hardwareType; + } + + /** + * 设置硬件型号 + * + * @param hardwareType 硬件型号 + */ + public void setHardwareType(String hardwareType) { + this.hardwareType = hardwareType; + } + + /** + * 获取电子厂代码 + * + * @return 电子厂代码 + */ + public String getFactoryCode() { + return this.factoryCode; + } + + /** + * 设置电子厂代码 + * + * @param factoryCode 电子厂代码 + */ + public void setFactoryCode(String factoryCode) { + this.factoryCode = factoryCode; + } + + /** + * 获取鱼缸场代码 + * + * @return 鱼缸场代码 + */ + public String getBrandCode() { + return this.brandCode; + } + + /** + * 设置鱼缸场代码 + * + * @param brandCode 鱼缸场代码 + */ + public void setBrandCode(String brandCode) { + this.brandCode = brandCode; + } +} diff --git a/src/main/java/com/ifish/bean/Tbl_Device_User.java b/src/main/java/com/ifish/bean/Tbl_Device_User.java new file mode 100644 index 0000000..08184a0 --- /dev/null +++ b/src/main/java/com/ifish/bean/Tbl_Device_User.java @@ -0,0 +1,293 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.bean; + +import java.util.Date; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * 设备与用户关系表(tbl_device_user) + * + * @author bianj + * @version 1.0.0 2017-06-27 + */ +@Entity +@Table(name = "tbl_device_user") +public class Tbl_Device_User implements java.io.Serializable { + + /** + * 版本号 + */ + private static final long serialVersionUID = -4018159739383033383L; + + /** + * id + */ + @Id + @Column(name = "id", unique = true, nullable = false, length = 10) + private Integer id; + + /** + * 用户Id + */ + @Column(name = "user_id", unique = true, nullable = false, length = 10) + private Integer userId; + + /** + * 设备Id + */ + @Column(name = "device_id", unique = true, nullable = false, length = 10) + private Integer deviceId; + + /** + * 是否主控:1、主控制权,0、被分享者 + */ + @Column(name = "is_master", nullable = true, length = 1) + private String isMaster; + + /** + * 显示名称 + */ + @Column(name = "show_name", nullable = true, length = 50) + private String showName; + + /** + * 创建时间 + */ + @Column(name = "create_time", nullable = true) + private Date createTime; + + /** + * 修改时间 + */ + @Column(name = "update_time", nullable = true) + private Date updateTime; + + /** + * 保存的显示图标 + */ + @Column(name = "custom_icon_name", nullable = true, length = 100) + private String customIconName; + + /** + * 保存的显示名称 + */ + @Column(name = "custom_show_name", nullable = true, length = 100) + private String customShowName; + + /** + * 是否看护 + */ + @Column(name = "is_look", nullable = true, length = 1) + private String isLook; + + /** + * 是否直播 + */ + @Column(name = "is_live", nullable = true, length = 1) + private String isLive; + + /** + * 获取id + * + * @return id + */ + public Integer getId() { + return this.id; + } + + /** + * 设置id + * + * @param id id + */ + public void setId(Integer id) { + this.id = id; + } + + /** + * 获取用户Id + * + * @return 用户Id + */ + public Integer getUserId() { + return this.userId; + } + + /** + * 设置用户Id + * + * @param userId 用户Id + */ + public void setUserId(Integer userId) { + this.userId = userId; + } + + /** + * 获取设备Id + * + * @return 设备Id + */ + public Integer getDeviceId() { + return this.deviceId; + } + + /** + * 设置设备Id + * + * @param deviceId 设备Id + */ + public void setDeviceId(Integer deviceId) { + this.deviceId = deviceId; + } + + /** + * 获取是否主控:1、主控制权,0、被分享者 + * + * @return 是否主控:1、主控制权 + */ + public String getIsMaster() { + return this.isMaster; + } + + /** + * 设置是否主控:1、主控制权,0、被分享者 + * + * @param isMaster 是否主控:1、主控制权,0、被分享者 + */ + public void setIsMaster(String isMaster) { + this.isMaster = isMaster; + } + + /** + * 获取显示名称 + * + * @return 显示名称 + */ + public String getShowName() { + return this.showName; + } + + /** + * 设置显示名称 + * + * @param showName 显示名称 + */ + public void setShowName(String showName) { + this.showName = showName; + } + + /** + * 获取创建时间 + * + * @return 创建时间 + */ + public Date getCreateTime() { + return this.createTime; + } + + /** + * 设置创建时间 + * + * @param createTime 创建时间 + */ + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + /** + * 获取修改时间 + * + * @return 修改时间 + */ + public Date getUpdateTime() { + return this.updateTime; + } + + /** + * 设置修改时间 + * + * @param updateTime 修改时间 + */ + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + + /** + * 获取保存的显示图标 + * + * @return 保存的显示图标 + */ + public String getCustomIconName() { + return this.customIconName; + } + + /** + * 设置保存的显示图标 + * + * @param customIconName 保存的显示图标 + */ + public void setCustomIconName(String customIconName) { + this.customIconName = customIconName; + } + + /** + * 获取保存的显示名称 + * + * @return 保存的显示名称 + */ + public String getCustomShowName() { + return this.customShowName; + } + + /** + * 设置保存的显示名称 + * + * @param customShowName 保存的显示名称 + */ + public void setCustomShowName(String customShowName) { + this.customShowName = customShowName; + } + + /** + * 获取是否看护 + * + * @return 是否看护 + */ + public String getIsLook() { + return this.isLook; + } + + /** + * 设置是否看护 + * + * @param isLook 是否看护 + */ + public void setIsLook(String isLook) { + this.isLook = isLook; + } + + /** + * 获取是否直播 + * + * @return 是否直播 + */ + public String getIsLive() { + return this.isLive; + } + + /** + * 设置是否直播 + * + * @param isLive 是否直播 + */ + public void setIsLive(String isLive) { + this.isLive = isLive; + } +} diff --git a/src/main/java/com/ifish/bean/Tbl_HardWare_Type.java b/src/main/java/com/ifish/bean/Tbl_HardWare_Type.java new file mode 100644 index 0000000..7760168 --- /dev/null +++ b/src/main/java/com/ifish/bean/Tbl_HardWare_Type.java @@ -0,0 +1,437 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.bean; + +import java.util.Date; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * 设备类型详情表(tbl_hardware_type) + * + * @author bianj + * @version 1.0.0 2017-06-27 + */ +@Entity +@Table(name = "tbl_hardware_type") +public class Tbl_HardWare_Type implements java.io.Serializable { + + /** + * 版本号 + */ + private static final long serialVersionUID = 7870932947017585134L; + + /** + * 设备型号代码 + */ + @Id + @Column(name = "hardware_type", unique = true, nullable = false, length = 10) + private String hardwareType; + + /** + * 电子厂代码 + */ + @Column(name = "factory_code", nullable = true, length = 20) + private String factoryCode; + + /** + * 设备名称 + */ + @Column(name = "hardware_name", nullable = false, length = 20) + private String hardwareName; + + /** + * 描述 + */ + @Column(name = "hardware_desc", nullable = true, length = 100) + private String hardwareDesc; + + /** + * 创建时间 + */ + @Column(name = "create_time", nullable = true) + private Date createTime; + + /** + * 控制个数 + */ + @Column(name = "control_amount", nullable = true, length = 10) + private Integer controlAmount; + + /** + * 定时器个数 + */ + @Column(name = "timer_amount", nullable = true, length = 10) + private Integer timerAmount; + + /** + * 是否自定义图标:1是、0否 + */ + @Column(name = "is_custom_icon", nullable = true, length = 1) + private String isCustomIcon; + + /** + * 自定义图标根地址 + */ + @Column(name = "icon_link", nullable = true, length = 200) + private String iconLink; + + /** + * 根地址下图标名称 + */ + @Column(name = "all_icon_name", nullable = true, length = 200) + private String allIconName; + + /** + * 修改时间 + */ + @Column(name = "update_time", nullable = true) + private Date updateTime; + + /** + * 是否有背光:1是、0否 + */ + @Column(name = "is_lightness", nullable = true, length = 1) + private String isLightness; + + /** + * 是否有柜灯:1是、0否 + */ + @Column(name = "is_sark_lamp", nullable = true, length = 1) + private String isSarkLamp; + + /** + * 是否有工作模式:1是、0否 + */ + @Column(name = "is_work_model", nullable = true, length = 1) + private String isWorkModel; + + /** + * 显示名称 + */ + @Column(name = "all_show_name", nullable = true, length = 200) + private String allShowName; + + /** + * 默认名称 + */ + @Column(name = "default_show_name", nullable = true, length = 200) + private String defaultShowName; + + /** + * 默认图标 + */ + @Column(name = "default_icon_name", nullable = true, length = 200) + private String defaultIconName; + + /** + * 获取设备型号代码 + * + * @return 设备型号代码 + */ + public String getHardwareType() { + return this.hardwareType; + } + + /** + * 设置设备型号代码 + * + * @param hardwareType 设备型号代码 + */ + public void setHardwareType(String hardwareType) { + this.hardwareType = hardwareType; + } + + /** + * 获取电子厂代码 + * + * @return 电子厂代码 + */ + public String getFactoryCode() { + return this.factoryCode; + } + + /** + * 设置电子厂代码 + * + * @param factoryCode 电子厂代码 + */ + public void setFactoryCode(String factoryCode) { + this.factoryCode = factoryCode; + } + + /** + * 获取设备名称 + * + * @return 设备名称 + */ + public String getHardwareName() { + return this.hardwareName; + } + + /** + * 设置设备名称 + * + * @param hardwareName 设备名称 + */ + public void setHardwareName(String hardwareName) { + this.hardwareName = hardwareName; + } + + /** + * 获取描述 + * + * @return 描述 + */ + public String getHardwareDesc() { + return this.hardwareDesc; + } + + /** + * 设置描述 + * + * @param hardwareDesc 描述 + */ + public void setHardwareDesc(String hardwareDesc) { + this.hardwareDesc = hardwareDesc; + } + + /** + * 获取创建时间 + * + * @return 创建时间 + */ + public Date getCreateTime() { + return this.createTime; + } + + /** + * 设置创建时间 + * + * @param createTime 创建时间 + */ + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + /** + * 获取控制个数 + * + * @return 控制个数 + */ + public Integer getControlAmount() { + return this.controlAmount; + } + + /** + * 设置控制个数 + * + * @param controlAmount 控制个数 + */ + public void setControlAmount(Integer controlAmount) { + this.controlAmount = controlAmount; + } + + /** + * 获取定时器个数 + * + * @return 定时器个数 + */ + public Integer getTimerAmount() { + return this.timerAmount; + } + + /** + * 设置定时器个数 + * + * @param timerAmount 定时器个数 + */ + public void setTimerAmount(Integer timerAmount) { + this.timerAmount = timerAmount; + } + + /** + * 获取是否自定义图标:1是、0否 + * + * @return 是否自定义图标 + */ + public String getIsCustomIcon() { + return this.isCustomIcon; + } + + /** + * 设置是否自定义图标:1是、0否 + * + * @param isCustomIcon 是否自定义图标:1是、0否 + */ + public void setIsCustomIcon(String isCustomIcon) { + this.isCustomIcon = isCustomIcon; + } + + /** + * 获取自定义图标根地址 + * + * @return 自定义图标根地址 + */ + public String getIconLink() { + return this.iconLink; + } + + /** + * 设置自定义图标根地址 + * + * @param iconLink 自定义图标根地址 + */ + public void setIconLink(String iconLink) { + this.iconLink = iconLink; + } + + /** + * 获取根地址下图标名称 + * + * @return 根地址下图标名称 + */ + public String getAllIconName() { + return this.allIconName; + } + + /** + * 设置根地址下图标名称 + * + * @param allIconName 根地址下图标名称 + */ + public void setAllIconName(String allIconName) { + this.allIconName = allIconName; + } + + /** + * 获取修改时间 + * + * @return 修改时间 + */ + public Date getUpdateTime() { + return this.updateTime; + } + + /** + * 设置修改时间 + * + * @param updateTime 修改时间 + */ + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + + /** + * 获取是否有背光:1是、0否 + * + * @return 是否有背光 + */ + public String getIsLightness() { + return this.isLightness; + } + + /** + * 设置是否有背光:1是、0否 + * + * @param isLightness 是否有背光:1是、0否 + */ + public void setIsLightness(String isLightness) { + this.isLightness = isLightness; + } + + /** + * 获取是否有柜灯:1是、0否 + * + * @return 是否有柜灯 + */ + public String getIsSarkLamp() { + return this.isSarkLamp; + } + + /** + * 设置是否有柜灯:1是、0否 + * + * @param isSarkLamp 是否有柜灯:1是、0否 + */ + public void setIsSarkLamp(String isSarkLamp) { + this.isSarkLamp = isSarkLamp; + } + + /** + * 获取是否有工作模式:1是、0否 + * + * @return 是否有工作模式 + */ + public String getIsWorkModel() { + return this.isWorkModel; + } + + /** + * 设置是否有工作模式:1是、0否 + * + * @param isWorkModel 是否有工作模式:1是、0否 + */ + public void setIsWorkModel(String isWorkModel) { + this.isWorkModel = isWorkModel; + } + + /** + * 获取显示名称 + * + * @return 显示名称 + */ + public String getAllShowName() { + return this.allShowName; + } + + /** + * 设置显示名称 + * + * @param allShowName 显示名称 + */ + public void setAllShowName(String allShowName) { + this.allShowName = allShowName; + } + + /** + * 获取默认名称 + * + * @return 默认名称 + */ + public String getDefaultShowName() { + return this.defaultShowName; + } + + /** + * 设置默认名称 + * + * @param defaultShowName 默认名称 + */ + public void setDefaultShowName(String defaultShowName) { + this.defaultShowName = defaultShowName; + } + + /** + * 获取默认图标 + * + * @return 默认图标 + */ + public String getDefaultIconName() { + return this.defaultIconName; + } + + /** + * 设置默认图标 + * + * @param defaultIconName 默认图标 + */ + public void setDefaultIconName(String defaultIconName) { + this.defaultIconName = defaultIconName; + } +} diff --git a/src/main/java/com/ifish/bean/Tbl_Live_Message.java b/src/main/java/com/ifish/bean/Tbl_Live_Message.java new file mode 100644 index 0000000..5b915b7 --- /dev/null +++ b/src/main/java/com/ifish/bean/Tbl_Live_Message.java @@ -0,0 +1,231 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.bean; + +import java.util.Date; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * 直播间评论表(tbl_live_message) + * + * @author bianj + * @version 1.0.0 2017-07-03 + */ +@Entity +@Table(name = "tbl_live_message") +public class Tbl_Live_Message implements java.io.Serializable { + + /** + * 版本号 + */ + private static final long serialVersionUID = 4867709378808071267L; + + /** + * 评论Id + */ + @Id + @Column(name = "message_id", unique = true, nullable = false, length = 10) + private Integer messageId; + + /** + * 直播间Id + */ + @Column(name = "room_id", nullable = false, length = 10) + private Integer roomId; + + /** + * 评论用户Id + */ + @Column(name = "user_id", nullable = false, length = 10) + private Integer userId; + + /** + * @用户Id + */ + @Column(name = "as_user_id", nullable = true, length = 10) + private Integer asUserId; + + /** + * 评论内容 + */ + @Column(name = "message_content", nullable = true, length = 200) + private String messageContent; + + /** + * 评论时间 + */ + @Column(name = "create_time", nullable = true) + private Date createTime; + + /** + * @人的用户名 + */ + private String asUserName; + + /** + * 创建人的头像 + */ + private String userImg; + + /** + * 创建人的用户名 + */ + private String userName; + + /** + * @return the asUserName + */ + public String getAsUserName() { + return asUserName; + } + + /** + * @param asUserName the asUserName to set + */ + public void setAsUserName(String asUserName) { + this.asUserName = asUserName; + } + + /** + * @return the userImg + */ + public String getUserImg() { + return userImg; + } + + /** + * @param userImg the userImg to set + */ + public void setUserImg(String userImg) { + this.userImg = userImg; + } + + /** + * @return the userName + */ + public String getUserName() { + return userName; + } + + /** + * @param userName the userName to set + */ + public void setUserName(String userName) { + this.userName = userName; + } + + /** + * 获取评论Id + * + * @return 评论Id + */ + public Integer getMessageId() { + return this.messageId; + } + + /** + * 设置评论Id + * + * @param messageId 评论Id + */ + public void setMessageId(Integer messageId) { + this.messageId = messageId; + } + + /** + * 获取直播间Id + * + * @return 直播间Id + */ + public Integer getRoomId() { + return this.roomId; + } + + /** + * 设置直播间Id + * + * @param roomId 直播间Id + */ + public void setRoomId(Integer roomId) { + this.roomId = roomId; + } + + /** + * 获取评论用户Id + * + * @return 评论用户Id + */ + public Integer getUserId() { + return this.userId; + } + + /** + * 设置评论用户Id + * + * @param userId 评论用户Id + */ + public void setUserId(Integer userId) { + this.userId = userId; + } + + /** + * 获取@用户Id + * + * @return @用户Id + */ + public Integer getAsUserId() { + return this.asUserId; + } + + /** + * 设置@用户Id + * + * @param asUserId + * @用户Id + */ + public void setAsUserId(Integer asUserId) { + this.asUserId = asUserId; + } + + /** + * 获取评论内容 + * + * @return 评论内容 + */ + public String getMessageContent() { + return this.messageContent; + } + + /** + * 设置评论内容 + * + * @param messageContent 评论内容 + */ + public void setMessageContent(String messageContent) { + this.messageContent = messageContent; + } + + /** + * 获取评论时间 + * + * @return 评论时间 + */ + public Date getCreateTime() { + return this.createTime; + } + + /** + * 设置评论时间 + * + * @param createTime 评论时间 + */ + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } +} diff --git a/src/main/java/com/ifish/bean/Tbl_Live_Room.java b/src/main/java/com/ifish/bean/Tbl_Live_Room.java new file mode 100644 index 0000000..723b43b --- /dev/null +++ b/src/main/java/com/ifish/bean/Tbl_Live_Room.java @@ -0,0 +1,317 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.bean; + +import java.util.Date; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * 直播间详情表(tbl_live_room) + * + * @author bianj + * @version 1.0.0 2017-07-03 + */ +@Entity +@Table(name = "tbl_live_room") +public class Tbl_Live_Room implements java.io.Serializable { + + /** + * 版本号 + */ + private static final long serialVersionUID = -4747733838201318438L; + + /** + * 直播间Id + */ + @Id + @Column(name = "room_id", unique = true, nullable = false, length = 10) + private Integer roomId; + + /** + * 用户Id + */ + @Column(name = "user_id", unique = true, nullable = false, length = 10) + private Integer userId; + + /** + * 摄像头ID + */ + @Column(name = "camera_id", nullable = true, length = 20) + private String cameraId; + + /** + * 直播间名称 + */ + @Column(name = "room_name", nullable = true, length = 20) + private String roomName; + + /** + * 直播间描述 + */ + @Column(name = "room_desc", nullable = true, length = 70) + private String roomDesc; + + /** + * */ + @Column(name = "room_img", nullable = true, length = 50) + private String roomImg; + + /** + * 直播间状态:1直播、0关闭 + */ + @Column(name = "room_status", nullable = true, length = 1) + private String roomStatus; + + /** + * 人气值 + */ + @Column(name = "popularity_value", nullable = false, length = 10) + private Integer popularityValue; + + /** + * 创建时间 + */ + @Column(name = "create_time", nullable = true) + private Date createTime; + + /** + * 是否推荐 + */ + @Column(name = "is_tuijian", nullable = false, length = 1) + private Integer isTuijian; + + /** + * 推荐排序 + */ + @Column(name = "tuijian_num", nullable = true, length = 10) + private Integer tuijianNum; + + /** + * 首次分享 + */ + @Column(name = "first_share", nullable = false, length = 1) + private Integer firstShare; + + /** + * 获取直播间Id + * + * @return 直播间Id + */ + public Integer getRoomId() { + return this.roomId; + } + + /** + * 设置直播间Id + * + * @param roomId 直播间Id + */ + public void setRoomId(Integer roomId) { + this.roomId = roomId; + } + + /** + * 获取用户Id + * + * @return 用户Id + */ + public Integer getUserId() { + return this.userId; + } + + /** + * 设置用户Id + * + * @param userId 用户Id + */ + public void setUserId(Integer userId) { + this.userId = userId; + } + + /** + * 获取摄像头ID + * + * @return 摄像头ID + */ + public String getCameraId() { + return this.cameraId; + } + + /** + * 设置摄像头ID + * + * @param cameraId 摄像头ID + */ + public void setCameraId(String cameraId) { + this.cameraId = cameraId; + } + + /** + * 获取直播间名称 + * + * @return 直播间名称 + */ + public String getRoomName() { + return this.roomName; + } + + /** + * 设置直播间名称 + * + * @param roomName 直播间名称 + */ + public void setRoomName(String roomName) { + this.roomName = roomName; + } + + /** + * 获取直播间描述 + * + * @return 直播间描述 + */ + public String getRoomDesc() { + return this.roomDesc; + } + + /** + * 设置直播间描述 + * + * @param roomDesc 直播间描述 + */ + public void setRoomDesc(String roomDesc) { + this.roomDesc = roomDesc; + } + + /** + * 获取 + * + * @return + */ + public String getRoomImg() { + return this.roomImg; + } + + /** + * 设置 + * + * @param roomImg + * + */ + public void setRoomImg(String roomImg) { + this.roomImg = roomImg; + } + + /** + * 获取直播间状态:1直播、0关闭 + * + * @return 直播间状态 + */ + public String getRoomStatus() { + return this.roomStatus; + } + + /** + * 设置直播间状态:1直播、0关闭 + * + * @param roomStatus 直播间状态:1直播、0关闭 + */ + public void setRoomStatus(String roomStatus) { + this.roomStatus = roomStatus; + } + + /** + * 获取人气值 + * + * @return 人气值 + */ + public Integer getPopularityValue() { + return this.popularityValue; + } + + /** + * 设置人气值 + * + * @param popularityValue 人气值 + */ + public void setPopularityValue(Integer popularityValue) { + this.popularityValue = popularityValue; + } + + /** + * 获取创建时间 + * + * @return 创建时间 + */ + public Date getCreateTime() { + return this.createTime; + } + + /** + * 设置创建时间 + * + * @param createTime 创建时间 + */ + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + /** + * 获取是否推荐 + * + * @return 是否推荐 + */ + public Integer getIsTuijian() { + return this.isTuijian; + } + + /** + * 设置是否推荐 + * + * @param isTuijian 是否推荐 + */ + public void setIsTuijian(Integer isTuijian) { + this.isTuijian = isTuijian; + } + + /** + * 获取推荐排序 + * + * @return 推荐排序 + */ + public Integer getTuijianNum() { + return this.tuijianNum; + } + + /** + * 设置推荐排序 + * + * @param tuijianNum 推荐排序 + */ + public void setTuijianNum(Integer tuijianNum) { + this.tuijianNum = tuijianNum; + } + + /** + * 获取首次分享 + * + * @return 首次分享 + */ + public Integer getFirstShare() { + return this.firstShare; + } + + /** + * 设置首次分享 + * + * @param firstShare 首次分享 + */ + public void setFirstShare(Integer firstShare) { + this.firstShare = firstShare; + } +} diff --git a/src/main/java/com/ifish/bean/Tbl_Push_List.java b/src/main/java/com/ifish/bean/Tbl_Push_List.java new file mode 100644 index 0000000..8bfa849 --- /dev/null +++ b/src/main/java/com/ifish/bean/Tbl_Push_List.java @@ -0,0 +1,465 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.bean; + +import java.util.Date; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * 推送详情表(tbl_push_list) + * + * @author bianj + * @version 1.0.0 2017-07-03 + */ +@Entity +@Table(name = "tbl_push_list") +public class Tbl_Push_List implements java.io.Serializable { + + /** + * 版本号 + */ + private static final long serialVersionUID = -7760764975977010045L; + + /** + * ID + */ + @Id + @Column(name = "push_id", unique = true, nullable = false, length = 10) + private Integer pushId; + + /** + * 用户Id + */ + @Column(name = "user_id", nullable = true, length = 10) + private Integer userId; + + /** + * 设备Id + */ + @Column(name = "device_id", nullable = true, length = 10) + private Integer deviceId; + + /** + * 显示名称 + */ + @Column(name = "show_name", nullable = true, length = 20) + private String showName; + + /** + * 推送手机类型 + */ + @Column(name = "phone_type", nullable = true, length = 20) + private String phoneType; + + /** + * 推送消息类型 + * 1."remove_device","解绑通知";2."wendu_warn","温度预警;3."qu_reply","问题反馈";4."app_update","IOS更新推送";5."remind_water","换水提醒";6."offline_push","离线通知";7."send_report","看护报告";8."shops_push","看护通知";9."all_push","所有用户推送" + */ + @Column(name = "push_type", nullable = true, length = 20) + private String pushType; + + /** + * 推送标题 + */ + @Column(name = "push_title", nullable = true, length = 100) + private String pushTitle; + + /** + * 推送内容 + */ + @Column(name = "push_context", nullable = true, length = 200) + private String pushContext; + + /** + * 创建时间 + */ + @Column(name = "create_time", nullable = true) + private Date createTime; + + /** + * 链接 + */ + @Column(name = "push_link", nullable = false, length = 100) + private String pushLink; + + /** + * 极光推送状态 + */ + @Column(name = "jpush_status", nullable = true, length = 1) + private String jpushStatus; + + /** + * 谷歌推送状态 + */ + @Column(name = "google_status", nullable = true, length = 1) + private String googleStatus; + + /** + * 看护报告Id + */ + @Column(name = "report_id", nullable = true, length = 10) + private Integer reportId; + + /** + * MCU启动次数 + */ + @Column(name = "mcu_count", nullable = true, length = 10) + private Integer mcuCount; + + /** + * 模块启动次数 + */ + @Column(name = "modular_count", nullable = true, length = 10) + private Integer modularCount; + + /** + * 连接路由器次数 + */ + @Column(name = "router_count", nullable = true, length = 10) + private Integer routerCount; + + /** + * 成功连接服务器次数 + */ + @Column(name = "server_count", nullable = true, length = 10) + private Integer serverCount; + + /** + * 尝试连接服务器次数 + */ + @Column(name = "server_try_count", nullable = true, length = 10) + private Integer serverTryCount; + + /** + * 获取ID + * + * @return ID + */ + public Integer getPushId() { + return this.pushId; + } + + /** + * 设置ID + * + * @param pushId ID + */ + public void setPushId(Integer pushId) { + this.pushId = pushId; + } + + /** + * 获取用户Id + * + * @return 用户Id + */ + public Integer getUserId() { + return this.userId; + } + + /** + * 设置用户Id + * + * @param userId 用户Id + */ + public void setUserId(Integer userId) { + this.userId = userId; + } + + /** + * 获取设备Id + * + * @return 设备Id + */ + public Integer getDeviceId() { + return this.deviceId; + } + + /** + * 设置设备Id + * + * @param deviceId 设备Id + */ + public void setDeviceId(Integer deviceId) { + this.deviceId = deviceId; + } + + /** + * 获取显示名称 + * + * @return 显示名称 + */ + public String getShowName() { + return this.showName; + } + + /** + * 设置显示名称 + * + * @param showName 显示名称 + */ + public void setShowName(String showName) { + this.showName = showName; + } + + /** + * 获取推送手机类型 + * + * @return 推送手机类型 + */ + public String getPhoneType() { + return this.phoneType; + } + + /** + * 设置推送手机类型 + * + * @param phoneType 推送手机类型 + */ + public void setPhoneType(String phoneType) { + this.phoneType = phoneType; + } + + /** + * 获取推送消息类型 + * 1."remove_device","解绑通知";2."wendu_warn","温度预警;3."qu_reply","问题反馈";4."app_update","IOS更新推送";5."remind_water","换水提醒";6."offline_push","离线通知";7."send_report","看护报告";8."shops_push","看护通知";9."all_push","所有用户推送" + * + * @return 推送消息类型 1."remove_device" + */ + public String getPushType() { + return this.pushType; + } + + /** + * 设置推送消息类型 + * 1."remove_device","解绑通知";2."wendu_warn","温度预警;3."qu_reply","问题反馈";4."app_update","IOS更新推送";5."remind_water","换水提醒";6."offline_push","离线通知";7."send_report","看护报告";8."shops_push","看护通知";9."all_push","所有用户推送" + * + * @param pushType 推送消息类型 + * 1."remove_device","解绑通知";2."wendu_warn","温度预警;3."qu_reply","问题反馈";4."app_update","IOS更新推送";5."remind_water","换水提醒";6."offline_push","离线通知";7."send_report","看护报告";8."shops_push","看护通知";9."all_push","所有用户推送" + */ + public void setPushType(String pushType) { + this.pushType = pushType; + } + + /** + * 获取推送标题 + * + * @return 推送标题 + */ + public String getPushTitle() { + return this.pushTitle; + } + + /** + * 设置推送标题 + * + * @param pushTitle 推送标题 + */ + public void setPushTitle(String pushTitle) { + this.pushTitle = pushTitle; + } + + /** + * 获取推送内容 + * + * @return 推送内容 + */ + public String getPushContext() { + return this.pushContext; + } + + /** + * 设置推送内容 + * + * @param pushContext 推送内容 + */ + public void setPushContext(String pushContext) { + this.pushContext = pushContext; + } + + /** + * 获取创建时间 + * + * @return 创建时间 + */ + public Date getCreateTime() { + return this.createTime; + } + + /** + * 设置创建时间 + * + * @param createTime 创建时间 + */ + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + /** + * 获取链接 + * + * @return 链接 + */ + public String getPushLink() { + return this.pushLink; + } + + /** + * 设置链接 + * + * @param pushLink 链接 + */ + public void setPushLink(String pushLink) { + this.pushLink = pushLink; + } + + /** + * 获取极光推送状态 + * + * @return 极光推送状态 + */ + public String getJpushStatus() { + return this.jpushStatus; + } + + /** + * 设置极光推送状态 + * + * @param jpushStatus 极光推送状态 + */ + public void setJpushStatus(String jpushStatus) { + this.jpushStatus = jpushStatus; + } + + /** + * 获取谷歌推送状态 + * + * @return 谷歌推送状态 + */ + public String getGoogleStatus() { + return this.googleStatus; + } + + /** + * 设置谷歌推送状态 + * + * @param googleStatus 谷歌推送状态 + */ + public void setGoogleStatus(String googleStatus) { + this.googleStatus = googleStatus; + } + + /** + * 获取看护报告Id + * + * @return 看护报告Id + */ + public Integer getReportId() { + return this.reportId; + } + + /** + * 设置看护报告Id + * + * @param reportId 看护报告Id + */ + public void setReportId(Integer reportId) { + this.reportId = reportId; + } + + /** + * 获取MCU启动次数 + * + * @return MCU启动次数 + */ + public Integer getMcuCount() { + return this.mcuCount; + } + + /** + * 设置MCU启动次数 + * + * @param mcuCount MCU启动次数 + */ + public void setMcuCount(Integer mcuCount) { + this.mcuCount = mcuCount; + } + + /** + * 获取模块启动次数 + * + * @return 模块启动次数 + */ + public Integer getModularCount() { + return this.modularCount; + } + + /** + * 设置模块启动次数 + * + * @param modularCount 模块启动次数 + */ + public void setModularCount(Integer modularCount) { + this.modularCount = modularCount; + } + + /** + * 获取连接路由器次数 + * + * @return 连接路由器次数 + */ + public Integer getRouterCount() { + return this.routerCount; + } + + /** + * 设置连接路由器次数 + * + * @param routerCount 连接路由器次数 + */ + public void setRouterCount(Integer routerCount) { + this.routerCount = routerCount; + } + + /** + * 获取成功连接服务器次数 + * + * @return 成功连接服务器次数 + */ + public Integer getServerCount() { + return this.serverCount; + } + + /** + * 设置成功连接服务器次数 + * + * @param serverCount 成功连接服务器次数 + */ + public void setServerCount(Integer serverCount) { + this.serverCount = serverCount; + } + + /** + * 获取尝试连接服务器次数 + * + * @return 尝试连接服务器次数 + */ + public Integer getServerTryCount() { + return this.serverTryCount; + } + + /** + * 设置尝试连接服务器次数 + * + * @param serverTryCount 尝试连接服务器次数 + */ + public void setServerTryCount(Integer serverTryCount) { + this.serverTryCount = serverTryCount; + } +} diff --git a/src/main/java/com/ifish/bean/Tbl_User.java b/src/main/java/com/ifish/bean/Tbl_User.java new file mode 100644 index 0000000..57cb9af --- /dev/null +++ b/src/main/java/com/ifish/bean/Tbl_User.java @@ -0,0 +1,557 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.bean; + +import java.util.Date; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * 用户详情表(tbl_user) + * + * @author bianj + * @version 1.0.0 2017-06-28 + */ +@Entity +@Table(name = "tbl_user") +public class Tbl_User implements java.io.Serializable { + + /** + * 版本号 + */ + private static final long serialVersionUID = -3293426131332327827L; + + /** + * 用户Id + */ + @Id + @Column(name = "user_id", unique = true, nullable = false, length = 10) + private Integer userId; + + /** + * 昵称 + */ + @Column(name = "nick_name", nullable = true, length = 20) + private String nickName; + + /** + * 密码 + */ + @Column(name = "user_password", nullable = true, length = 32) + private String userPassword; + + /** + * 手机 + */ + @Column(name = "phone_number", unique = true, nullable = true, length = 11) + private String phoneNumber; + + /** + * 邮箱 + */ + @Column(name = "user_email", unique = true, nullable = true, length = 50) + private String userEmail; + + /** + * 用户类型 + */ + @Column(name = "user_type", nullable = false, length = 1) + private String userType; + + /** + * 头像 + */ + @Column(name = "user_img", nullable = true, length = 100) + private String userImg; + + /** + * 性别 + */ + @Column(name = "user_sex", nullable = true, length = 1) + private String userSex; + + /** + * 登陆次数 + */ + @Column(name = "login_count", nullable = true, length = 10) + private Integer loginCount; + + /** + * 修改时间 + */ + @Column(name = "update_time", nullable = true) + private Date updateTime; + + /** + * 登陆时间 + */ + @Column(name = "login_time", nullable = true) + private Date loginTime; + + /** + * 注册时间 + */ + @Column(name = "create_time", nullable = true) + private Date createTime; + + /** + * 登陆手机类型 + */ + @Column(name = "login_type", nullable = true, length = 10) + private String loginType; + + /** + * 备注 + */ + @Column(name = "remarks", nullable = true, length = 100) + private String remarks; + + /** + * 地址 + */ + @Column(name = "address", nullable = true, length = 200) + private String address; + + /** + * 技威Code1 + */ + @Column(name = "p2pverify_code1", nullable = true, length = 50) + private String p2pverifyCode1; + + /** + * 技威Code2 + */ + @Column(name = "p2pverify_code2", nullable = true, length = 50) + private String p2pverifyCode2; + + /** + * 技威用户ID + */ + @Column(name = "gwell_userid", nullable = true, length = 50) + private String gwellUserid; + + /** + * 是否注册技威:1已注册、0未注册 + */ + @Column(name = "is_register_gwell", nullable = true, length = 1) + private String isRegisterGwell; + + /** + * 极光用户ID + */ + @Column(name = "jiguang_userid", nullable = true, length = 50) + private String jiguangUserid; + + /** + * 经度 + */ + @Column(name = "longitude", nullable = true) + private Double longitude; + + /** + * 纬度 + */ + @Column(name = "latitude", nullable = true) + private Double latitude; + + /** + * 获取用户Id + * + * @return 用户Id + */ + public Integer getUserId() { + return this.userId; + } + + /** + * 设置用户Id + * + * @param userId 用户Id + */ + public void setUserId(Integer userId) { + this.userId = userId; + } + + /** + * 获取昵称 + * + * @return 昵称 + */ + public String getNickName() { + return this.nickName; + } + + /** + * 设置昵称 + * + * @param nickName 昵称 + */ + public void setNickName(String nickName) { + this.nickName = nickName; + } + + /** + * 获取密码 + * + * @return 密码 + */ + public String getUserPassword() { + return this.userPassword; + } + + /** + * 设置密码 + * + * @param userPassword 密码 + */ + public void setUserPassword(String userPassword) { + this.userPassword = userPassword; + } + + /** + * 获取手机 + * + * @return 手机 + */ + public String getPhoneNumber() { + return this.phoneNumber; + } + + /** + * 设置手机 + * + * @param phoneNumber 手机 + */ + public void setPhoneNumber(String phoneNumber) { + this.phoneNumber = phoneNumber; + } + + /** + * 获取邮箱 + * + * @return 邮箱 + */ + public String getUserEmail() { + return this.userEmail; + } + + /** + * 设置邮箱 + * + * @param userEmail 邮箱 + */ + public void setUserEmail(String userEmail) { + this.userEmail = userEmail; + } + + /** + * 获取用户类型 + * + * @return 用户类型 + */ + public String getUserType() { + return this.userType; + } + + /** + * 设置用户类型 + * + * @param userType 用户类型 + */ + public void setUserType(String userType) { + this.userType = userType; + } + + /** + * 获取头像 + * + * @return 头像 + */ + public String getUserImg() { + return this.userImg; + } + + /** + * 设置头像 + * + * @param userImg 头像 + */ + public void setUserImg(String userImg) { + this.userImg = userImg; + } + + /** + * 获取性别 + * + * @return 性别 + */ + public String getUserSex() { + return this.userSex; + } + + /** + * 设置性别 + * + * @param userSex 性别 + */ + public void setUserSex(String userSex) { + this.userSex = userSex; + } + + /** + * 获取登陆次数 + * + * @return 登陆次数 + */ + public Integer getLoginCount() { + return this.loginCount; + } + + /** + * 设置登陆次数 + * + * @param loginCount 登陆次数 + */ + public void setLoginCount(Integer loginCount) { + this.loginCount = loginCount; + } + + /** + * 获取修改时间 + * + * @return 修改时间 + */ + public Date getUpdateTime() { + return this.updateTime; + } + + /** + * 设置修改时间 + * + * @param updateTime 修改时间 + */ + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + + /** + * 获取登陆时间 + * + * @return 登陆时间 + */ + public Date getLoginTime() { + return this.loginTime; + } + + /** + * 设置登陆时间 + * + * @param loginTime 登陆时间 + */ + public void setLoginTime(Date loginTime) { + this.loginTime = loginTime; + } + + /** + * 获取注册时间 + * + * @return 注册时间 + */ + public Date getCreateTime() { + return this.createTime; + } + + /** + * 设置注册时间 + * + * @param createTime 注册时间 + */ + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + /** + * 获取登陆手机类型 + * + * @return 登陆手机类型 + */ + public String getLoginType() { + return this.loginType; + } + + /** + * 设置登陆手机类型 + * + * @param loginType 登陆手机类型 + */ + public void setLoginType(String loginType) { + this.loginType = loginType; + } + + /** + * 获取备注 + * + * @return 备注 + */ + public String getRemarks() { + return this.remarks; + } + + /** + * 设置备注 + * + * @param remarks 备注 + */ + public void setRemarks(String remarks) { + this.remarks = remarks; + } + + /** + * 获取地址 + * + * @return 地址 + */ + public String getAddress() { + return this.address; + } + + /** + * 设置地址 + * + * @param address 地址 + */ + public void setAddress(String address) { + this.address = address; + } + + /** + * 获取技威Code1 + * + * @return 技威Code1 + */ + public String getP2pverifyCode1() { + return this.p2pverifyCode1; + } + + /** + * 设置技威Code1 + * + * @param p2pverifyCode1 技威Code1 + */ + public void setP2pverifyCode1(String p2pverifyCode1) { + this.p2pverifyCode1 = p2pverifyCode1; + } + + /** + * 获取技威Code2 + * + * @return 技威Code2 + */ + public String getP2pverifyCode2() { + return this.p2pverifyCode2; + } + + /** + * 设置技威Code2 + * + * @param p2pverifyCode2 技威Code2 + */ + public void setP2pverifyCode2(String p2pverifyCode2) { + this.p2pverifyCode2 = p2pverifyCode2; + } + + /** + * 获取技威用户ID + * + * @return 技威用户ID + */ + public String getGwellUserid() { + return this.gwellUserid; + } + + /** + * 设置技威用户ID + * + * @param gwellUserid 技威用户ID + */ + public void setGwellUserid(String gwellUserid) { + this.gwellUserid = gwellUserid; + } + + /** + * 获取是否注册技威:1已注册、0未注册 + * + * @return 是否注册技威 + */ + public String getIsRegisterGwell() { + return this.isRegisterGwell; + } + + /** + * 设置是否注册技威:1已注册、0未注册 + * + * @param isRegisterGwell 是否注册技威:1已注册、0未注册 + */ + public void setIsRegisterGwell(String isRegisterGwell) { + this.isRegisterGwell = isRegisterGwell; + } + + /** + * 获取极光用户ID + * + * @return 极光用户ID + */ + public String getJiguangUserid() { + return this.jiguangUserid; + } + + /** + * 设置极光用户ID + * + * @param jiguangUserid 极光用户ID + */ + public void setJiguangUserid(String jiguangUserid) { + this.jiguangUserid = jiguangUserid; + } + + /** + * 获取经度 + * + * @return 经度 + */ + public Double getLongitude() { + return this.longitude; + } + + /** + * 设置经度 + * + * @param longitude 经度 + */ + public void setLongitude(Double longitude) { + this.longitude = longitude; + } + + /** + * 获取纬度 + * + * @return 纬度 + */ + public Double getLatitude() { + return this.latitude; + } + + /** + * 设置纬度 + * + * @param latitude 纬度 + */ + public void setLatitude(Double latitude) { + this.latitude = latitude; + } +} diff --git a/src/main/java/com/ifish/bean/Tbl_Vender.java b/src/main/java/com/ifish/bean/Tbl_Vender.java new file mode 100644 index 0000000..da691c8 --- /dev/null +++ b/src/main/java/com/ifish/bean/Tbl_Vender.java @@ -0,0 +1,270 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.bean; + +import java.util.Date; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * 鱼缸场详情表(tbl_vender_list) + * + * @author bianj + * @version 1.0.0 2017-06-27 + */ +@Entity +@Table(name = "tbl_vender_list") +public class Tbl_Vender implements java.io.Serializable { + + /** + * 版本号 + */ + private static final long serialVersionUID = -487543106603936914L; + + /** + * 鱼缸厂编号 + */ + @Id + @Column(name = "brand_code", unique = true, nullable = false, length = 20) + private String brandCode; + + /** + * 电子厂代码 + */ + @Id + @Column(name = "factory_code", unique = true, nullable = false, length = 20) + private String factoryCode; + + /** + * logo + */ + @Column(name = "brand_logo", nullable = true, length = 100) + private String brandLogo; + + /** + * 鱼缸厂名称 + */ + @Column(name = "brand_name", nullable = false, length = 20) + private String brandName; + + /** + * 品牌介绍 + */ + @Column(name = "brand_introduce", nullable = true, length = 100) + private String brandIntroduce; + + /** + * app展示 + */ + @Column(name = "app_show", nullable = true, length = 1) + private String appShow; + + /** + * 联系电话 + */ + @Column(name = "contact_phone", nullable = true, length = 30) + private String contactPhone; + + /** + * 联系地址 + */ + @Column(name = "contact_address", nullable = true, length = 50) + private String contactAddress; + + /** + * 更新时间 + */ + @Column(name = "update_time", nullable = true) + private Date updateTime; + + /** + * 创建时间 + */ + @Column(name = "create_time", nullable = true) + private Date createTime; + + /** + * 获取鱼缸厂编号 + * + * @return 鱼缸厂编号 + */ + public String getBrandCode() { + return this.brandCode; + } + + /** + * 设置鱼缸厂编号 + * + * @param brandCode 鱼缸厂编号 + */ + public void setBrandCode(String brandCode) { + this.brandCode = brandCode; + } + + /** + * 获取电子厂代码 + * + * @return 电子厂代码 + */ + public String getFactoryCode() { + return this.factoryCode; + } + + /** + * 设置电子厂代码 + * + * @param factoryCode 电子厂代码 + */ + public void setFactoryCode(String factoryCode) { + this.factoryCode = factoryCode; + } + + /** + * 获取logo + * + * @return logo + */ + public String getBrandLogo() { + return this.brandLogo; + } + + /** + * 设置logo + * + * @param brandLogo logo + */ + public void setBrandLogo(String brandLogo) { + this.brandLogo = brandLogo; + } + + /** + * 获取鱼缸厂名称 + * + * @return 鱼缸厂名称 + */ + public String getBrandName() { + return this.brandName; + } + + /** + * 设置鱼缸厂名称 + * + * @param brandName 鱼缸厂名称 + */ + public void setBrandName(String brandName) { + this.brandName = brandName; + } + + /** + * 获取品牌介绍 + * + * @return 品牌介绍 + */ + public String getBrandIntroduce() { + return this.brandIntroduce; + } + + /** + * 设置品牌介绍 + * + * @param brandIntroduce 品牌介绍 + */ + public void setBrandIntroduce(String brandIntroduce) { + this.brandIntroduce = brandIntroduce; + } + + /** + * 获取app展示 + * + * @return app展示 + */ + public String getAppShow() { + return this.appShow; + } + + /** + * 设置app展示 + * + * @param appShow app展示 + */ + public void setAppShow(String appShow) { + this.appShow = appShow; + } + + /** + * 获取联系电话 + * + * @return 联系电话 + */ + public String getContactPhone() { + return this.contactPhone; + } + + /** + * 设置联系电话 + * + * @param contactPhone 联系电话 + */ + public void setContactPhone(String contactPhone) { + this.contactPhone = contactPhone; + } + + /** + * 获取联系地址 + * + * @return 联系地址 + */ + public String getContactAddress() { + return this.contactAddress; + } + + /** + * 设置联系地址 + * + * @param contactAddress 联系地址 + */ + public void setContactAddress(String contactAddress) { + this.contactAddress = contactAddress; + } + + /** + * 获取更新时间 + * + * @return 更新时间 + */ + public Date getUpdateTime() { + return this.updateTime; + } + + /** + * 设置更新时间 + * + * @param updateTime 更新时间 + */ + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + + /** + * 获取创建时间 + * + * @return 创建时间 + */ + public Date getCreateTime() { + return this.createTime; + } + + /** + * 设置创建时间 + * + * @param createTime 创建时间 + */ + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } +} diff --git a/src/main/java/com/ifish/config/MybatisConfig.java b/src/main/java/com/ifish/config/MybatisConfig.java new file mode 100644 index 0000000..235479f --- /dev/null +++ b/src/main/java/com/ifish/config/MybatisConfig.java @@ -0,0 +1,86 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.config; + +import javax.sql.DataSource; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.mybatis.spring.mapper.MapperScannerConfigurer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +/** + * + * @author Administrator + */ +@Configuration +@EnableTransactionManagement +public class MybatisConfig { + + @Bean + public DataSource dataSource() { +// try { +// ComboPooledDataSource datasourc = new ComboPooledDataSource(); +// datasourc.setDriverClass(JdbcProperties.driverClassName); +// datasourc.setJdbcUrl(JdbcProperties.url); +// datasourc.setUser(JdbcProperties.username); +// datasourc.setPassword(JdbcProperties.password); +// datasourc.setAutoCommitOnClose(JdbcProperties.autoCommitOnClose); +// datasourc.setInitialPoolSize(JdbcProperties.initialPoolSize); +// datasourc.setMinPoolSize(JdbcProperties.minPoolSize); +// datasourc.setMaxPoolSize(JdbcProperties.maxPoolSize); +// datasourc.setAcquireIncrement(JdbcProperties.acquireIncrement); +// datasourc.setCheckoutTimeout(JdbcProperties.checkoutTimeout); +// datasourc.setMaxIdleTime(JdbcProperties.maxIdleTime); +// datasourc.setIdleConnectionTestPeriod(JdbcProperties.idleConnectionTestPeriod); +// return datasourc; +// } catch (Exception e) { +// +// } + DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName("com.mysql.jdbc.Driver"); + //线上生产数据库连接 + dataSource.setUsername("ifish"); + dataSource.setPassword("ifish7pwd"); + dataSource.setUrl("jdbc:mysql://localhost:3306/myfishdbenglish?characterEncoding=UTF-8"); + return dataSource; + } + + @Bean(name = "sqlSessionFactory") + public SqlSessionFactoryBean sqlSessionFactory() { + SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean(); + ssfb.setDataSource(dataSource()); + ssfb.setTypeAliasesPackage("com.ifish.bean"); + try { + org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration(); + configuration.setMapUnderscoreToCamelCase(true); + ssfb.setConfiguration(configuration); + + } catch (Exception e) { + } + + return ssfb; + } + + @Bean + public MapperScannerConfigurer mpperScannnerConfigurer() { + MapperScannerConfigurer msc = new MapperScannerConfigurer(); + msc.setSqlSessionFactoryBeanName("sqlSessionFactory"); + msc.setBasePackage("com.ifish.mapper"); + return msc; + } + + @Bean + PlatformTransactionManager transactionManager() { + DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(); + transactionManager.setDataSource(dataSource()); + return transactionManager; + } + +} diff --git a/src/main/java/com/ifish/config/RedisConfig.java b/src/main/java/com/ifish/config/RedisConfig.java new file mode 100644 index 0000000..1d37213 --- /dev/null +++ b/src/main/java/com/ifish/config/RedisConfig.java @@ -0,0 +1,58 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.config; + +import com.ifish.util.IfishFilePath; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; + +/** + * + * @author Administrator + */ +@Configuration +public class RedisConfig { + + @Bean + public RedisConnectionFactory redisCF() { + JedisConnectionFactory cf = new JedisConnectionFactory(); + +// //获取当前操作系统(servers_os为服务器设置的属性JAVA_OPTS=%JAVA_OPTS% -Dservers_os=online84) +// String servers_os = System.getProperty("servers_os") == null ? "" : System.getProperty("servers_os"); + if (IfishFilePath.link_img_head.contains("ifish7")) { + //站点线上服务器 + cf.setHostName("120.55.190.56"); + cf.setPort(3796); + cf.setPassword("ifish7myredis"); + } else { + //站点测试服务器 + cf.setHostName("139.196.24.156"); + cf.setPort(3796); + cf.setPassword("ifish7myredis"); +// FileUtil.writeLinesByLog("测试缓存连接"); + } + + return cf; + } + + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory cf) { + RedisTemplate redis = new RedisTemplate(); + redis.setConnectionFactory(cf); + return redis; + } + + @Bean + public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory cf) { + StringRedisTemplate redis = new StringRedisTemplate(); + redis.setConnectionFactory(cf); + return redis; + } +} diff --git a/src/main/java/com/ifish/config/RootConfig.java b/src/main/java/com/ifish/config/RootConfig.java new file mode 100644 index 0000000..f2aaaa3 --- /dev/null +++ b/src/main/java/com/ifish/config/RootConfig.java @@ -0,0 +1,26 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.config; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.ComponentScan.Filter; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; +import org.springframework.context.annotation.Import; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; + +/** + * + * @author Administrator + */ +@Configuration +//@Import(MybatisConfig.class) //导入数据库文件配置 +@ComponentScan(basePackages = {"com.ifish.*"}, + excludeFilters = { + @Filter(type = FilterType.ANNOTATION, value = EnableWebMvc.class)}) +public class RootConfig { + +} diff --git a/src/main/java/com/ifish/config/WebAppInitializer.java b/src/main/java/com/ifish/config/WebAppInitializer.java new file mode 100644 index 0000000..c963f53 --- /dev/null +++ b/src/main/java/com/ifish/config/WebAppInitializer.java @@ -0,0 +1,46 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.config; + +import javax.servlet.Filter; +import org.springframework.context.annotation.Bean; +import org.springframework.web.filter.CharacterEncodingFilter; +import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; + +/** + * + * @author Administrator + */ +public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { + + @Override + protected Class[] getRootConfigClasses() { + return new Class[]{RootConfig.class, MybatisConfig.class}; + } + + @Override + protected Class[] getServletConfigClasses() { + return new Class[]{WebConfig.class}; + } + + @Override + protected String[] getServletMappings() { + return new String[]{"/api/*"}; + } + + @Override + protected Filter[] getServletFilters() { + return null; + } + + @Bean + public Filter characterEncodingFilter() { + CharacterEncodingFilter filter = new CharacterEncodingFilter(); + filter.setEncoding("UTF-8"); + filter.setForceEncoding(true); + return filter; + } +} diff --git a/src/main/java/com/ifish/config/WebConfig.java b/src/main/java/com/ifish/config/WebConfig.java new file mode 100644 index 0000000..0062765 --- /dev/null +++ b/src/main/java/com/ifish/config/WebConfig.java @@ -0,0 +1,71 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.config; + +import com.ifish.Interceptor.SecurityValidateInterceptor; +import com.ifish.util.IfishFilePath; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.view.InternalResourceViewResolver; + +/** + * + * @author Administrator + */ +@Configuration +/** + * 启动SpringMVC + */ +@EnableWebMvc +/** + * 启动组件扫描器,com.mymvc.controller是包 + */ +@ComponentScan("com.ifish.controller") +public class WebConfig extends WebMvcConfigurerAdapter { + + /** + * 配置视图解析器 + * + * @return + */ + @Bean + public ViewResolver viewResolver() { + InternalResourceViewResolver resolver = new InternalResourceViewResolver(); + resolver.setPrefix("/WEB-INF/views/"); + resolver.setSuffix(".jsp"); + resolver.setExposeContextBeansAsAttributes(true); + return resolver; + } + + /** + * 配置静态资源的处理 + * + * @param configurer + */ + @Override + public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { + configurer.enable();; + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(MyInterceptor()); + super.addInterceptors(registry); + } + + @Bean + public SecurityValidateInterceptor MyInterceptor() { + boolean devModel = IfishFilePath.devModel; + return new SecurityValidateInterceptor(devModel); + } + +} diff --git a/src/main/java/com/ifish/controller/Device.java b/src/main/java/com/ifish/controller/Device.java new file mode 100644 index 0000000..7028c28 --- /dev/null +++ b/src/main/java/com/ifish/controller/Device.java @@ -0,0 +1,142 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.controller; + +import com.ifish.bean.Tbl_Device; +import com.ifish.bean.Tbl_Device_User; +import com.ifish.bean.Tbl_User; +import com.ifish.enums.ResultEnum; +import com.ifish.helper.DeviceHelperI; +import com.ifish.util.IfishUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +/** + * + * @author Administrator + */ +@RestController +public class Device { + + @Autowired + private DeviceHelperI deviceHelperI; + + /** + * 绑定设备 + * + * @param userId + * @param macAddress + * @return + */ + @RequestMapping(value = "/bindDevice.do", method = RequestMethod.POST) + public Object bindDevice(Integer userId, String macAddress) { + try { + return deviceHelperI.bindDevice(userId, macAddress); + } catch (Exception e) { + + } + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + + /** + * 绑定摄像头 + * + * @param userId + * @param cameraId + * @return + */ + @RequestMapping(value = "/bindCamera.do", method = RequestMethod.POST) + public Object bindCamera(Integer userId, String cameraId) { + try { + return deviceHelperI.bindCamera(userId, cameraId); + } catch (Exception e) { + + } + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + + /** + * 激活摄像头 + * + * @param activeCode + * @param cameraId + * @return + */ + @RequestMapping(value = "/activeCamera.do", method = RequestMethod.POST) + public Object activeCamera(String activeCode, String cameraId) { + try { + return deviceHelperI.activeCamera(activeCode, cameraId); + } catch (Exception e) { + } + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + + /** + * 修改设备显示名称 + * + * @param device + * @param userId + * @return + */ + @RequestMapping(value = "/updateDeviceUser.do", method = RequestMethod.POST) + public Object updateDeviceUser(Tbl_Device_User device) { + try { + return deviceHelperI.updateDeviceUser(device); + } catch (Exception e) { + } + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + + /** + * 修改摄像头信息 + * + * @param cameraId + * @param device_User + * @return + */ + @RequestMapping(value = "/updateCameraUser.do", method = RequestMethod.POST) + public Object updateCameraUser(Integer cameraId, Tbl_Device_User device_User) { + try { + return deviceHelperI.updateCameraUser(cameraId, device_User); + } catch (Exception e) { + } + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + + /** + * 删除绑定的设备 + * + * @param deviceUser + * @return + */ + @RequestMapping(value = "/deleteDeviceUser.do", method = RequestMethod.POST) + public Object deleteDeviceUser(Tbl_Device_User deviceUser) { + try { + return deviceHelperI.deleteDeviceUser(deviceUser); + } catch (Exception e) { + + } + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + + /** + * 删除绑定的摄像头 + * + * @param deviceUser + * @return + */ + @RequestMapping(value = "/deleteCameraUser.do", method = RequestMethod.POST) + public Object deleteCameraUser(Integer userId, String cameraId) { + try { + return deviceHelperI.deleteCameraUser(userId, cameraId); + } catch (Exception e) { + + } + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } +} diff --git a/src/main/java/com/ifish/controller/Index.java b/src/main/java/com/ifish/controller/Index.java new file mode 100644 index 0000000..591d78c --- /dev/null +++ b/src/main/java/com/ifish/controller/Index.java @@ -0,0 +1,23 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +/** + * + * @author Administrator + */ +@Controller +public class Index { + + @RequestMapping(value = "/", method = RequestMethod.GET) //处理路由的请求 + public String index() { + return "index"; //返回的视图名为index(指向/WEB-INF/Views/index.jsp) + } +} diff --git a/src/main/java/com/ifish/controller/LiveRoom.java b/src/main/java/com/ifish/controller/LiveRoom.java new file mode 100644 index 0000000..3860fd5 --- /dev/null +++ b/src/main/java/com/ifish/controller/LiveRoom.java @@ -0,0 +1,107 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.controller; + +import com.ifish.bean.Tbl_Live_Message; +import com.ifish.bean.Tbl_Live_Room; +import com.ifish.enums.ResultEnum; +import com.ifish.helper.LiveRoomHelperI; +import com.ifish.util.IfishUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +/** + * + * @author Administrator + */ +@RestController +public class LiveRoom { + + @Autowired + private LiveRoomHelperI liveRoomHelperI; + + /** + * 新增直播间 + * + * @param liveRoom + * @param fileUpload + * @return + */ + @RequestMapping(value = "/liveRoom/v3/addLiveRoom.do", method = RequestMethod.POST) + public Object addLiveRoom(MultipartFile fileUpload, Tbl_Live_Room liveRoom) { + try { + return liveRoomHelperI.addLiveRoom(fileUpload, liveRoom); + } catch (Exception e) { + } + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + + /** + * 直播间点赞 + * + * @param roomId + * @param userId + * @return + */ + @RequestMapping(value = "/liveRoomZan/{roomId}/{userId}", method = RequestMethod.POST) + public Object liveRoomsZan(@PathVariable Integer roomId, @PathVariable Integer userId) { + try { + return liveRoomHelperI.liveRoomsZan(roomId, userId); + } catch (Exception e) { + } + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + + /** + * 直播间留言 + * + * @param liveMessage + * @return + */ + @RequestMapping(value = "/liveRoom/v3/leaveMessage.do", method = RequestMethod.POST) + public Object leaveMessage(Tbl_Live_Message liveMessage) { + try { + return liveRoomHelperI.leaveMessage(liveMessage); + } catch (Exception e) { + } + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + + /** + * 获取直播间信息 + * + * @param roomId + * @return + */ + @RequestMapping(value = "/liveRoom/v3/getLiveRoomInfo.do", method = RequestMethod.GET) + public Object getLiveRoomInfo(Integer userId) { + try { + return liveRoomHelperI.getLiveRoomInfo(userId); + } catch (Exception e) { + } + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + + /** + * 获取直播列表 + * + * @param firstResult + * @param pageSize + * @return + */ + @RequestMapping(value = "/liveRoom/v3/getLiveRooms.do", method = RequestMethod.GET) + public Object getLiveRooms(Integer firstResult, Integer pageSize, Integer userId, String orders) { + try { + return liveRoomHelperI.getLiveRooms(firstResult, pageSize, userId, orders); + } catch (Exception e) { + } + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } +} diff --git a/src/main/java/com/ifish/controller/Login.java b/src/main/java/com/ifish/controller/Login.java new file mode 100644 index 0000000..37ad256 --- /dev/null +++ b/src/main/java/com/ifish/controller/Login.java @@ -0,0 +1,46 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.controller; + +import com.ifish.bean.Tbl_User; +import com.ifish.helper.UserHelperI; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMethod; + +/** + * + * @author Administrator + */ +@RestController +public class Login { + + @Autowired + private UserHelperI userHelperI; + + /** + * 用户登陆 + * + * @param user + * @return + */ + @RequestMapping(value = "/userLogin.do", method = RequestMethod.GET) + public Object userLogin(Tbl_User user) { + return userHelperI.login(user); + } + + /** + * 游客注册 + * + * @return + */ + @RequestMapping(value = "/touristLogin.do", method = RequestMethod.POST) + public Object touristLogin() { + return userHelperI.touristRegister(); + } + +} diff --git a/src/main/java/com/ifish/controller/PushMessage.java b/src/main/java/com/ifish/controller/PushMessage.java new file mode 100644 index 0000000..022d1f4 --- /dev/null +++ b/src/main/java/com/ifish/controller/PushMessage.java @@ -0,0 +1,65 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.controller; + +import com.ifish.bean.PageResult; +import com.ifish.bean.Tbl_Push_List; +import com.ifish.enums.ResultEnum; +import com.ifish.helper.PushMessageHelperI; +import com.ifish.util.IfishUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +/** + * + * @author Administrator + */ +@RestController +@RequestMapping("/push") +public class PushMessage { + + @Autowired + private PushMessageHelperI pushMessageHelperI; + + /** + * 获取推送消息列表 + * + * @param pushId + * @param userId + * @param firstResult + * @param pageSize + * @return + */ + @RequestMapping(value = "/getPushList", method = RequestMethod.GET) + public Object pushListInf(String pushType, Integer userId, Integer firstResult, Integer pageSize) { + + try { + return pushMessageHelperI.getPushList(pushType, userId, firstResult, pageSize); + } catch (Exception e) { + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + } + + /** + * 删除推送消息 + * + * @param userId + * @param pushId + * @return + */ + @RequestMapping(value = "/deletePushList", method = RequestMethod.GET) + public Object deletePushList(Integer userId, Integer pushId) { + + try { + return pushMessageHelperI.deletePushList(userId, pushId); + } catch (Exception e) { + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + } + +} diff --git a/src/main/java/com/ifish/enums/GwellEnum.java b/src/main/java/com/ifish/enums/GwellEnum.java new file mode 100644 index 0000000..ed918b3 --- /dev/null +++ b/src/main/java/com/ifish/enums/GwellEnum.java @@ -0,0 +1,41 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.enums; + +/** + * + * @author Administrator + */ +public enum GwellEnum { + + success("0", "注册成功"),//注册成功 + fail("1", "注册失败"),//注册失败 + repeat("7", "邮箱已被注册");//邮箱已被注册 + + private GwellEnum(String key, String value) { + this.key = key; + this.value = value; + } + + private String key; + private String value; + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/src/main/java/com/ifish/enums/PushTypeEnum.java b/src/main/java/com/ifish/enums/PushTypeEnum.java new file mode 100644 index 0000000..5e209a9 --- /dev/null +++ b/src/main/java/com/ifish/enums/PushTypeEnum.java @@ -0,0 +1,58 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.enums; + +/** + * 推送消息类型 + * + * @author Administrator + */ +public enum PushTypeEnum { + remove_device("remove_device", "解绑通知"), + wendu_warn("wendu_warn", "温度预警"), + qu_reply("qu_reply", "问题反馈"), + app_update("app_update", "IOS更新推送"), + remind_water("remind_water", "换水提醒"), + offline_push("offline_push", "离线通知"), + send_report("send_report", "看护报告"), + shops_push("shops_push", "看护通知"), + all_push("all_push", "所有用户推送"); + + private PushTypeEnum(String key, String value) { + this.key = key; + this.value = value; + } + + private String key; + private String value; + + //普通方法 + public static String getValue(String key) { + for (PushTypeEnum c : PushTypeEnum.values()) { + if (c.getKey().equals(key)) { + return c.getValue(); + } + } + return null; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + +} diff --git a/src/main/java/com/ifish/enums/ResultEnum.java b/src/main/java/com/ifish/enums/ResultEnum.java new file mode 100644 index 0000000..853dad8 --- /dev/null +++ b/src/main/java/com/ifish/enums/ResultEnum.java @@ -0,0 +1,66 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.enums; + +/** + * + * @author Administrator + */ +public enum ResultEnum { + success("100", "成功"), + fail101("101", "失败"), + warn201("201", "手机已经注册过"), + warn202("202", "手机未注册"), + warn203("203", "未知操作"),//获取验证码时 + warn204("204", "密码不正确"), + warn205("205", "图片格式不正确"), + warn206("206", "上传图片太大"), + warn207("207", "设备不存在"), + warn208("208", "激活码已被使用"), + warn209("209", "无效的激活码"), + warn210("210", "摄像头不存在"), + warn211("211", "用户ID不存在"), + warn212("212", "请填写正确的商家手机号"), + warn213("213", "包含敏感词"), + warn214("214", "直播间已存在"), + warn215("215", "金币不足"), + warn216("216", "金币规则不存在"), + warn217("217", "打赏金额错误"), + warn218("218", "没有商家"), + warn219("219", "优惠券已停止兑换"), + warn220("220", "用户能兑换数量达到上限"), + warn221("221", "优惠券已全部兑换完"), + warn222("222", "请上传正确的商品介绍图"), + warn223("223", "请上传正确的商品介绍视频"), + error400("400", "安全校验失败"), + error401("401", "参数校验失败"), + error402("402", "参数不存在"); + + private ResultEnum(String key, String value) { + this.key = key; + this.value = value; + } + + private String key; + private String value; + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + +} diff --git a/src/main/java/com/ifish/enums/SubDirectoryEnum.java b/src/main/java/com/ifish/enums/SubDirectoryEnum.java new file mode 100644 index 0000000..2715c25 --- /dev/null +++ b/src/main/java/com/ifish/enums/SubDirectoryEnum.java @@ -0,0 +1,45 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.enums; + +/** + * + * @author Administrator + */ +public enum SubDirectoryEnum { + headImage("app/", "头像"), + banner("banner/", "banner图"), + look("look/", "看护报告"), + ueditorHtml("ueditorHtml/", "后台生成的网页"), + adInfo("Img/adInfo/", "广告图片"), + information("Img/information/", "资讯图片"), + ifishGoods("Img/goods/", "商品图片"), + ifishCommodity("Img/commodity/", "商家商品介绍图"); + + private SubDirectoryEnum(String key, String value) { + this.key = key; + this.value = value; + } + + private String key; + private String value; + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/src/main/java/com/ifish/helper/DeviceHelper.java b/src/main/java/com/ifish/helper/DeviceHelper.java new file mode 100644 index 0000000..17181d1 --- /dev/null +++ b/src/main/java/com/ifish/helper/DeviceHelper.java @@ -0,0 +1,592 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.helper; + +import com.ifish.bean.Tbl_Activa_Code; +import com.ifish.bean.Tbl_Device; +import com.ifish.bean.Tbl_Device_Statistics; +import com.ifish.bean.Tbl_Device_User; +import com.ifish.bean.Tbl_User; +import com.ifish.enums.PushTypeEnum; +import com.ifish.enums.ResultEnum; +import com.ifish.mapper.Tbl_Device_Mapper; +import com.ifish.util.IfishUtil; +import com.ifish.util.RedisKey; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * + * @author Administrator + */ +@Component +public class DeviceHelper implements DeviceHelperI { + + @Autowired + private RedisHelperI redisHelperI; + + @Autowired + private Tbl_Device_Mapper tbl_Device_Mapper; + + @Autowired + private UserHelperI userHelperI; + + /** + * 根据用户Id获取绑定设备集合 + * + * @param userId + * @return + */ + @Override + public List getDeviceUsersByUserId(Integer userId) throws Exception { + List deviceUserList = null; + String key = RedisKey.DeviceUser_Key + userId; + String redisString = redisHelperI.getRedis(key); + if (StringUtils.isNotBlank(redisString)) { + deviceUserList = (List) IfishUtil.JsonToList(redisString, Tbl_Device_User.class); + } else { + deviceUserList = tbl_Device_Mapper.getDeviceUsersByUserId(userId); + if (deviceUserList != null && deviceUserList.size() > 0) { + redisHelperI.setRedis(key, IfishUtil.ObjectToJson(deviceUserList)); + } + } + return deviceUserList; + } + + /** + * 根据用户ID和设备ID获取此设备和此用户的关系 + * + * @param userId + * @param deviceId + * @return + * @throws Exception + */ + public Tbl_Device_User getDeviceUserByUserId_DeviceId(Integer userId, Integer deviceId) throws Exception { + Tbl_Device_User device = null; + String key = RedisKey.DeviceUser_Key + "d" + deviceId + "_u" + userId; + String redisString = redisHelperI.getRedis(key); + if (StringUtils.isNotBlank(redisString)) { + device = (Tbl_Device_User) IfishUtil.JsonToBean(redisString, Tbl_Device_User.class); + } else { + device = tbl_Device_Mapper.getDeviceUsersByUserIdAndDeviceId(userId, deviceId); + if (device != null && device.getDeviceId() > 0) { + redisHelperI.setRedis(key, IfishUtil.ObjectToJson(device)); + } + } + return device; + } + + /** + * 根据用户ID和摄像头ID获取此摄像头和用户的关系 + * + * @param userId + * @param deviceId + * @return + * @throws Exception + */ + @Override + public Tbl_Device_User getDeviceUserByUserId_CameraId(Integer userId, String cameraId) throws Exception { + Tbl_Device device = getDeviceByCameraId(cameraId); + if (device == null) { + return null; + } + return getDeviceUserByUserId_DeviceId(userId, device.getDeviceId()); + } + + /** + * 根据设备Id获取设备详情 + * + * @param deviceId + * @return + * @throws Exception + */ + @Override + public Tbl_Device getDeviceById(Integer deviceId) throws Exception { + Tbl_Device device = null; + String key = RedisKey.Device_key + deviceId; + String redisString = redisHelperI.getRedis(key); + if (StringUtils.isNotBlank(redisString)) { + device = (Tbl_Device) IfishUtil.JsonToBean(redisString, Tbl_Device.class); + } else { + device = tbl_Device_Mapper.getDeviceById(deviceId); + if (device != null && device.getDeviceId() > 0) { + redisHelperI.setRedis(key, IfishUtil.ObjectToJson(device)); + } + } + return device; + } + + /** + * 根据摄像头ID从缓存中取得设备信息 + * + * @param cameraId + * @return + * @throws Exception + */ + @Override + public Tbl_Device getDeviceByCameraId(String cameraId) throws Exception { + Tbl_Device device = null; + String key = RedisKey.Camera_key + cameraId; + String redisString = redisHelperI.getRedis(key); + if (StringUtils.isNotBlank(redisString)) { + device = (Tbl_Device) IfishUtil.JsonToBean(redisString, Tbl_Device.class); + } else { + device = tbl_Device_Mapper.getDeviceByCameraId(cameraId); + if (device != null && device.getDeviceId() > 0) { + redisHelperI.setRedis(key, IfishUtil.ObjectToJson(device)); + } + } + return device; + } + + /** + * 根据设备mac地址获取设备详情 + * + * @param macAddress + * @return + * @throws Exception + */ + @Override + public Tbl_Device getDeviceByMacAddress(String macAddress) throws Exception { + Tbl_Device device = null; + String key = RedisKey.Device_key + macAddress; + String redisString = redisHelperI.getRedis(key); + if (StringUtils.isNotBlank(redisString)) { + device = (Tbl_Device) IfishUtil.JsonToBean(redisString, Tbl_Device.class); + } else { + device = tbl_Device_Mapper.getDeviceByMacAddress(macAddress); + if (device != null && device.getDeviceId() > 0) { + redisHelperI.setRedis(key, IfishUtil.ObjectToJson(device)); + } + } + return device; + } + + /** + * 根据设备ID获取设备统计信息 + * + * @param deviceId + * @return + * @throws Exception + */ + public Tbl_Device_Statistics getDeviceStatisticsByDeviceId(Integer deviceId) throws Exception { + Tbl_Device_Statistics device = null; + String key = RedisKey.DeviceStatistic_key + deviceId; + String redisString = redisHelperI.getRedis(key); + if (StringUtils.isNotBlank(redisString)) { + device = (Tbl_Device_Statistics) IfishUtil.JsonToBean(redisString, Tbl_Device_Statistics.class); + } else { + device = tbl_Device_Mapper.getDevStatisticsByDeviceId(deviceId); + if (device != null && device.getDeviceId() > 0) { + redisHelperI.setRedis(key, IfishUtil.ObjectToJson(device)); + } + } + return device; + } + + /** + * 绑定设备 + * + * @param userId + * @param user + * @param mackAddress + * @return + */ + @Override + public Object bindDevice(Integer userId, String mackAddress) { + + try { + Tbl_User tmpUser = userHelperI.getUserById(userId); + //用户存在 + if (tmpUser != null) { + //新增用户拥有设备 + Tbl_Device_User deviceUser = new Tbl_Device_User(); + Tbl_Device device = getDeviceByMacAddress(mackAddress); + boolean bln = false; + //设备存在 + if (device != null) { + //关联用户-设备 + deviceUser.setUserId(tmpUser.getUserId()); + deviceUser.setDeviceId(device.getDeviceId()); + //已关联设备的其他用户,这里的用户ID查询条件是不等于<> + List deviceUserList = tbl_Device_Mapper.getOtherDeviceUsersByOtherUserIdAndDeviceId(tmpUser.getUserId(), device.getDeviceId()); + //是否已关联这里的用户ID查询是等于= + Tbl_Device_User tmpDdeviceUser = tbl_Device_Mapper.getDeviceUsersByUserIdAndDeviceId(tmpUser.getUserId(), device.getDeviceId()); + //已关联 + if (tmpDdeviceUser != null) { + //原先不是主控制,则删除其他用户关联关系 + if (!tmpDdeviceUser.getIsMaster().equals("1")) { + + for (Tbl_Device_User du : deviceUserList) { + Integer userid = du.getUserId(); + Integer deviceId = du.getDeviceId(); + Tbl_User tu = userHelperI.getUserById(userid); + if (tu != null) { + String timestamp = IfishUtil.format(new Date()); + //基本参数 + Map baseMap = new HashMap(); + baseMap.put("title", PushTypeEnum.remove_device.getValue()); + baseMap.put("content", "你已于" + timestamp + "失去对“" + du.getShowName() + "”设备的控制权"); + baseMap.put("user_id", tu.getUserId().toString()); + baseMap.put("loginType", tu.getLoginType()); + //推送参数 + Map pushMap = new HashMap(); + pushMap.put("device_id", deviceId.toString()); + pushMap.put("device_name", du.getShowName()); + pushMap.put("timestamp", timestamp); + pushMap.put("msg_type", PushTypeEnum.remove_device.getKey()); + //推送消息 + jPushNotifcation(baseMap, pushMap); + } + tbl_Device_Mapper.deleteDeviceUserById(du.getId()); + + } + } + //变更为主控 + tmpDdeviceUser.setIsMaster("1"); + Date date = new Date(); + tmpDdeviceUser.setUpdateTime(date); + tmpDdeviceUser.setCreateTime(date); + tbl_Device_Mapper.updateTblDeviceUser(tmpDdeviceUser); + + deviceUser.setShowName(tmpDdeviceUser.getShowName()); + deviceUser.setIsMaster(tmpDdeviceUser.getIsMaster()); + } //未绑定过 + else { + //删除其他用户控制权 + for (Tbl_Device_User du : deviceUserList) { + Integer userid = du.getUserId(); + Integer deviceId = du.getDeviceId(); + Tbl_User tu = userHelperI.getUserById(userid); + if (tu != null) { + String timestamp = IfishUtil.format(new Date()); + //基本参数 + Map baseMap = new HashMap(); + baseMap.put("title", PushTypeEnum.remove_device.getValue()); + baseMap.put("content", "你已于" + timestamp + "失去对“" + du.getShowName() + "”设备的控制权"); + baseMap.put("user_id", tu.getUserId().toString()); + baseMap.put("loginType", tu.getLoginType()); + //推送参数 + Map pushMap = new HashMap(); + pushMap.put("device_id", deviceId.toString()); + pushMap.put("device_name", du.getShowName()); + pushMap.put("timestamp", timestamp); + pushMap.put("msg_type", PushTypeEnum.remove_device.getKey()); + //推送消息 + jPushNotifcation(baseMap, pushMap); + } + tbl_Device_Mapper.deleteDeviceUserById(du.getId()); + } + //需要新增 + bln = true; + //查询设备统计信息 + Tbl_Device_Statistics ds = getDeviceStatisticsByDeviceId(device.getDeviceId()); + //如果设备统计信息为空,新增 + if (ds == null || ds.getId() <= 0) { + ds = new Tbl_Device_Statistics(); + ds.setDeviceId(device.getDeviceId()); + ds.setMacAddress(StringUtils.isBlank(device.getMacAddress()) ? null : device.getMacAddress()); + ds.setLoginCount(1); + ds.setLoginTime(new Date()); + ds.setFirstActivate(new Date()); + ds.setCreateTime(new Date()); + ds.setIsCharge("0"); + ds.setHardwareType(StringUtils.isBlank(device.getHardwareType()) ? null : device.getHardwareType()); + ds.setFactoryCode(StringUtils.isBlank(device.getFactoryCode()) ? null : device.getFactoryCode()); + ds.setBrandCode(StringUtils.isBlank(device.getBrandCode()) ? null : device.getBrandCode()); + tbl_Device_Mapper.insertDeviceStatistics(ds); + } else { + //修改设备统计信息 + ds.setFirstActivate(new Date()); + tbl_Device_Mapper.updateDeviceStatistics(ds); + } + } + } //设备不存在 + else { + //新增设备信息 + device = new Tbl_Device(); + device.setIsBlacklist("1"); + device.setMacAddress(mackAddress); + Date date = new Date(); + device.setCreateTime(date); + int i = tbl_Device_Mapper.insertDevice(device); + if (i > 0) { + Tbl_Device_Statistics tds = new Tbl_Device_Statistics(); + tds.setLoginCount(0); + tds.setMacAddress(mackAddress); + tds.setDeviceId(device.getDeviceId()); + tds.setFirstActivate(date); + tds.setCreateDate(date); + tds.setCreateTime(date); + tbl_Device_Mapper.insertDeviceStatistics(tds); + bln = true; + deviceUser.setUserId(tmpUser.getUserId()); + deviceUser.setDeviceId(device.getDeviceId()); + } + } + //需要新增 + if (bln) { + //新增关联关系 + deviceUser.setShowName("鱼缸" + (int) (Math.random() * 9000 + 1000)); + deviceUser.setIsMaster("1"); + Date date = new Date(); + deviceUser.setUpdateTime(date); + deviceUser.setCreateTime(date); + tbl_Device_Mapper.insertDeviceUser(deviceUser); + } + //封装设备返回信息 + return IfishUtil.returnJson(ResultEnum.success.getKey(), userHelperI.getDeviceInfo(device, deviceUser)); + } else { + return IfishUtil.returnJson(ResultEnum.warn202.getKey(), ""); + } + } catch (Exception e) { + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + } + + /** + * 绑定摄像头 + * + * @param userId + * @param cameraId + * @return + */ + @Override + public Object bindCamera(Integer userId, String cameraId) { + try { + Tbl_User user = userHelperI.getUserById(userId); + Tbl_Device camera = getDeviceByCameraId(cameraId); + //返回数据 + Map dataMap = new HashMap(); + //用户存在 + if (user != null) { + //摄像头存在 + if (camera != null) { + //已关联摄像头的用户 + List CameraUserList = tbl_Device_Mapper.getDeviceUsersByDeviceId(camera.getDeviceId()); + //删除摄像头与用户关系 + for (Tbl_Device_User cu : CameraUserList) { + //删除摄像头和用户的关系 + tbl_Device_Mapper.deleteDeviceUserById(cu.getId()); + } + } else { + //摄像头不存在 + camera = new Tbl_Device(); + camera.setCameraId(cameraId); + camera.setCreateTime(new Date()); + camera.setIsCamera("1"); + tbl_Device_Mapper.insertDevice(camera); + } + //建立关系 + Tbl_Device_User device_User = new Tbl_Device_User(); + device_User.setUserId(userId); + device_User.setIsMaster("1"); + device_User.setIsLook("0"); + device_User.setIsLive("0"); + device_User.setDeviceId(camera.getDeviceId()); + device_User.setShowName("摄像头" + (int) (Math.random() * 900 + 100)); + device_User.setCreateTime(new Date()); + tbl_Device_Mapper.insertDeviceUser(device_User); + //返回数据 + dataMap.put("cameraId", cameraId); + dataMap.put("showName", device_User.getShowName()); + dataMap.put("isMaster", device_User.getIsMaster()); + dataMap.put("isLook", device_User.getIsLook()); + dataMap.put("isLive", device_User.getIsLive()); + dataMap.put("isActive", camera.getActiveCode() != null && !camera.getActiveCode().equals("") ? "1" : "0"); + return IfishUtil.returnJson(ResultEnum.success.getKey(), dataMap); + } else { + return IfishUtil.returnJson(ResultEnum.warn202.getKey(), ""); + } + } catch (Exception e) { + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + } + + /** + * 激活摄像头 + */ + @Override + public Object activeCamera(String activeCode, String cameraId) { + try { + Tbl_Activa_Code activa_Code = tbl_Device_Mapper.getActiva_CodeByCode(activeCode); + if (activa_Code != null) { + if (activa_Code.getIsUsed().equals("1")) { + return IfishUtil.returnJson(ResultEnum.warn208.getKey(), ""); + } else { + Tbl_Device camera = tbl_Device_Mapper.getDeviceByCameraId(cameraId); + if (camera != null) { + if (StringUtils.isNotBlank(camera.getActiveCode())) { + return IfishUtil.returnJson(ResultEnum.success.getKey(), ""); + } else { + Date date = new Date(); + camera.setActiveCode(activeCode); + camera.setActiveTime(date); + camera.setUpdateTime(date); + int i = tbl_Device_Mapper.updateTbl_Device(camera); + + activa_Code.setIsUsed("1"); + tbl_Device_Mapper.updateTblActivaCodeIsUse(activeCode); + return IfishUtil.returnJson(ResultEnum.success.getKey(), ""); + } + } else { + return IfishUtil.returnJson(ResultEnum.warn210.getKey(), ""); + } + } + } else { + return IfishUtil.returnJson(ResultEnum.warn209.getKey(), ""); + } + } catch (Exception e) { + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + } + + /** + * 修改设备和用户的关系数据 + * + * @param device + * @param userId + * @return + */ + @Override + public Object updateDeviceUser(Tbl_Device_User device) { + + try { + Tbl_Device_User olDevice_User = getDeviceUserByUserId_DeviceId(device.getUserId(), device.getDeviceId()); + String key = RedisKey.DeviceUser_Key + device.getUserId(); + String key2 = RedisKey.DeviceUser_Key + "d" + device.getDeviceId() + "_u" + device.getUserId(); + if (device != null) { + if (olDevice_User != null) { + device.setId(olDevice_User.getId()); + int i = tbl_Device_Mapper.updateTblDeviceUser(device); + if (i > 0) { + redisHelperI.deleteRedis(key); + redisHelperI.deleteRedis(key2); + Tbl_Device device1 = getDeviceById(device.getDeviceId()); + return IfishUtil.returnJson(ResultEnum.success.getKey(), userHelperI.getDeviceInfo(device1, device)); + } + } + return IfishUtil.returnJson(ResultEnum.warn207.getKey(), ""); + } else { + return IfishUtil.returnJson(ResultEnum.warn207.getKey(), ""); + } + } catch (Exception e) { + } + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + + /** + * 修改摄像头信息 + * + * @param cameraId + * @param device_User + * @return + */ + @Override + public Object updateCameraUser(Integer cameraId, Tbl_Device_User device_User) { + try { + Tbl_Device_User olDevice_User = getDeviceUserByUserId_CameraId(device_User.getUserId(), cameraId.toString()); + if (olDevice_User != null) { + if (olDevice_User != null) { + String key = RedisKey.DeviceUser_Key + device_User.getUserId(); + String key2 = RedisKey.DeviceUser_Key + "d" + olDevice_User.getDeviceId() + "_u" + device_User.getUserId(); + device_User.setId(olDevice_User.getId()); + int i = tbl_Device_Mapper.updateTblDeviceUser(device_User); + if (i > 0) { + redisHelperI.deleteRedis(key); + redisHelperI.deleteRedis(key2); + Map dataMap = new HashMap(); + dataMap.put("cameraId", cameraId); + dataMap.put("showName", device_User.getShowName()); + dataMap.put("isMaster", device_User.getIsMaster()); + dataMap.put("isLook", device_User.getIsLook()); + dataMap.put("isLive", device_User.getIsLive()); + Tbl_Device camera = getDeviceById(olDevice_User.getDeviceId()); + dataMap.put("isActive", camera.getActiveCode() != null && !camera.getActiveCode().equals("") ? "1" : "0"); + return IfishUtil.returnJson(ResultEnum.success.getKey(), dataMap); + } + } + return IfishUtil.returnJson(ResultEnum.warn207.getKey(), ""); + } else { + return IfishUtil.returnJson(ResultEnum.warn207.getKey(), ""); + } + } catch (Exception e) { + } + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + + /** + * 解除绑定设备 + * + * @param deviceUser + * @return + */ + @Override + public Object deleteDeviceUser(Tbl_Device_User deviceUser) { + try { + Tbl_Device_User device_User = getDeviceUserByUserId_DeviceId(deviceUser.getUserId(), deviceUser.getDeviceId()); + if (device_User != null) { + int i = tbl_Device_Mapper.deleteDeviceUserById(device_User.getId()); + if (i > 0) { + String key = RedisKey.DeviceUser_Key + device_User.getUserId(); + String key2 = RedisKey.DeviceUser_Key + "d" + device_User.getDeviceId() + "_u" + device_User.getUserId(); + redisHelperI.deleteRedis(key); + redisHelperI.deleteRedis(key2); + return IfishUtil.returnJson(ResultEnum.success.getKey(), ""); + } + } + } catch (Exception e) { + } + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + + /** + * 删除绑定摄像头 + * + * @param userId + * @param cameraId + * @return + */ + @Override + public Object deleteCameraUser(Integer userId, String cameraId) { + try { + Tbl_Device_User device_User = getDeviceUserByUserId_CameraId(userId, cameraId); + if (device_User != null) { + int i = tbl_Device_Mapper.deleteDeviceUserById(device_User.getId()); + if (i > 0) { + String key = RedisKey.DeviceUser_Key + device_User.getUserId(); + String key2 = RedisKey.DeviceUser_Key + "d" + device_User.getDeviceId() + "_u" + device_User.getUserId(); + String key3 = RedisKey.Camera_key + cameraId; + redisHelperI.deleteRedis(key); + redisHelperI.deleteRedis(key2); + redisHelperI.deleteRedis(key3); + return IfishUtil.returnJson(ResultEnum.success.getKey(), ""); + } + } + } catch (Exception e) { + } + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + + /** + * 极光推送 + * + * @param userId + */ + public boolean jPushNotifcation(Map baseMap, Map pushMap) { + try { + + } catch (Exception e) { + throw new RuntimeException(); + } + return false; + } +} diff --git a/src/main/java/com/ifish/helper/DeviceHelperI.java b/src/main/java/com/ifish/helper/DeviceHelperI.java new file mode 100644 index 0000000..bc83b8d --- /dev/null +++ b/src/main/java/com/ifish/helper/DeviceHelperI.java @@ -0,0 +1,124 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.helper; + +import com.ifish.bean.Tbl_Device; +import com.ifish.bean.Tbl_Device_User; +import com.ifish.bean.Tbl_User; +import java.util.List; + +/** + * + * @author Administrator + */ +public interface DeviceHelperI { + + /** + * 根据用户Id获取绑定设备集合 + * + * @param userId + * @return + * @throws java.lang.Exception + */ + List getDeviceUsersByUserId(Integer userId) throws Exception; + + /** + * 根据用户ID和摄像头信息获取用户关联数据 + * + * @return + */ + Tbl_Device_User getDeviceUserByUserId_CameraId(Integer userId, String cameraId) throws Exception; + + /** + * 根据设备Id获取设备详情 + * + * @param deviceId + * @return + * @throws Exception + */ + Tbl_Device getDeviceById(Integer deviceId) throws Exception; + + /** + * 根据设备MacAddress获取设备详情 + * + * @param macAddress + * @param deviceId + * @return + * @throws Exception + */ + Tbl_Device getDeviceByMacAddress(String macAddress) throws Exception; + + /** + * 绑定设备 + * + * @param userId + * @param mackAddress + * @return + */ + Object bindDevice(Integer userId, String mackAddress); + + /** + * 激活摄像头 + * + * @param activeCode + * @param cameraId + * @return + */ + Object activeCamera(String activeCode, String cameraId); + + /** + * 绑定摄像头 + * + * @param userId + * @param cameraId + * @return + */ + Object bindCamera(Integer userId, String cameraId); + + /** + * 根据摄像头ID获取设备信息 + * + * @param cameraId + * @return + */ + Tbl_Device getDeviceByCameraId(String cameraId) throws Exception; + + /** + * 修改设备信息 + * + * @param device + * @param userId + * @return + */ + Object updateDeviceUser(Tbl_Device_User device); + + /** + * 修改摄像头信息 + * + * @param cameraId + * @param device_User + * @return + */ + Object updateCameraUser(Integer cameraId, Tbl_Device_User device_User); + + /** + * 删除绑定摄像头 + * + * @param userId + * @param cameraId + * @return + */ + Object deleteCameraUser(Integer userId, String cameraId); + + /** + * 删除绑定的设备 + * + * @param deviceUser + * @return + */ + Object deleteDeviceUser(Tbl_Device_User deviceUser); + +} diff --git a/src/main/java/com/ifish/helper/FastDFSClient.java b/src/main/java/com/ifish/helper/FastDFSClient.java new file mode 100644 index 0000000..04a5ea9 --- /dev/null +++ b/src/main/java/com/ifish/helper/FastDFSClient.java @@ -0,0 +1,145 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.helper; + +import com.ifish.util.IfishFilePath; +import com.ifish.util.IfishUtil; +import org.apache.commons.lang3.StringUtils; +import org.csource.fastdfs.ClientGlobal; +import org.csource.fastdfs.StorageClient1; +import org.csource.fastdfs.StorageServer; +import org.csource.fastdfs.TrackerClient; +import org.csource.fastdfs.TrackerServer; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +@Component +public class FastDFSClient implements FastDFSClientI { + + private TrackerClient trackerClient = null; + private TrackerServer trackerServer = null; + private StorageServer storageServer = null; + //使用StorageClient1进行上传 + private StorageClient1 storageClient1 = null; + + public FastDFSClient() throws Exception { + //获取classpath路径下配置文件"fdfs_client.conf"的路径 + //conf直接写相对于classpath的位置,不需要写classpath: + String conf = ""; + if (IfishFilePath.link_img_head.contains("ifish7")) { + conf = "fdfs_client_ifish7.conf"; + } else { + conf = "fdfs_client_zhangxinyanv5.conf"; + } + + String configPath = this.getClass().getClassLoader().getResource(conf).getFile(); + System.out.println(configPath); + ClientGlobal.init(configPath); + + trackerClient = new TrackerClient(); + trackerServer = trackerClient.getConnection(); + storageServer = trackerClient.getStoreStorage(trackerServer); + storageClient1 = new StorageClient1(trackerServer, storageServer); + } + + /** + * 上传一个字节型文件 + * + * @param file_buff 字节数组 + * @param file_ext_name 文件后缀 + * @return + * @throws Exception + */ + @Override + public String uploadFile(byte[] file_buff, String file_ext_name) throws Exception { + + String result = ""; + + try { + result = storageClient1.upload_file1(file_buff, file_ext_name, null); + } catch (Exception e) { + try { + result = storageClient1.upload_file1(file_buff, file_ext_name, null); + } catch (Exception a) { + return ""; + } + } + + return result; + } + + /** + * 上传一个本地文件 + * + * @param local_filename 本地文件名(路径+文件名+后缀) + * @param file_ext_name 文件后缀 + * @return + * @throws Exception + */ + @Override + public String uploadFile(String local_filename, String file_ext_name) throws Exception { + + String result = storageClient1.upload_file1(local_filename, file_ext_name, null); + + return result; + } + + /** + * 上传一个文件 + * + * @param group_name 指定位置 + * @param local_filename 本地文件名(路径+文件名+后缀) + * @param file_ext_name 文件后缀 + * @return + * @throws Exception + */ + @Override + public String uploadFile(String group_name, String local_filename, String file_ext_name) throws Exception { + + String result = storageClient1.upload_file1(group_name, local_filename, file_ext_name, null); + + return result; + } + + public String getFileType(MultipartFile file) { + String[] allowTypes = new String[]{".mp4", ".png", ".jpg", ".bmp"}; + String filename = file.getOriginalFilename(); + if (StringUtils.isNotBlank(filename)) { + for (String allowType : allowTypes) { + if (filename.contains(allowType)) { + return allowType.replace(".", ""); + } + } + } + return ""; + } + + @Override + public String uploadFileToFastDFS(MultipartFile file) { + try { + String type = getFileType(file); + if (StringUtils.isBlank(type)) { + return null; + } + byte[] bt = file.getBytes(); + String url = uploadFile(bt, type); + if (url.contains("group1/M00/")) { + url = url.replace("group1/M00/", ""); + } else { + return ""; + } + //本地返回测试环境fastfds,线上返回正式服务器部署的fastfds + if (IfishUtil.IsWinOrUnix()) { + return IfishFilePath.fastDFS_url_app + url; + } else { + return IfishFilePath.link_img_head + url; + } + + } catch (Exception e) { + return ""; + } + } +} diff --git a/src/main/java/com/ifish/helper/FastDFSClientI.java b/src/main/java/com/ifish/helper/FastDFSClientI.java new file mode 100644 index 0000000..a937ff3 --- /dev/null +++ b/src/main/java/com/ifish/helper/FastDFSClientI.java @@ -0,0 +1,55 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.helper; + +import org.springframework.web.multipart.MultipartFile; + +/** + * FastDFS分布式文件管理系统接口方法 + * + * @author Administrator + */ +public interface FastDFSClientI { + + /** + * 上传一个字节型文件 + * + * @param file_buff 字节数组 + * @param file_ext_name 文件后缀 + * @return + * @throws Exception + */ + String uploadFile(byte[] file_buff, String file_ext_name) throws Exception; + + /** + * 上传一个本地文件 + * + * @param local_filename 本地文件名(路径+文件名+后缀) + * @param file_ext_name 文件后缀 + * @return + * @throws Exception + */ + String uploadFile(String local_filename, String file_ext_name) throws Exception; + + /** + * 上传一个文件 + * + * @param group_name 指定位置 + * @param local_filename 本地文件名(路径+文件名+后缀) + * @param file_ext_name 文件后缀 + * @return + * @throws Exception + */ + String uploadFile(String group_name, String local_filename, String file_ext_name) throws Exception; + + /** + * 上传一个MultipartFile类型文件,返回成功后文件路径,适用于保存完整路径方法 + * + * @param file + * @return + */ + String uploadFileToFastDFS(MultipartFile file); +} diff --git a/src/main/java/com/ifish/helper/HardWareTypeHelper.java b/src/main/java/com/ifish/helper/HardWareTypeHelper.java new file mode 100644 index 0000000..c293548 --- /dev/null +++ b/src/main/java/com/ifish/helper/HardWareTypeHelper.java @@ -0,0 +1,66 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.helper; + +import com.ifish.bean.Tbl_HardWare_Type; +import com.ifish.bean.Tbl_Vender; +import com.ifish.mapper.Tbl_Hardware_Type_Mapper; +import com.ifish.util.IfishUtil; +import com.ifish.util.RedisKey; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * + * @author Administrator + */ +@Component +public class HardWareTypeHelper implements HardWareTypeHelperI { + + /** + * 所有tbl_Hardware_Type表的操作方法接口 + */ + @Autowired + private Tbl_Hardware_Type_Mapper tbl_Hardware_Type_Mapper; + + /** + * redis缓存服务器方法接口 + */ + @Autowired + private RedisHelperI redisHelperI; + + @Override + public Tbl_HardWare_Type getHardwareTypeByTypeCode(String code) throws Exception { + Tbl_HardWare_Type hardwareType = null; + String key = RedisKey.HardWareType_key + code; + String redisString = redisHelperI.getRedis(key); + if (StringUtils.isNotBlank(redisString)) { + hardwareType = (Tbl_HardWare_Type) IfishUtil.JsonToBean(redisString, Tbl_HardWare_Type.class); + } else { + hardwareType = tbl_Hardware_Type_Mapper.getHardwareTypeByTypeCode(code); + if (hardwareType != null && StringUtils.isNotBlank(hardwareType.getHardwareType())) { + redisHelperI.setRedis(key, IfishUtil.ObjectToJson(hardwareType)); + } + } + return hardwareType; + } + + @Override + public Tbl_Vender getVenderListByBrandCode(String code) throws Exception { + Tbl_Vender venderList = new Tbl_Vender(); + String key = RedisKey.VenderList_key + code; + String redisString = redisHelperI.getRedis(key); + if (StringUtils.isNotBlank(redisString)) { + venderList = (Tbl_Vender) IfishUtil.JsonToBean(redisString, Tbl_Vender.class); + } else { + venderList = tbl_Hardware_Type_Mapper.getVenderListByBrandCode(code); + redisHelperI.setRedis(key, IfishUtil.ObjectToJson(venderList)); + } + return venderList; + } +} + diff --git a/src/main/java/com/ifish/helper/HardWareTypeHelperI.java b/src/main/java/com/ifish/helper/HardWareTypeHelperI.java new file mode 100644 index 0000000..284a9d5 --- /dev/null +++ b/src/main/java/com/ifish/helper/HardWareTypeHelperI.java @@ -0,0 +1,34 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.helper; + +import com.ifish.bean.Tbl_HardWare_Type; +import com.ifish.bean.Tbl_Vender; + +/** + * + * @author Administrator + */ +public interface HardWareTypeHelperI { + + /** + * 根据设备型号获取设备类型参数 + * + * @param code + * @return + */ + Tbl_HardWare_Type getHardwareTypeByTypeCode(String code) throws Exception; + + /** + * 根据厂家code获取厂家信息 + * + * @param code + * @return + * @throws Exception + */ + Tbl_Vender getVenderListByBrandCode(String code) throws Exception; + +} diff --git a/src/main/java/com/ifish/helper/LiveRoomHelper.java b/src/main/java/com/ifish/helper/LiveRoomHelper.java new file mode 100644 index 0000000..56b9c29 --- /dev/null +++ b/src/main/java/com/ifish/helper/LiveRoomHelper.java @@ -0,0 +1,429 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.helper; + +import com.ifish.Interceptor.IfishException; +import com.ifish.bean.LiveRoomPageInfo; +import com.ifish.bean.Tbl_Device_User; +import com.ifish.bean.Tbl_Live_Message; +import com.ifish.bean.Tbl_Live_Room; +import com.ifish.bean.Tbl_User; +import com.ifish.enums.ResultEnum; +import com.ifish.mapper.Tbl_Live_Room_Mapper; +import com.ifish.util.IfishUtil; +import com.ifish.util.RedisKey; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import static org.springframework.http.converter.json.Jackson2ObjectMapperBuilder.json; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +/** + * + * @author Administrator + */ +@Component +public class LiveRoomHelper implements LiveRoomHelperI { + + @Autowired + private FastDFSClientI fastDFSClientI; + + @Autowired + private Tbl_Live_Room_Mapper tbl_Live_Room_Mapper; + + @Autowired + private UserHelperI userHelperI; + + @Autowired + private DeviceHelperI deviceHelperI; + + @Autowired + private RedisHelperI redisHelperI; + + /** + * 新增直播间 + * + * @param fileUpload + * @param liveRoom + */ + @Override + public Object addLiveRoom(MultipartFile fileUpload, Tbl_Live_Room liveRoom) { + try { + if (liveRoom.getUserId() == null || liveRoom.getUserId() <= 0) { + throw new IfishException(ResultEnum.error401); + } + if (StringUtils.isBlank(liveRoom.getRoomName()) || liveRoom.getRoomName().length() > 20) { + throw new IfishException(ResultEnum.error401); + } + if (StringUtils.isBlank(liveRoom.getRoomDesc()) || liveRoom.getRoomDesc().length() > 70) { + throw new IfishException(ResultEnum.error401); + } + if (StringUtils.isBlank(liveRoom.getRoomStatus()) || liveRoom.getRoomStatus().length() > 1) { + throw new IfishException(ResultEnum.error401); + } + if (StringUtils.isBlank(liveRoom.getCameraId()) || liveRoom.getCameraId().length() > 20) { + throw new IfishException(ResultEnum.error401); + } + if (fileUpload == null || fileUpload.getSize() > 1048576) { + //throw new IfishException(ResultEnum.warn206); + } + String file = fastDFSClientI.uploadFileToFastDFS(fileUpload); + if (StringUtils.isNotBlank(file)) { + liveRoom.setRoomImg(file); + } + + //用户ID + Integer userId = liveRoom.getUserId(); + Tbl_User user = userHelperI.getUserById(userId); + if (user == null) { + throw new IfishException(ResultEnum.error402); + } + //用户是否绑定摄像头 + String cameraId = liveRoom.getCameraId(); + Tbl_Device_User cameraUser = deviceHelperI.getDeviceUserByUserId_CameraId(userId, cameraId); + + if (cameraUser == null) { + throw new IfishException(ResultEnum.error402); + } + //原来不是开启状态 + Boolean cameraChange = false; + if (cameraUser.getIsLive().equals("0")) { + cameraUser.setIsLive("1"); + cameraChange = true; + } + //新增直播间 + liveRoom.setCreateTime(new Date()); + liveRoom.setFirstShare(0); + liveRoom.setPopularityValue(0); + int i = tbl_Live_Room_Mapper.insertLiveRoom(liveRoom); + if (i > 0) { + if (cameraChange) { + deviceHelperI.updateDeviceUser(cameraUser); + } + Map map = new HashMap(); + map.put("cameraId", cameraId); + map.put("isLive", cameraUser.getIsLive()); + map.put("roomId", liveRoom.getRoomId()); + return IfishUtil.returnJson(ResultEnum.success.getKey(), map); + } + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } catch (Exception e) { + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + + } + + /** + * 根据直播间ID获取直播间详情 + * + * @param roomId + * @return + */ + public Tbl_Live_Room getLive_RoomById(Integer roomId) throws Exception { + Tbl_Live_Room live_Room = null; + String key = RedisKey.LiveRoom_key + roomId; + String redisString = redisHelperI.getRedis(key); + if (StringUtils.isNotBlank(redisString)) { + live_Room = (Tbl_Live_Room) IfishUtil.JsonToBean(redisString, Tbl_Live_Room.class); + } else { + live_Room = tbl_Live_Room_Mapper.getTbl_Live_RoomById(roomId); + if (live_Room != null && live_Room.getRoomId() > 0) { + redisHelperI.setRedis(key, IfishUtil.ObjectToJson(live_Room)); + } + } + return live_Room; + } + + /** + * 根据用户ID获取直播间详情 + * + * @param roomId + * @return + */ + public Tbl_Live_Room getLive_RoomByUserId(Integer userId) throws Exception { + Tbl_Live_Room live_Room = null; + String key = RedisKey.LiveRoom_key + "u_" + userId; + String redisString = redisHelperI.getRedis(key); + if (StringUtils.isNotBlank(redisString)) { + live_Room = (Tbl_Live_Room) IfishUtil.JsonToBean(redisString, Tbl_Live_Room.class); + } else { + live_Room = tbl_Live_Room_Mapper.getLive_RoomByUserId(userId); + if (live_Room != null && live_Room.getRoomId() > 0) { + redisHelperI.setRedis(key, IfishUtil.ObjectToJson(live_Room)); + } + } + return live_Room; + } + + /** + * 根据房间ID查询直播间 + * + * @param roomId + * @return + */ + public Tbl_Live_Room getTbl_Live_RoomById(Integer roomId) throws Exception { + Tbl_Live_Room device = null; + String key = RedisKey.LiveRoom_key + roomId; + String redisString = redisHelperI.getRedis(key); + if (StringUtils.isNotBlank(redisString)) { + device = (Tbl_Live_Room) IfishUtil.JsonToBean(redisString, Tbl_Live_Room.class); + } else { + device = tbl_Live_Room_Mapper.getTbl_Live_RoomById(roomId); + if (device != null && device.getRoomId() > 0) { + redisHelperI.setRedis(key, IfishUtil.ObjectToJson(device)); + } + } + return device; + } + + /** + * 直播间点赞 + * + * @param roomId + * @param userId + * @return + */ + @Override + public Object liveRoomsZan(Integer roomId, Integer userId) { + try { + //点赞和人气值不一样,人气值只此直播间点击数,点赞指观看此直播并点赞的人数 + Tbl_Live_Room room = getTbl_Live_RoomById(roomId); + if (room == null) { + throw new IfishException(ResultEnum.error402); + } + Tbl_User user = userHelperI.getUserById(userId); + if (user == null) { + throw new IfishException(ResultEnum.error402); + } + //点赞数量 + Integer zanNum = tbl_Live_Room_Mapper.getLiveRoomZanCountByRoomId(roomId); + //是否点过赞 + int i = tbl_Live_Room_Mapper.IsZan(roomId, userId); + Map map = new HashMap(); + //点赞过,取消点赞 + if (i > 0) { + int j = tbl_Live_Room_Mapper.cancelZan(roomId, userId); + //成功取消 + if (j > 0) { + zanNum--; + map.put("isZan", 0); + map.put("zanNum", zanNum); + return IfishUtil.returnJson(ResultEnum.success.getKey(), map); + } + } //没有点赞,点赞一次 + else { + int j = tbl_Live_Room_Mapper.ImplementZan(roomId, userId); + if (j > 0) { + zanNum++; + map.put("isZan", 1); + map.put("zanNum", zanNum); + return IfishUtil.returnJson(ResultEnum.success.getKey(), map); + } + } + + } catch (Exception e) { + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + + /** + * 直播间留言 + * + * @param liveMessage + * @return + */ + @Override + public Object leaveMessage(Tbl_Live_Message liveMessage) { + try { + Integer roomId = liveMessage.getRoomId(); + Integer userId = liveMessage.getUserId(); + String messageContent = new String(liveMessage.getMessageContent().getBytes("ISO-8859-1"), "UTF-8"); + liveMessage.setMessageContent(messageContent); + if (roomId != null && userId != null && StringUtils.isNotBlank(messageContent)) { + Tbl_Live_Room live_Room = getLive_RoomById(roomId); + Tbl_User user = userHelperI.getUserById(userId); + if (live_Room != null && user != null) { + liveMessage.setCreateTime(new Date()); + int i = tbl_Live_Room_Mapper.insertLiveMessage(liveMessage); + if (i > 0) { + liveMessage.setUserName(user.getNickName()); + liveMessage.setUserImg(user.getUserImg()); + } + liveMessage.setUserName(user.getNickName()); + liveMessage.setUserImg(user.getUserImg()); + Integer asUserId = liveMessage.getAsUserId(); + if (asUserId != null) { + Tbl_User asUser = userHelperI.getUserById(asUserId); + if (asUser != null) { + liveMessage.setAsUserName(asUser.getNickName()); + if (!asUserId.equals(userId)) { + //发送云信消息给所@的用户 + //neteaseIM.sendMsg(userId.toString(), asUserId.toString(), "来自爱鱼看看的回复:" + messageContent, ""); + } + } else { + Integer roomUserId = live_Room.getUserId(); + if (!roomUserId.equals(userId)) { + //发送云信消息给房主 + //neteaseIM.sendMsg(userId.toString(), roomUserId.toString(), "来自爱鱼看看的留言:" + messageContent, ""); + } + } + } + return IfishUtil.toJson(ResultEnum.success.getKey(), liveMessage); + } + } + return IfishUtil.toJson(ResultEnum.fail101.getKey(), ""); + } catch (Exception e) { + return IfishUtil.toJson(ResultEnum.fail101.getKey(), ""); + } + } + + /** + * 根据用户ID获取直播间信息 + * + * @param userId + * @return + */ + @Override + public Object getLiveRoomInfo(Integer userId) { + try { + if (userId != null) { + //查找直播间信息 + Tbl_Live_Room curLiveRoom = getLive_RoomByUserId(userId); + if (curLiveRoom != null) { + Map map = new HashMap(); + Integer roomId = curLiveRoom.getRoomId(); + map.put("roomId", roomId); + map.put("userId", curLiveRoom.getUserId()); + map.put("roomName", curLiveRoom.getRoomName()); + map.put("roomDesc", curLiveRoom.getRoomDesc()); + map.put("popularityValue", curLiveRoom.getPopularityValue()); + map.put("roomStatus", curLiveRoom.getRoomStatus()); + return IfishUtil.toJson(ResultEnum.success.getKey(), map); + } + } + return IfishUtil.toJson(ResultEnum.success.getKey(), ""); + } catch (Exception e) { + return IfishUtil.toJson(ResultEnum.fail101.getKey(), ""); + } + } + + /** + * 根据条件查询直播间列表 + * + * @param firstResult + * @param pageSize + * @param userId + * @param orders + * @return + */ + @Override + public Object getLiveRooms(Integer firstResult, Integer pageSize, Integer userId, String orders) { + try { + if (firstResult != null && pageSize != null && userId != null) { + Map returnMap = new HashMap(); + Map map = new HashMap(); + if (firstResult == 0) { + Tbl_User user = userHelperI.getUserById(userId); + if (user != null) { + //经度 + Double longitude = user.getLongitude(); + //纬度 + Double latitude = user.getLatitude(); + //距离用户最近的前5条记录 + List distanceList = tbl_Live_Room_Mapper.getLiveRoomListByLongLat(longitude, latitude); + for (LiveRoomPageInfo liveRoomInfo : distanceList) { + Integer roomId = liveRoomInfo.getRoomId(); + map.put(roomId, liveRoomInfo); + } + //获取用户最近浏览的5条记录 + List browseList = this.liveRoomDao.findByBrowse(userId); + for (LiveRoomPageInfo liveRoomInfo : browseList) { + Integer roomId = liveRoomInfo.getRoomId(); + map.put(roomId, liveRoomInfo); + } + //获取人气值最高的5条记录 + List popularityList = this.liveRoomDao.findByPopularityValue(); + for (LiveRoomPageInfo liveRoomInfo : popularityList) { + Integer roomId = liveRoomInfo.getRoomId(); + map.put(roomId, liveRoomInfo); + } + //去重条件 + orders = StringUtils.join(map.keySet().toArray(), ","); + //根据开播时间倒序排列 + Pagination page = this.liveRoomDao.findByTime(firstResult, pageSize, orders); + List timeList = page.getList(); + for (LiveRoomPageInfo liveRoomInfo : timeList) { + Integer roomId = liveRoomInfo.getRoomId(); + map.put(roomId, liveRoomInfo); + } + List list = new ArrayList(); + Long curTime = new Date().getTime(); + //计算活跃值 + for (LiveRoomPageInfo liveRoomInfo : map.values()) { + Long loginTime = liveRoomInfo.getLoginTime().getTime(); + //最近登录天数 + Integer days = (int) ((curTime - loginTime) / (1000 * 60 * 60 * 24)); + //小于一周 + if (days <= 7) { + liveRoomInfo.setLiveness("优"); + } //一周至半个月 + else if (days > 7 && days <= 15) { + liveRoomInfo.setLiveness("良"); + } //半个月至一个月 + else if (days > 15 && days <= 30) { + liveRoomInfo.setLiveness("中"); + } else { + liveRoomInfo.setLiveness("差"); + } + list.add(liveRoomInfo); + } + returnMap.put("orders", orders); + returnMap.put("total", page.getTotalCount()); + returnMap.put("liveRoomInfo", list); + return IfishUtil.toJson(ResultEnum.success.getKey(), returnMap); + } + } else { + //根据开播时间倒序排列 + Pagination page = this.liveRoomDao.findByTime(firstResult, pageSize, orders); + List timeList = page.getList(); + Long curTime = new Date().getTime(); + //计算活跃值 + for (LiveRoomPageInfo liveRoomInfo : timeList) { + Long loginTime = liveRoomInfo.getLoginTime().getTime(); + //最近登录天数 + Integer days = (int) ((curTime - loginTime) / (1000 * 60 * 60 * 24)); + //小于一周 + if (days <= 7) { + liveRoomInfo.setLiveness("优"); + } //一周至半个月 + else if (days > 7 && days <= 15) { + liveRoomInfo.setLiveness("良"); + } //半个月至一个月 + else if (days > 15 && days <= 30) { + liveRoomInfo.setLiveness("中"); + } else { + liveRoomInfo.setLiveness("差"); + } + } + returnMap.put("orders", orders); + returnMap.put("total", page.getTotalCount()); + returnMap.put("liveRoomInfo", timeList); + return IfishUtil.toJson(ResultEnum.success.getKey(), returnMap); + } + } + return IfishUtil.toJson(ResultEnum.fail101.getKey(), ""); + } catch (Exception e) { + return IfishUtil.toJson(ResultEnum.fail101.getKey(), ""); + } + } +} diff --git a/src/main/java/com/ifish/helper/LiveRoomHelperI.java b/src/main/java/com/ifish/helper/LiveRoomHelperI.java new file mode 100644 index 0000000..2234d45 --- /dev/null +++ b/src/main/java/com/ifish/helper/LiveRoomHelperI.java @@ -0,0 +1,62 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.helper; + +import com.ifish.bean.Tbl_Live_Message; +import com.ifish.bean.Tbl_Live_Room; +import com.ifish.controller.LiveRoom; +import org.springframework.web.multipart.MultipartFile; + +/** + * + * @author Administrator + */ +public interface LiveRoomHelperI { + + /** + * 新增直播间 + * + * @param fileUpload + * @param liveRoom + */ + Object addLiveRoom(MultipartFile fileUpload, Tbl_Live_Room liveRoom); + + /** + * 直播间点赞 + * + * @param roomId + * @param userId + * @return + */ + Object liveRoomsZan(Integer roomId, Integer userId); + + /** + * 直播间留言 + * + * @param liveMessage + * @return + */ + Object leaveMessage(Tbl_Live_Message liveMessage); + + /** + * 根据用户ID获取直播间信息 + * + * @param userId + * @return + */ + Object getLiveRoomInfo(Integer userId); + + /** + * 根据条件查询直播间列表 + * + * @param firstResult + * @param pageSize + * @param userId + * @param orders + * @return + */ + Object getLiveRooms(Integer firstResult, Integer pageSize, Integer userId, String orders); +} diff --git a/src/main/java/com/ifish/helper/PushMessageHelper.java b/src/main/java/com/ifish/helper/PushMessageHelper.java new file mode 100644 index 0000000..93e3e9b --- /dev/null +++ b/src/main/java/com/ifish/helper/PushMessageHelper.java @@ -0,0 +1,110 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.helper; + +import com.ifish.bean.PageResult; +import com.ifish.bean.Tbl_Push_List; +import com.ifish.enums.ResultEnum; +import com.ifish.mapper.Tbl_Push_List_Mapper; +import com.ifish.util.IfishUtil; +import com.ifish.util.RedisKey; +import java.util.List; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * + * @author Administrator + */ +@Component +public class PushMessageHelper implements PushMessageHelperI { + + @Autowired + private Tbl_Push_List_Mapper tbl_Push_List_Mapper; + + @Autowired + private RedisHelperI redisHelperI; + + /** + * 根据条件获取推送列表 + * + * @param pushId + * @param userId + * @param firstResult + * @param pageSize + * @return + */ + @Override + public Object getPushList(String pushType, Integer userId, Integer firstResult, Integer pageSize) { + try { + if (firstResult == null) { + firstResult = 0; + } + if (pageSize == null) { + pageSize = 10; + } + if (userId == null) { + return IfishUtil.returnJson(ResultEnum.error401.getKey(), ""); + } + List list = tbl_Push_List_Mapper.getPushList(userId, pushType, pageSize, firstResult); + int count = tbl_Push_List_Mapper.getPushListCount(userId, pushType, pageSize, firstResult); + PageResult page = new PageResult(); + page.setList(list); + page.setPageNo(firstResult); + page.setPageSize(pageSize); + page.setTotalCount(count); + return IfishUtil.returnPageData(page, ResultEnum.success.getKey()); + } catch (Exception e) { + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + } + + /** + * 删除推送消息 + * + * @param userId + * @param pushId + * @return + */ + @Override + public Object deletePushList(Integer userId, Integer pushId) { + try { + Tbl_Push_List tpl = getPush_ListById(pushId); + if (tpl.getUserId().equals(userId)) { + int i = tbl_Push_List_Mapper.deletePushListById(pushId); + if (i > 0) { + return IfishUtil.returnJson(ResultEnum.success.getKey(), ""); + } + } + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } catch (Exception e) { + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + } + + /** + * 根据ID从缓存中获取推送消息对象 + * + * @param pushId + * @return + * @throws Exception + */ + public Tbl_Push_List getPush_ListById(Integer pushId) throws Exception { + Tbl_Push_List list = null; + String key = RedisKey.PUSHLIST_KEY + pushId; + String redisString = redisHelperI.getRedis(key); + if (StringUtils.isNotBlank(redisString)) { + list = (Tbl_Push_List) IfishUtil.JsonToBean(redisString, Tbl_Push_List.class); + } else { + list = tbl_Push_List_Mapper.getPush_ListById(pushId); + if (list != null && list.getPushId() > 0) { + redisHelperI.setRedis(key, IfishUtil.ObjectToJson(list)); + } + } + return list; + } +} diff --git a/src/main/java/com/ifish/helper/PushMessageHelperI.java b/src/main/java/com/ifish/helper/PushMessageHelperI.java new file mode 100644 index 0000000..00a6aa0 --- /dev/null +++ b/src/main/java/com/ifish/helper/PushMessageHelperI.java @@ -0,0 +1,33 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.helper; + +/** + * + * @author Administrator + */ +public interface PushMessageHelperI { + + /** + * 根据条件获取推送列表 + * + * @param pushId + * @param userId + * @param firstResult + * @param pageSize + * @return + */ + Object getPushList(String pushType, Integer userId, Integer firstResult, Integer pageSize); + + /** + * 删除推送消息 + * + * @param userId + * @param pushId + * @return + */ + Object deletePushList(Integer userId, Integer pushId); +} diff --git a/src/main/java/com/ifish/helper/RedisHelper.java b/src/main/java/com/ifish/helper/RedisHelper.java new file mode 100644 index 0000000..5f8f512 --- /dev/null +++ b/src/main/java/com/ifish/helper/RedisHelper.java @@ -0,0 +1,172 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.helper; + +import com.ifish.util.IfishUtil; +import java.util.Iterator; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Component; + +/** + * redis缓存服务器所有接口方法 + * + * @author Administrator + */ +@Component +public class RedisHelper implements RedisHelperI { + + @Autowired + private StringRedisTemplate redis; + + /* + *获取缓存值 + */ + @Override + public String getRedis(String key) { + try { + String result = redis.opsForValue().get(key.toLowerCase()); + return result; + } catch (Exception e) { + return null; + } + } + + /* + *设置缓存(默认时间为1天) + */ + @Override + public void setRedis(String key, String value) { + if (value == null) { + return; + } + try { + redis.opsForValue().set(key.toLowerCase(), value, IfishUtil.CacheTime_DAYS, TimeUnit.DAYS); + } catch (Exception e) { + } + } + + /*设置自定义时效缓存 + *key 缓存名称,value缓存值(string),time(保存时间),unit(时间类型) + */ + @Override + public void setRedis(String key, String value, int time, TimeUnit unit) { + if (value == null) { + return; + } + try { + redis.opsForValue().set(key.toLowerCase(), value, time, unit); + } catch (Exception e) { + } + } + + /* + *设置按天时效缓存 + */ + @Override + public void setRedisToDAYS(String key, String value) { + if (value == null) { + return; + } + try { + redis.opsForValue().set(key.toLowerCase(), value, IfishUtil.CacheTime_DAYS, TimeUnit.DAYS); + } catch (Exception e) { + } + } + + /* + *设置按时时效缓存 + */ + @Override + public void setRedisToHOURS(String key, String value) { + if (value == null) { + return; + } + try { + redis.opsForValue().set(key.toLowerCase(), value, IfishUtil.CacheTime_HOURS, TimeUnit.HOURS); + } catch (Exception e) { + } + } + + /* + *设置按分时效缓存 + */ + @Override + public void setRedisToMINUTES(String key, String value) { + if (value == null) { + return; + } + try { + redis.opsForValue().set(key.toLowerCase(), value, IfishUtil.CacheTime_MINUTES, TimeUnit.MINUTES); + } catch (Exception e) { + } + } + + /* + *设置按秒时效缓存 + */ + @Override + public void setRedisToSECONDS(String key, String value) { + if (value == null) { + return; + } + try { + redis.opsForValue().set(key.toLowerCase(), value, IfishUtil.CacheTime_SECONDS, TimeUnit.SECONDS); + } catch (Exception e) { + } + } + + /* + *删除缓存值 + */ + @Override + public void deleteRedis(String key) { + try { + redis.delete(key.toLowerCase()); + } catch (Exception e) { + } + } + + /* + *删除带前缀的批量缓存 + *tagkey 缓存前缀 + *如省份缓存 province:10,前缀为province + */ + @Override + public void delRedisByTagKey(String tagkey) { + try { + Set set = redis.keys(tagkey.toLowerCase() + "*"); + Iterator it = set.iterator(); + while (it.hasNext()) { + String keyStr = it.next(); + redis.delete(keyStr); + } + } catch (Exception e) { + } + } + + /* + * 删除当前缓存数据库所有的key + * 排除系数设置缓存 + */ + @Override + public void deleteDBRedis() { + try { + Set set = redis.keys("*"); + Iterator it = set.iterator(); + while (it.hasNext()) { + String keyStr = it.next(); + //排除系数设置缓存 + if (!keyStr.contains("recommendsetting:")) { + redis.delete(keyStr); + } + } + } catch (Exception e) { + } + } +} diff --git a/src/main/java/com/ifish/helper/RedisHelperI.java b/src/main/java/com/ifish/helper/RedisHelperI.java new file mode 100644 index 0000000..0faa9cb --- /dev/null +++ b/src/main/java/com/ifish/helper/RedisHelperI.java @@ -0,0 +1,69 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.helper; + +import java.util.concurrent.TimeUnit; + +/** + * redis缓存服务器所有接口方法 + * + * @author Administrator + */ +public interface RedisHelperI { + + /* + *删除带前缀的批量缓存 + *tagkey 缓存前缀 + *如省份缓存 province:10,前缀为province + */ + void delRedisByTagKey(String tagkey); + + /* + *删除缓存值 + */ + void deleteRedis(String key); + + /* + *删除当前缓存数据库所有的key + */ + void deleteDBRedis(); + + /* + *获取缓存值 + */ + String getRedis(String key); + + /* + *设置缓存(有效时间默认为1天) + */ + void setRedis(String key, String value); + + /*设置自定义时效缓存 + *key 缓存名称,value缓存值(string),time(保存时间),unit(时间类型) + */ + void setRedis(String key, String value, int time, TimeUnit unit); + + /* + *设置按天时效缓存 + */ + void setRedisToDAYS(String key, String value); + + /* + *设置按时时效缓存 + */ + void setRedisToHOURS(String key, String value); + + /* + *设置按分时效缓存 + */ + void setRedisToMINUTES(String key, String value); + + /* + *设置按秒时效缓存 + */ + void setRedisToSECONDS(String key, String value); + +} diff --git a/src/main/java/com/ifish/helper/UserHelper.java b/src/main/java/com/ifish/helper/UserHelper.java new file mode 100644 index 0000000..703f4e8 --- /dev/null +++ b/src/main/java/com/ifish/helper/UserHelper.java @@ -0,0 +1,473 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.helper; + +import com.ifish.API.GwellApi; +import com.ifish.bean.Tbl_Device; +import com.ifish.bean.Tbl_Device_User; +import com.ifish.bean.Tbl_HardWare_Type; +import com.ifish.bean.Tbl_User; +import com.ifish.bean.Tbl_Vender; +import com.ifish.enums.GwellEnum; +import com.ifish.enums.ResultEnum; +import com.ifish.mapper.Tbl_Hardware_Type_Mapper; +import com.ifish.mapper.Tbl_User_Mapper; +import com.ifish.util.IfishUtil; +import com.ifish.util.RedisKey; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * + * @author Administrator + */ +@Component +public class UserHelper implements UserHelperI { + + /** + * redis缓存服务器方法接口 + */ + @Autowired + private RedisHelperI redisHelperI; + + /** + * 所有tbl_user表的操作方法接口 + */ + @Autowired + private Tbl_User_Mapper tbl_User_Mapper; + + @Autowired + private DeviceHelperI deviceHelperI; + + @Autowired + private HardWareTypeHelperI hardWareTypeHelperI; + + /** + * 登陆接口 + * + * @param user + * @return + */ + @Override + public Object login(Tbl_User user) { + try { + Tbl_User tmpUser = null; + //如果用户手机不为空,进行手机登陆 + if (StringUtils.isNotBlank(user.getPhoneNumber())) { + tmpUser = tbl_User_Mapper.getUserByPhoneNumber(user.getPhoneNumber()); + return checkUserPassword(tmpUser, user); + } //如果用户邮箱不为空,进行邮箱登陆 + else if (StringUtils.isNotBlank(user.getUserEmail())) { + tmpUser = tbl_User_Mapper.getUserByUserEmail(user.getPhoneNumber()); + return checkUserPassword(tmpUser, user); + } //如果用户手机邮箱都为空,用户ID不为空,则进行游客登陆 + else if (user.getUserId() != null && user.getUserId() > 0) { + tmpUser = getUserById(user.getUserId()); + return touristLogin(tmpUser); + } + //密码不正确 + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } catch (Exception e) { + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + } + + /** + * 根据用户ID从缓存中获取用户对象 + * + * @param userId + * @return + * @throws Exception + */ + @Override + public Tbl_User getUserById(Integer userId) throws Exception { + Tbl_User tmpUser = null; + String userKey = RedisKey.User_Key + userId; + String userString = redisHelperI.getRedis(userKey); + //1.从数据库或缓存中读取用户对象 + if (StringUtils.isNotBlank(userString)) { + tmpUser = (Tbl_User) IfishUtil.JsonToBean(userString, Tbl_User.class); + } else { + tmpUser = tbl_User_Mapper.getUserByUserId(userId + ""); + saveUserToRedis(tmpUser); + } + return tmpUser; + } + + /** + * 游客注册接口 + * + * @return + */ + @Override + public Object touristRegister() { + Tbl_User user = new Tbl_User(); + user.setUserType("0"); + int i = tbl_User_Mapper.insertUser(user); + Map result = new HashMap(); + if (i > 0 && user.getUserId() > 0) { + //4.1未注册技威,则注册获取code1,code2 + Map gwellMap = registUserGWell(user, false); + user = (Tbl_User) gwellMap.get("user"); + Integer updateInteger = tbl_User_Mapper.updateUser(user); + //如果修改失败,返回错误信息 + if (updateInteger <= 0) { + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + + try { + saveUserToRedis(user); + } catch (Exception e) { + } + + result.put("userId", user.getUserId()); + result.put("P2PVerifyCode1", user.getP2pverifyCode1()); + result.put("P2PVerifyCode2", user.getP2pverifyCode2()); + result.put("gwellUserID", user.getGwellUserid()); + return IfishUtil.returnJson(ResultEnum.success.getKey(), result); + } else { + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + } + + /** + * 邮箱和手机登陆用户,需要进行密码验证,游客登陆不需要 + * + * @param tmpUser + * @param user + * @return + * @throws Exception + */ + private Object checkUserPassword(Tbl_User tmpUser, Tbl_User user) throws Exception { + //2.如果都为空,则没有此用户,返回未注册信息 + if (tmpUser == null) { + //用户不存在 + return IfishUtil.returnJson(ResultEnum.warn202.getKey(), ""); + } + //3.验证密码是否正确 + if (tmpUser.getUserPassword().equals(user.getUserPassword())) { + //4.如果密码正确,确认是否更新用户信息 + + //是否更新 + boolean isUpdate = false; + + //4.1未注册技威,则注册获取code1,code2 + Map gwellMap = registUserGWell(tmpUser, isUpdate); + tmpUser = (Tbl_User) gwellMap.get("user"); + isUpdate = (Boolean) gwellMap.get("isUpdate"); + + //4.3登陆次数修改 + Integer logincount = tbl_User_Mapper.executeLoginUpdate(tmpUser.getUserId(), user.getLoginType()); + //修改失败,返回错误信息 + if (logincount <= 0) { + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + //4.4验证是否需要修改技威等信息,如果需要则进行修改 + if (isUpdate) { + Integer updateInteger = tbl_User_Mapper.updateUser(tmpUser); + //如果修改失败,返回错误信息 + if (updateInteger <= 0) { + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + saveUserToRedis(tmpUser); + } + + //4.5 获取用户数据 + Map userMap = getUserMap(tmpUser); + //4.8获取用户绑定设备信息和摄像头信息 + Map deviceMap = getDeviceList(tmpUser); + Map dataMap = new HashMap(); + dataMap.put("user", userMap); + dataMap.put("device", deviceMap.get("list")); + dataMap.put("camera", deviceMap.get("list2")); + return IfishUtil.returnJson(ResultEnum.success.getKey(), dataMap); + } else { + //密码不正确 + return IfishUtil.returnJson(ResultEnum.warn204.getKey(), ""); + } + } + + /** + * 游客登陆接口 + * + * @param tmpUser + * @return + * @throws Exception + */ + private Object touristLogin(Tbl_User tmpUser) throws Exception { + //2.如果为空,则没有此用户,返回未注册信息 + if (tmpUser == null) { + //用户不存在 + return IfishUtil.returnJson(ResultEnum.warn202.getKey(), ""); + } + + //是否更新 + boolean isUpdate = false; + + //4.1未注册技威,则注册获取code1,code2 + Map gwellMap = registUserGWell(tmpUser, isUpdate); + tmpUser = (Tbl_User) gwellMap.get("user"); + isUpdate = (Boolean) gwellMap.get("isUpdate"); + + //4.4验证是否需要修改技威等信息,如果需要则进行修改 + if (isUpdate) { + Integer updateInteger = tbl_User_Mapper.updateUser(tmpUser); + //如果修改失败,返回错误信息 + if (updateInteger <= 0) { + return IfishUtil.returnJson(ResultEnum.fail101.getKey(), ""); + } + saveUserToRedis(tmpUser); + } + + //4.5 获取用户数据 + Map userMap = getUserMap(tmpUser); + //4.8获取用户绑定设备信息和摄像头信息 + Map deviceMap = getDeviceList(tmpUser); + Map dataMap = new HashMap(); + dataMap.put("user", userMap); + dataMap.put("device", deviceMap.get("list")); + dataMap.put("camera", deviceMap.get("list2")); + return IfishUtil.returnJson(ResultEnum.success.getKey(), dataMap); + + } + + /** + * 未注册技威,则注册获取code1,code2 + * + * @param tmpUser + * @param isUpdate + * @return + */ + private Map registUserGWell(Tbl_User tmpUser, boolean isUpdate) { + //4.1未注册技威,则注册获取code1,code2 + if (StringUtils.isBlank(tmpUser.getIsRegisterGwell()) || tmpUser.getIsRegisterGwell().equals("0")) { + String code = ""; + //如果有手机用手机号注册,否则用用户ID注册 + if (StringUtils.isBlank(tmpUser.getPhoneNumber())) { + code = tmpUser.getUserId() + ""; + } else { + code = tmpUser.getPhoneNumber(); + } + //注册技威 + Map map = GwellApi.Register(code); + String result = map.get("result"); + if (result != null) { + //注册成功 + if (result.equals(GwellEnum.success.getKey())) { + String P2PVerifyCode1 = map.get("P2PVerifyCode1"); + String P2PVerifyCode2 = map.get("P2PVerifyCode2"); + String gwellUserID = map.get("UserID"); + tmpUser.setIsRegisterGwell("1"); + tmpUser.setP2pverifyCode1(P2PVerifyCode1); + tmpUser.setP2pverifyCode2(P2PVerifyCode2); + tmpUser.setGwellUserid(gwellUserID); + isUpdate = true; + } //已经注册过 + else if (GwellEnum.repeat.getKey().equals(result)) { + tmpUser.setIsRegisterGwell("1"); + isUpdate = true; + } + } + }//已经注册过技威 + else if (tmpUser.getIsRegisterGwell().equals("1")) { + //code1和code2为空则重新登陆获取 + String P2PVerifyCode1 = tmpUser.getP2pverifyCode1(); + String P2PVerifyCode2 = tmpUser.getP2pverifyCode2(); + String gwellUserID = tmpUser.getGwellUserid(); + if (P2PVerifyCode1.equals("") || P2PVerifyCode2.equals("") || gwellUserID.equals("")) { + Map map = GwellApi.Login(tmpUser.getPhoneNumber()); + String result = map.get("result"); + //登陆成功 + if (result != null && result.equals(GwellEnum.success.getKey())) { + P2PVerifyCode1 = map.get("P2PVerifyCode1"); + P2PVerifyCode2 = map.get("P2PVerifyCode2"); + gwellUserID = map.get("UserID"); + tmpUser.setP2pverifyCode1(P2PVerifyCode1); + tmpUser.setP2pverifyCode2(P2PVerifyCode2); + tmpUser.setGwellUserid(gwellUserID); + isUpdate = true; + } + } + } + Map resultMap = new HashMap(); + resultMap.put("user", tmpUser); + resultMap.put("isUpdate", isUpdate); + return resultMap; + } + + /** + * 登录成功,返回给App数据 + * + * @param tmpUser + * @return + */ + private Map getUserMap(Tbl_User tmpUser) { + //登录成功,返回给App数据 + Map userMap = new HashMap(); + userMap.put("userId", tmpUser.getUserId().toString()); + //如果手机号不为空 + if (StringUtils.isNotBlank(tmpUser.getPhoneNumber())) { + userMap.put("phoneNumber", tmpUser.getPhoneNumber()); + } + //如果邮箱不为空 + if (StringUtils.isNotBlank(tmpUser.getUserEmail())) { + userMap.put("userEmail", tmpUser.getUserEmail()); + } + userMap.put("nickName", tmpUser.getNickName()); + userMap.put("userSex", tmpUser.getUserSex()); + userMap.put("userImg", tmpUser.getUserImg()); + userMap.put("P2PVerifyCode1", tmpUser.getP2pverifyCode1()); + userMap.put("P2PVerifyCode2", tmpUser.getP2pverifyCode2()); + userMap.put("gwellUserID", tmpUser.getGwellUserid()); + userMap.put("userType", tmpUser.getUserType()); + if (tmpUser.getUpdateTime() != null) { + userMap.put("updateTime", IfishUtil.format(tmpUser.getUpdateTime())); + } + + return userMap; + } + + /** + * 获取用户绑定设备信息 + * + * @param tmpUser + * @return + */ + private Map getDeviceList(Tbl_User tmpUser) throws Exception { + //设备信息 + List list = new ArrayList(); + //摄像头信息 + List list2 = new ArrayList(); + //获取用户拥有设备 + List deviceUserList = deviceHelperI.getDeviceUsersByUserId(tmpUser.getUserId()); + List deviceIds = new ArrayList(); + List cameraIds = new ArrayList(); + for (Tbl_Device_User deviceUser : deviceUserList) { + Tbl_Device device = deviceHelperI.getDeviceById(deviceUser.getDeviceId()); + if (device.getIsCamera().equals("1")) { + cameraIds.add(device.getDeviceId()); + list2.add(getCameraInfo(device, deviceUser)); + } else { + deviceIds.add(device.getDeviceId()); + //封装设备返回信息 + list.add(getDeviceInfo(device, deviceUser)); + } + + } + + Map map = new HashMap(); + map.put("list", list); + map.put("list2", list2); + return map; + } + + /** + * 封装设备返回信息 + * + * @param device + * @param deviceUser + * @return + */ + @Override + public Map getDeviceInfo(Tbl_Device device, Tbl_Device_User deviceUser) throws Exception { + Map deviceMap = new HashMap(); + deviceMap.put("userId", deviceUser.getUserId()); + deviceMap.put("deviceId", deviceUser.getDeviceId()); + deviceMap.put("isMaster", deviceUser.getIsMaster()); + deviceMap.put("showName", deviceUser.getShowName()); + deviceMap.put("macAddress", device.getMacAddress()); + deviceMap.put("isBlacklist", device.getIsBlacklist()); + deviceMap.put("customIconName", deviceUser.getCustomIconName()); + deviceMap.put("customShowName", deviceUser.getCustomShowName()); + deviceMap.put("deviceIp", device.getDeviceIp()); + deviceMap.put("loginTime", device.getLoginTime()); + if (device.getBrandCode() != null && device.getBrandCode().equals("YUEM") && device.getCreateTime().before(IfishUtil.StrToDate("2016-04-26"))) { + //是否显示预警推送 + deviceMap.put("isPushWendu", "0"); + } else { + //是否显示预警推送 + deviceMap.put("isPushWendu", "1"); + } + //控制方案 + String type = device.getHardwareType(); + if (type != null) { + Tbl_HardWare_Type hardwareType = hardWareTypeHelperI.getHardwareTypeByTypeCode(type); + if (hardwareType != null) { + //设备类型 + deviceMap.put("type", type); + //有无工作模式 + deviceMap.put("isWorkModel", hardwareType.getIsWorkModel()); + //控制信息 + deviceMap.put("controlAmount", hardwareType.getControlAmount()); + deviceMap.put("timerAmount", hardwareType.getTimerAmount()); + //背光/柜灯 + deviceMap.put("isLightness", hardwareType.getIsLightness()); + deviceMap.put("isSarkLamp", hardwareType.getIsSarkLamp()); + //自定义图标 + deviceMap.put("isCustomIcon", hardwareType.getIsCustomIcon()); + deviceMap.put("iconLink", hardwareType.getIconLink()); + deviceMap.put("allIconName", hardwareType.getAllIconName()); + deviceMap.put("allShowName", hardwareType.getAllShowName()); + deviceMap.put("defaultIconName", hardwareType.getDefaultIconName()); + deviceMap.put("defaultShowName", hardwareType.getDefaultShowName()); + deviceMap.put("updateTime", hardwareType.getUpdateTime()); + //换水提醒 + deviceMap.put("todayRemind", device.getTodayRemind()); + deviceMap.put("waterRemind", device.getWaterRemind()); + deviceMap.put("remindDate", device.getRemindDate() != null ? IfishUtil.format1(device.getRemindDate()) : ""); + deviceMap.put("remindCycle", device.getRemindCycle() != null ? device.getRemindCycle() : ""); + } + } + //厂家 + if (device.getBrandCode() != null) { + //厂家 + Tbl_Vender venderList = new Tbl_Vender(); + venderList = hardWareTypeHelperI.getVenderListByBrandCode(device.getBrandCode()); + deviceMap.put("venderList", venderList); + } else { + //默认爱鱼奇 + Tbl_Vender defaultVenderList = new Tbl_Vender(); + defaultVenderList = hardWareTypeHelperI.getVenderListByBrandCode("AYQ"); + deviceMap.put("venderList", defaultVenderList); + } + return deviceMap; + } + + /** + * 封装摄像头返回信息 + * + * @param camera + * @param cameraUser + * @param device + * @param deviceUser + * @return + */ + public Map getCameraInfo(Tbl_Device camera, Tbl_Device_User cameraUser) { + Map cameraMap = new HashMap(); + cameraMap.put("cameraId", camera.getDeviceId()); + cameraMap.put("isMaster", cameraUser.getIsMaster()); + cameraMap.put("isLook", cameraUser.getIsLook()); + cameraMap.put("isActive", StringUtils.isNotBlank(camera.getActiveCode()) ? "1" : "0"); + cameraMap.put("showName", cameraUser.getShowName()); + return cameraMap; + } + + /** + * 将用户对象保存至redis缓存中,有效期1天 + * + * @param user + */ + private void saveUserToRedis(Tbl_User user) throws Exception { + String key = RedisKey.User_Key + user.getUserId(); + redisHelperI.setRedis(key, IfishUtil.ObjectToJson(user)); + } + +} diff --git a/src/main/java/com/ifish/helper/UserHelperI.java b/src/main/java/com/ifish/helper/UserHelperI.java new file mode 100644 index 0000000..16e6de6 --- /dev/null +++ b/src/main/java/com/ifish/helper/UserHelperI.java @@ -0,0 +1,53 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.helper; + +import com.ifish.bean.Tbl_Device; +import com.ifish.bean.Tbl_Device_User; +import com.ifish.bean.Tbl_User; +import java.util.Map; + +/** + * + * @author Administrator + */ +public interface UserHelperI { + + /** + * 登陆接口 + * + * @param user + * @return + */ + public Object login(Tbl_User user); + + /** + * 根据用户Id获取用户信息 + * + * @param userId + * @return + * @throws java.lang.Exception + */ + public Tbl_User getUserById(Integer userId) throws Exception; + + /** + * 游客注册接口 + * + * @return + */ + public Object touristRegister(); + + /** + * 封装设备返回信息 + * + * @param device + * @param deviceUser + * @return + * @throws java.lang.Exception + */ + public Map getDeviceInfo(Tbl_Device device, Tbl_Device_User deviceUser) throws Exception; + +} diff --git a/src/main/java/com/ifish/mapper/Tbl_Device_Mapper.java b/src/main/java/com/ifish/mapper/Tbl_Device_Mapper.java new file mode 100644 index 0000000..4096535 --- /dev/null +++ b/src/main/java/com/ifish/mapper/Tbl_Device_Mapper.java @@ -0,0 +1,199 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.mapper; + +import com.ifish.bean.Tbl_Activa_Code; +import com.ifish.bean.Tbl_Device; +import com.ifish.bean.Tbl_Device_Statistics; +import com.ifish.bean.Tbl_Device_User; +import java.util.List; +import org.apache.ibatis.annotations.Delete; +import org.apache.ibatis.annotations.InsertProvider; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.SelectKey; +import org.apache.ibatis.annotations.Update; +import org.apache.ibatis.annotations.UpdateProvider; + +/** + * + * @author Administrator + */ +public interface Tbl_Device_Mapper { + + /** + * 根据设备ID获取设备详情 + * + * @param deviceid + * @return + */ + @Select("SELECT device_id,server_ip,device_ip,is_camera,mac_address,login_time,is_blacklist,hardware_type,on_off," + + "today_remind,water_remind,remind_cycle,remind_date,factory_code,brand_code,create_time,active_code,active_time,update_time,camera_id from tbl_device WHERE device_id= #{deviceid}") + Tbl_Device getDeviceById(@Param("deviceid") Integer deviceid); + + /** + * 根据摄像头ID获取设备详情 + * + * @param deviceid + * @return + */ + @Select("SELECT device_id,server_ip,device_ip,is_camera,mac_address,login_time,is_blacklist,hardware_type,on_off," + + "today_remind,water_remind,remind_cycle,remind_date,factory_code,brand_code,create_time,active_code,active_time,update_time,camera_id from tbl_device WHERE camera_id= #{cameraID}") + Tbl_Device getDeviceByCameraId(@Param("cameraID") String cameraID); + + /** + * 根据设备ID获取设备详情 + * + * @param deviceid + * @return + */ + @Select("SELECT device_id,server_ip,device_ip,is_camera,mac_address,login_time,is_blacklist,hardware_type,on_off," + + "today_remind,water_remind,remind_cycle,remind_date,factory_code,brand_code,create_time,active_code,active_time,update_time,camera_id from tbl_device WHERE mac_address= #{mac_address}") + Tbl_Device getDeviceByMacAddress(@Param("mac_address") String macAddress); + + /** + * 根据用户ID获取用户绑定设备集合 + * + * @param userid + * @param deviceId + * @return + */ + @Select("SELECT id,user_id,device_id,is_master,show_name,create_time,update_time,custom_icon_name,custom_show_name,is_look,is_live from tbl_device_user WHERE user_id = #{userid}") + List getDeviceUsersByUserId(@Param("userid") Integer userid); + + /** + * 根据设备ID和用户ID获取设备与其他用户的关系 + * + * @param userid + * @param deviceId + * @return + */ + @Select("SELECT id,user_id,device_id,is_master,show_name,create_time,update_time,custom_icon_name,custom_show_name,is_look,is_live from tbl_device_user WHERE user_id <> ${userid} AND device_id = #{deviceid}") + List getOtherDeviceUsersByOtherUserIdAndDeviceId(@Param("userid") Integer userid, @Param("deviceid") Integer deviceId); + + /** + * 根据设备ID和用户ID获取设备与用户的关系 + * + * @param userid + * @param deviceId + * @return + */ + @Select("SELECT id,user_id,device_id,is_master,show_name,create_time,update_time,custom_icon_name,custom_show_name,is_look,is_live from tbl_device_user WHERE user_id = #{userid} AND device_id = #{deviceid}") + Tbl_Device_User getDeviceUsersByUserIdAndDeviceId(@Param("userid") Integer userid, @Param("deviceid") Integer deviceId); + + /** + * 根据设备ID查询此设备关联的所有用户 + * + * @param deviceId + * @return + */ + @Select("SELECT id,user_id,device_id,is_master,show_name,create_time,update_time,custom_icon_name,custom_show_name,is_look,is_live from tbl_device_user WHERE device_id = #{deviceid}") + List getDeviceUsersByDeviceId(@Param("deviceid") Integer deviceId); + + /** + * 修改用户和设备关系表数据 + * + * @param device_User + * @return + */ + @UpdateProvider(method = "updateTblDeviceUser", type = Tbl_Device_MapperSql.class) + int updateTblDeviceUser(@Param("deviceUser") Tbl_Device_User device_User); + + /** + * 删除设备和用户的关系 + * + * @param id + * @return + */ + @Delete("DELETE from tbl_device_user where id = #{id}") + int deleteDeviceUserById(@Param("id") Integer id); + + /** + * 根据设备ID查询设备统计信息 + * + * @param deviceid + * @return + */ + @Select("SELECT id,device_id,mac_address,login_count,login_time,first_activate,create_time,is_charge,sdk_version,sdk_time,create_date,is_upgrade,upgrade_version," + + "upgrade_time,authorize_time,create_code,MCU_count,module_count,router_count,server_count,server_try_count,software_version,hardware_type,factory_code,brand_code FROM tbl_device_statistics WHERE device_id=#{deviceid}") + Tbl_Device_Statistics getDevStatisticsByDeviceId(@Param("deviceid") Integer deviceid); + + /** + * 插入一条设备统计信息 + * + * @param device_Statistics + * @return + */ + @InsertProvider(type = Tbl_Device_MapperSql.class, method = "insertDeviceStatistics") + @SelectKey(statement = "select @@IDENTITY as id", keyProperty = "deviceStatistics.id", keyColumn = "id", before = false, resultType = int.class) + Integer insertDeviceStatistics(@Param("deviceStatistics") Tbl_Device_Statistics device_Statistics); + + /** + * 修改设备统计信息表 + * + * @param device_Statistics + * @return + */ + @UpdateProvider(type = Tbl_Device_MapperSql.class, method = "updateDeviceStatistics") + Integer updateDeviceStatistics(@Param("deviceStatistics") Tbl_Device_Statistics device_Statistics); + + /** + * 插入一条设备信息 + * + * @param device + * @return + */ + @InsertProvider(type = Tbl_Device_MapperSql.class, method = "insertDevice") + @SelectKey(statement = "select @@IDENTITY as device_id", keyProperty = "device.deviceId", keyColumn = "device_id", before = false, resultType = int.class) + Integer insertDevice(@Param("device") Tbl_Device device); + + /** + * 插入一套设备与用户关系数据 + * + * @param deviceUser + * @return + */ + @InsertProvider(type = Tbl_Device_MapperSql.class, method = "insertDeviceUser") + @SelectKey(statement = "select @@IDENTITY as id", keyProperty = "deviceUser.id", keyColumn = "id", before = false, resultType = int.class) + Integer insertDeviceUser(@Param("deviceUser") Tbl_Device_User deviceUser); + + /** + * 根据ID删除设备信息数据(摄像头) + * + * @param id + * @return + */ + @Delete("DELETE from tbl_device where id = #{id}") + int deleteDeviceById(@Param("id") Integer id); + + /** + * 根据激活码查询激活码对象 + * + * @param activeCode + * @return + */ + @Select("SELECT active_code,batch_code,is_used,create_time FROM tbl_activa_code WHERE active_code = #{code}") + Tbl_Activa_Code getActiva_CodeByCode(@Param("code") String activeCode); + + /** + * 修改设备信息 + * + * @param device + * @return + */ + @UpdateProvider(type = Tbl_Device_MapperSql.class, method = "updateTbl_Device") + Integer updateTbl_Device(@Param("device") Tbl_Device device); + + /** + * 修改摄像头激活码信息为已使用 + * + * @param activa_Code + * @return + */ + @Update("UPDATE tbl_activa_code set is_used='1' WHERE active_code = #{code}") + Integer updateTblActivaCodeIsUse(@Param("code") String activa_Code); + +} diff --git a/src/main/java/com/ifish/mapper/Tbl_Device_MapperSql.java b/src/main/java/com/ifish/mapper/Tbl_Device_MapperSql.java new file mode 100644 index 0000000..77eb599 --- /dev/null +++ b/src/main/java/com/ifish/mapper/Tbl_Device_MapperSql.java @@ -0,0 +1,269 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.mapper; + +import com.ifish.bean.Tbl_Device; +import com.ifish.bean.Tbl_Device_Statistics; +import com.ifish.bean.Tbl_Device_User; +import org.apache.commons.lang3.StringUtils; +import org.apache.ibatis.annotations.Param; + +/** + * + * @author Administrator + */ +public class Tbl_Device_MapperSql { + + /** + * 修改设备和用户的表 + * + * @param device_User + * @return + */ + public String updateTblDeviceUser(@Param("deviceUser") Tbl_Device_User device_User) { + StringBuilder sb = new StringBuilder(); + + sb.append("UPDATE tbl_device_user SET "); + + if (device_User.getUserId() != null && device_User.getUserId() > 0) { + sb.append("user_id = #{deviceUser.userId}, "); + } + if (device_User.getDeviceId() != null && device_User.getDeviceId() > 0) { + sb.append("device_id = #{deviceUser.deviceId}, "); + } + if (StringUtils.isNotBlank(device_User.getIsMaster())) { + sb.append("is_master = #{deviceUser.isMaster}, "); + } + if (StringUtils.isNotBlank(device_User.getShowName())) { + sb.append("show_name = #{deviceUser.showName}, "); + } + if (device_User.getCreateTime() != null && StringUtils.isNotBlank(device_User.getCreateTime().toString())) { + sb.append("create_time = #{deviceUser.createTime}, "); + } + if (StringUtils.isNotBlank(device_User.getCustomIconName())) { + sb.append("custom_icon_name = #{deviceUser.customIconName}, "); + } + if (StringUtils.isNotBlank(device_User.getCustomShowName())) { + sb.append("custom_show_name = #{deviceUser.customShowName}, "); + } + if (StringUtils.isNotBlank(device_User.getIsLook())) { + sb.append("is_look = #{deviceUser.isLook}, "); + } + if (StringUtils.isNotBlank(device_User.getIsLive())) { + sb.append("is_live = #{deviceUser.isLive}, "); + } + sb.append("update_time = now() "); + sb.append(" WHERE id = #{deviceUser.id}"); + return sb.toString(); + } + + /** + * 插入一条设备统计信息表 + * + * @param device_Statistics + * @return + */ + public String insertDeviceStatistics(@Param("deviceStatistics") Tbl_Device_Statistics device_Statistics) { + StringBuilder sb = new StringBuilder(); + + sb.append("INSERT tbl_device_statistics(device_id,mac_address,login_count,login_time,first_activate,create_time,is_charge,sdk_version,sdk_time,create_date,authorize_time,create_code,hardware_type,factory_code,brand_code)"); + sb.append("values(#{deviceStatistics.deviceId},#{deviceStatistics.macAddress},#{deviceStatistics.loginCount},#{deviceStatistics.loginTime},#{deviceStatistics.firstActivate},#{deviceStatistics.createTime},"); + sb.append("#{deviceStatistics.isCharge},#{deviceStatistics.sdkVersion},#{deviceStatistics.sdkTime},#{deviceStatistics.createDate},#{deviceStatistics.authorizeTime},#{deviceStatistics.createCode},"); + sb.append("#{deviceStatistics.hardwareType},#{deviceStatistics.factoryCode},#{deviceStatistics.brandCode})"); + return sb.toString(); + } + + /** + * 修改设备统计信息表 + * + * @param device_Statistics + * @return + */ + public String updateDeviceStatistics(@Param("deviceStatistics") Tbl_Device_Statistics device_Statistics) { + StringBuilder sb = new StringBuilder(); + + sb.append("UPDATE tbl_device_statistics SET "); + + if (device_Statistics.getDeviceId() > 0) { + sb.append("device_id = #{deviceStatistics.deviceId}, "); + } + if (StringUtils.isNotBlank(device_Statistics.getMacAddress())) { + sb.append("mac_address = #{deviceStatistics.macAddress}, "); + } + if (device_Statistics.getLoginCount() > 0) { + sb.append("login_count = #{deviceStatistics.loginCount}, "); + } + if (device_Statistics.getLoginTime() != null && StringUtils.isNotBlank(device_Statistics.getLoginTime().toString())) { + sb.append("login_time= #{deviceStatistics.loginTime}, "); + } + if (device_Statistics.getFirstActivate() != null && StringUtils.isNotBlank(device_Statistics.getFirstActivate().toString())) { + sb.append("first_activate= #{deviceStatistics.firstActivate}, "); + } + if (device_Statistics.getCreateTime() != null && StringUtils.isNotBlank(device_Statistics.getCreateTime().toString())) { + sb.append("create_time= #{deviceStatistics.createTime}, "); + } + if (StringUtils.isNotBlank(device_Statistics.getIsCharge())) { + sb.append("is_charge = #{deviceStatistics.isCharge}, "); + } + if (StringUtils.isNotBlank(device_Statistics.getSdkVersion())) { + sb.append("sdk_version = #{deviceStatistics.sdkVersion}, "); + } + if (device_Statistics.getSdkTime() != null && StringUtils.isNotBlank(device_Statistics.getSdkTime().toString())) { + sb.append("sdk_time= #{deviceStatistics.sdkTime}, "); + } + if (device_Statistics.getCreateDate() != null && StringUtils.isNotBlank(device_Statistics.getCreateDate().toString())) { + sb.append("create_date= #{deviceStatistics.createDate}, "); + } + if (StringUtils.isNotBlank(device_Statistics.getIsUpgrade())) { + sb.append("is_upgrade = #{deviceStatistics.isUpgrade}, "); + } + if (StringUtils.isNotBlank(device_Statistics.getUpgradeVersion())) { + sb.append("upgrade_version = #{deviceStatistics.upgradeVersion}, "); + } + if (device_Statistics.getUpgradeTime() != null && StringUtils.isNotBlank(device_Statistics.getUpgradeTime().toString())) { + sb.append("upgrade_time= #{deviceStatistics.upgradeTime}, "); + } + if (device_Statistics.getAuthorizeTime() != null && StringUtils.isNotBlank(device_Statistics.getAuthorizeTime().toString())) { + sb.append("authorize_time= #{deviceStatistics.authorizeTime}, "); + } + if (StringUtils.isNotBlank(device_Statistics.getCreateCode())) { + sb.append("create_code = #{deviceStatistics.createCode}, "); + } + if (device_Statistics.getMcuCount() != null && device_Statistics.getMcuCount() > 0) { + sb.append("mcu_count = #{deviceStatistics.mcuCount}, "); + } + if (device_Statistics.getModuleCount() != null && device_Statistics.getModuleCount() > 0) { + sb.append("module_count = #{deviceStatistics.moduleCount}, "); + } + if (device_Statistics.getRouterCount() != null && device_Statistics.getRouterCount() > 0) { + sb.append("router_count = #{deviceStatistics.routerCount}, "); + } + if (device_Statistics.getServerCount() != null && device_Statistics.getServerCount() > 0) { + sb.append("server_count = #{deviceStatistics.serverCount}, "); + } + if (device_Statistics.getServerTryCount() != null && device_Statistics.getServerTryCount() > 0) { + sb.append("server_try_count = #{deviceStatistics.serverTryCount}, "); + } + if (StringUtils.isNotBlank(device_Statistics.getSoftwareVersion())) { + sb.append("software_version = #{deviceStatistics.softwareVersion}, "); + } + if (StringUtils.isNotBlank(device_Statistics.getHardwareType())) { + sb.append("hardware_type = #{deviceStatistics.hardwareType}, "); + } + if (StringUtils.isNotBlank(device_Statistics.getFactoryCode())) { + sb.append("factory_code = #{deviceStatistics.factoryCode}, "); + } + if (StringUtils.isNotBlank(device_Statistics.getBrandCode())) { + sb.append("brand_code = #{deviceStatistics.brandCode}, "); + } + if (sb.lastIndexOf(",") == sb.length() - 2) { + sb.deleteCharAt(sb.length() - 2); + } + sb.append(" WHERE id = #{deviceStatistics.id}"); + return sb.toString(); + } + + /** + * 插入一条设备信息 + * + * @param device + * @return + */ + public String insertDevice(@Param("device") Tbl_Device device) { + StringBuilder sb = new StringBuilder(); + + sb.append("INSERT INTO tbl_device(server_ip,device_ip,is_camera,mac_address,login_time,is_blacklist,hardware_type,on_off,today_remind,water_remind,remind_date,remind_cycle,factory_code,brand_code,"); + sb.append("create_time,active_code,active_time,update_time,camera_id) VALUES(#{device.serverIp},#{device.deviceIp},#{device.isCamera},#{device.macAddress},#{device.loginTime},#{device.isBlacklist},#{device.hardwareType},#{device.onOff},"); + sb.append("#{device.todayRemind},#{device.waterRemind},#{device.remindDate},#{device.remindCycle},#{device.factoryCode},#{device.brandCode},#{device.createTime},#{device.activeCode},#{device.activeTime},#{device.updateTime},#{device.cameraId})"); + + return sb.toString(); + } + + /** + * 插入设备和用户信息 + * + * @param deviceUser + * @return + */ + public String insertDeviceUser(@Param("deviceUser") Tbl_Device_User deviceUser) { + StringBuilder sb = new StringBuilder(); + + sb.append("INSERT INTO tbl_device_user (user_id,device_id,is_master,show_name,create_time,update_time,custom_icon_name,custom_show_name,is_look,is_live) VALUES("); + sb.append("#{deviceUser.userId},#{deviceUser.deviceId},#{deviceUser.isMaster},#{deviceUser.showName},#{deviceUser.createTime},#{deviceUser.updateTime},#{deviceUser.customIconName},#{deviceUser.customShowName},#{deviceUser.isLook},#{deviceUser.isLive})"); + + return sb.toString(); + } + + /** + * 修改设备信息 + * + * @param device + * @return + */ + public String updateTbl_Device(@Param("device") Tbl_Device device) { + StringBuilder sb = new StringBuilder(); + + sb.append("UPDATE tbl_device SET "); + if (StringUtils.isNotBlank(device.getServerIp())) { + sb.append("server_ip = #{device.serverIp}, "); + } + if (StringUtils.isNotBlank(device.getDeviceIp())) { + sb.append("device_ip = #{device.deviceIp}, "); + } + if (StringUtils.isNotBlank(device.getIsCamera())) { + sb.append("is_camera = #{device.isCamera}, "); + } + if (StringUtils.isNotBlank(device.getMacAddress())) { + sb.append("mac_address = #{device.macAddress}, "); + } + if (device.getLoginTime() != null && StringUtils.isNotBlank(device.getLoginTime().toString())) { + sb.append("login_time = #{device.loginTime}, "); + } + if (device.getRemindDate() != null && StringUtils.isNotBlank(device.getRemindDate().toString())) { + sb.append("remind_date = #{device.loginTime}, "); + } + if (StringUtils.isNotBlank(device.getIsBlacklist())) { + sb.append("is_blacklist = #{device.isBlacklist}, "); + } + if (StringUtils.isNotBlank(device.getHardwareType())) { + sb.append("hardware_type = #{device.hardwareType}, "); + } + if (StringUtils.isNotBlank(device.getOnOff())) { + sb.append("on_off = #{device.onOff}, "); + } + if (StringUtils.isNotBlank(device.getTodayRemind())) { + sb.append("today_remind = #{device.todayRemind}, "); + } + if (StringUtils.isNotBlank(device.getWaterRemind())) { + sb.append("water_remind = #{device.waterRemind}, "); + } + if (device.getRemindCycle() != null && device.getRemindCycle() > 0) { + sb.append("remind_cycle = #{device.remindCycle}, "); + } + if (StringUtils.isNotBlank(device.getFactoryCode())) { + sb.append("factory_code = #{device.factoryCode}, "); + } + if (StringUtils.isNotBlank(device.getBrandCode())) { + sb.append("brand_code = #{device.brandCode}, "); + } + if (StringUtils.isNotBlank(device.getCameraId())) { + sb.append("camera_id = #{device.cameraId}, "); + } + if (device.getCreateTime() != null && StringUtils.isNotBlank(device.getCreateTime().toString())) { + sb.append("create_time = #{device.createTime}, "); + } + if (device.getActiveTime() != null && StringUtils.isNotBlank(device.getActiveTime().toString())) { + sb.append("active_time = #{device.activeTime}, "); + } + + if (StringUtils.isNotBlank(device.getActiveCode())) { + sb.append("active_code = #{device.activeCode}, "); + } + sb.append("update_time = now() "); + sb.append(" WHERE device_id = #{device.deviceId}"); + return sb.toString(); + } +} diff --git a/src/main/java/com/ifish/mapper/Tbl_Hardware_Type_Mapper.java b/src/main/java/com/ifish/mapper/Tbl_Hardware_Type_Mapper.java new file mode 100644 index 0000000..47f7bd2 --- /dev/null +++ b/src/main/java/com/ifish/mapper/Tbl_Hardware_Type_Mapper.java @@ -0,0 +1,38 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.mapper; + +import com.ifish.bean.Tbl_HardWare_Type; +import com.ifish.bean.Tbl_Vender; +import java.util.Map; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +/** + * + * @author Administrator + */ +public interface Tbl_Hardware_Type_Mapper { + + /** + * 根据设备类型Code获取厂家设备类型详情 + * + * @param type + * @return + */ + @Select("select hardware_type,hardware_name,control_amount,timer_amount,is_work_model,is_custom_icon,all_icon_name,all_show_name,default_icon_name,default_show_name," + + "icon_link,is_lightness,is_sark_lamp,hardware_desc,update_time,create_time from tbl_hardware_type where hardware_type=#{type}") + Tbl_HardWare_Type getHardwareTypeByTypeCode(@Param("type") String type); + + /** + * 根据code获取厂家信息 + * + * @param code + * @return + */ + @Select("select brand_code,brand_name,brand_introduce,brand_logo from tbl_vender_list where brand_code=#{code}") + Tbl_Vender getVenderListByBrandCode(@Param("code") String code); +} diff --git a/src/main/java/com/ifish/mapper/Tbl_Live_Room_Mapper.java b/src/main/java/com/ifish/mapper/Tbl_Live_Room_Mapper.java new file mode 100644 index 0000000..c5ee5c7 --- /dev/null +++ b/src/main/java/com/ifish/mapper/Tbl_Live_Room_Mapper.java @@ -0,0 +1,112 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.mapper; + +import com.ifish.bean.LiveRoomPageInfo; +import com.ifish.bean.Tbl_Live_Message; +import com.ifish.bean.Tbl_Live_Room; +import java.util.List; +import org.apache.ibatis.annotations.Delete; +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.SelectKey; + +/** + * + * @author Administrator + */ +public interface Tbl_Live_Room_Mapper { + + /** + * 建立一个直播间 + */ + @Insert("INSERT INTO tbl_live_room (user_id,camera_id,room_name,room_desc,room_status,popularity_value,create_time,is_tuijian,tuijian_num,first_share) VALUES(" + + "#{liveroom.userId},#{liveroom.cameraId},#{liveroom.roomName},#{liveroom.roomDesc},#{liveroom.roomStatus},#{liveroom.popularityValue},now(),#{liveroom.isTuijian},#{liveroom.tuijianNum},#{liveroom.firstShare})") + @SelectKey(statement = "select @@IDENTITY as room_id", keyProperty = "liveroom.roomId", keyColumn = "room_id", before = false, resultType = int.class) + Integer insertLiveRoom(@Param("liveroom") Tbl_Live_Room liveRoom); + + /** + * 插入一条直播间评论 + * + * @param live_Message + * @return + */ + @Insert("INSERT INTO TBL_LIVE_MESSAGE (room_id,user_id,as_user_id,message_content,create_time) VALUES (#{livemessage.roomId},#{livemessage.userId},#{livemessage.asUserId},#{livemessage.messageContent},#{livemessage.createTime})") + @SelectKey(statement = "select @@IDENTITY as message_id", keyProperty = "livemessage.messageId", keyColumn = "message_id", before = false, resultType = int.class) + Integer insertLiveMessage(@Param("livemessage") Tbl_Live_Message live_Message); + + /** + * 根据用户ID查询直播间(每个用户只有一个直播间) + * + * @param UserId + * @return + */ + @Select("SELECT room_id,user_id,camera_id,room_name,room_desc,room_status,popularity_value,is_tuijian,tuijian_num,first_share FROM TBL_LIVE_ROOM WHERE user_id = #{userid}") + Tbl_Live_Room getLive_RoomByUserId(@Param("userid") Integer UserId); + + /** + * 查询直播间总赞数 + * + * @param roomID + * @return + */ + @Select("select count(*) from tbl_live_room_zan where room_id=#{roomid} ") + Integer getLiveRoomZanCountByRoomId(@Param("roomid") Integer roomID); + + /** + * 查询某个用户是否点赞了某个直播间 + * + * @param roomID + * @param userID + * @return + */ + @Select("SELECT COUNT(1) FROM TBL_LIVE_ROOM_ZAN WHERE ROOM_ID = #{roomid} AND USER_ID = #{userid}") + Integer IsZan(@Param("roomid") Integer roomID, @Param("userid") Integer userID); + + /** + * 取消点赞 + * + * @param roomID + * @param userID + * @return + */ + @Delete("DELETE FROM TBL_LIVE_ROOM_ZAN WHERE ROOM_ID = #{roomid} AND USER_ID = #{userid}") + Integer cancelZan(@Param("roomid") Integer roomID, @Param("userid") Integer userID); + + /** + * 执行点赞 + * + * @param roomID + * @param userID + * @return + */ + @Insert("INSERT INTO TBL_LIVE_ROOM_ZAN(ROOM_ID,USER_ID,CREATE_TIME) VALUES (#{roomid},#{userid},NOW())") + Integer ImplementZan(@Param("roomid") Integer roomID, @Param("userid") Integer userID); + + /** + * 根据房间ID查询直播间信息 + * + * @param roomid + * @return + */ + @Select("SELECT ROOM_ID,USER_ID,CAMERA_ID,ROOM_NAME,ROOM_DESC,ROOM_STATUS,POPULARITY_VALUE,CREATE_TIME,IS_TUIJIAN,TUIJIAN_NUM,FIRST_SHARE FROM TBL_LIVE_ROOM WHERE ROOM_ID = #{roomid}") + Tbl_Live_Room getTbl_Live_RoomById(@Param("roomid") Integer roomid); + + /** + * 根据经纬度获取直播间集合 + * + * @return + */ + @Select("select l.room_id AS roomId,u.user_id AS userId,u.user_type AS userType,u.nick_name AS nickName,u.user_img AS userImg,u.login_time AS loginTime,c.camera_id AS cameraId," + + "l.room_name AS roomName,l.room_desc AS roomDesc,l.popularity_value AS popularityValue,(TO_DAYS(NOW())-TO_DAYS(l.create_time)) AS numberDays," + + "round(6378.138*2*asin(sqrt(pow(sin((${lat}*pi()/180-u.latitude*pi()/180)/2),2)+cos(${lat}*pi()/180)*cos(u.latitude*pi()/180)* pow(sin((${long}*pi()/180-u.longitude*pi()/180)/2),2)))*1000) AS distance " + + "from tbl_user u LEFT JOIN tbl_camera_user c ON u.user_id=c.user_id " + + "LEFT JOIN tbl_live_room l on c.user_id=l.user_id " + + "WHERE c.is_live=1 AND l.room_status=1 HAVING distance IS NOT NULL" + + " ORDER BY distance ASC LIMIT 5") + List getLiveRoomListByLongLat(@Param("long") Double longitude, @Param("lat") Double latitude); +} diff --git a/src/main/java/com/ifish/mapper/Tbl_Push_List_Mapper.java b/src/main/java/com/ifish/mapper/Tbl_Push_List_Mapper.java new file mode 100644 index 0000000..5c5e970 --- /dev/null +++ b/src/main/java/com/ifish/mapper/Tbl_Push_List_Mapper.java @@ -0,0 +1,63 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.mapper; + +import com.ifish.bean.Tbl_Push_List; +import java.util.List; +import org.apache.ibatis.annotations.Delete; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.SelectProvider; + +/** + * + * @author Administrator + */ +public interface Tbl_Push_List_Mapper { + + /** + * 分页获取用户推送消息 + * + * @param userId + * @param pushType + * @param pageSize + * @param firstResult + * @return + */ + @SelectProvider(type = Tbl_Push_List_MapperSql.class, method = "getPushList") + List getPushList(@Param("userid") Integer userId, @Param("pushtype") String pushType, @Param("pagesize") Integer pageSize, @Param("first") Integer firstResult); + + /** + * 根据ID查询推送消息对象 + * + * @param pushId + * @return + */ + @Select("SELECT push_id,user_id,device_id,show_name,phone_type,push_type,push_title,push_context,create_time,push_link,jpush_status,google_status FROM TBL_PUSH_LIST WHERE push_id = #{pushid}") + Tbl_Push_List getPush_ListById(@Param("pushid") Integer pushId); + + /** + * 根据ID删除推送消息 + * + * @param pushId + * @return + */ + @Delete("DELETE FROM TBL_PUSH_LIST WHERE push_id = #{id}") + Integer deletePushListById(@Param("id") Integer pushId); + + /** + * 分页获取用户推送消息 + * + * @param userId + * @param pushType + * @param pageSize + * @param firstResult + * @return + */ + @Select("SELECT COUNT(1) FROM TBL_PUSH_LIST WHERE user_id = #{userid} AND push_type = #{pushtype} LIMIT ${first},${pagesize}") + Integer getPushListCount(@Param("userid") Integer userId, @Param("pushtype") String pushType, @Param("pagesize") Integer pageSize, @Param("first") Integer firstResult); + +} diff --git a/src/main/java/com/ifish/mapper/Tbl_Push_List_MapperSql.java b/src/main/java/com/ifish/mapper/Tbl_Push_List_MapperSql.java new file mode 100644 index 0000000..e4e8e5f --- /dev/null +++ b/src/main/java/com/ifish/mapper/Tbl_Push_List_MapperSql.java @@ -0,0 +1,30 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.mapper; + +import org.apache.commons.lang3.StringUtils; +import org.apache.ibatis.annotations.Param; + +/** + * + * @author Administrator + */ +public class Tbl_Push_List_MapperSql { + + public String getPushList(@Param("userid") Integer userId, @Param("pushtype") String pushType, @Param("pagesize") Integer pageSize, @Param("first") Integer firstResult) { + StringBuilder sb = new StringBuilder(); + + sb.append("SELECT push_id,user_id,device_id,show_name,phone_type,push_type,push_title,push_context,create_time,push_link,jpush_status,google_status FROM TBL_PUSH_LIST WHERE "); + sb.append("user_id = #{userid} "); + if (StringUtils.isNotBlank(pushType)) { + sb.append("AND push_type = #{pushtype} "); + } + sb.append("ORDER BY push_id DESC LIMIT ").append(firstResult).append(",").append(pageSize); + + return sb.toString(); + } + +} diff --git a/src/main/java/com/ifish/mapper/Tbl_User_Mapper.java b/src/main/java/com/ifish/mapper/Tbl_User_Mapper.java new file mode 100644 index 0000000..78c77b3 --- /dev/null +++ b/src/main/java/com/ifish/mapper/Tbl_User_Mapper.java @@ -0,0 +1,79 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.mapper; + +import com.ifish.bean.Tbl_User; +import org.apache.ibatis.annotations.InsertProvider; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.SelectKey; +import org.apache.ibatis.annotations.Update; +import org.apache.ibatis.annotations.UpdateProvider; + +/** + * + * @author Administrator + */ +public interface Tbl_User_Mapper { + + /** + * 根据手机号获取用户对象 + * + * @return + */ + @Select("select user_id,nick_name,user_password,phone_number,user_email,user_type,user_img,user_sex,login_count,update_time,login_time,create_time,login_type,remarks,address,P2PVerify_code1,P2PVerify_code2," + + "gwell_userID,is_register_gwell,jiguang_userID,longitude,latitude from tbl_user where phone_number=#{phoneNumber}") + Tbl_User getUserByPhoneNumber(@Param("phoneNumber") String phoneNumber); + + /** + * 根据用户邮箱获取用户对象 + * + * @param userid + * @return + */ + @Select("select user_id,nick_name,user_password,phone_number,user_email,user_type,user_img,user_sex,login_count,update_time,login_time,create_time,login_type,remarks,address,P2PVerify_code1,P2PVerify_code2," + + "gwell_userID,is_register_gwell,jiguang_userID,longitude,latitude from tbl_user where user_email=#{user_email}") + Tbl_User getUserByUserEmail(@Param("user_email") String userEmail); + + /** + * 根据用户ID获取用户对象 + * + * @param userid + * @return + */ + @Select("select user_id,nick_name,user_password,phone_number,user_email,user_type,user_img,user_sex,login_count,update_time,login_time,create_time,login_type,remarks,address,P2PVerify_code1,P2PVerify_code2," + + "gwell_userID,is_register_gwell,jiguang_userID,longitude,latitude from tbl_user where user_id=#{userid}") + Tbl_User getUserByUserId(@Param("userid") String userid); + + /** + * 每次登陆后修改登陆时间、次数和手机类型 + * + * @param userId + * @param loginType + * @return + */ + @Update("update tbl_user set login_count=if(login_count is null,1,login_count+1),login_type=#{logintype},login_time=current_timestamp() where user_id=#{userid}") + Integer executeLoginUpdate(@Param("userid") Integer userId, @Param("logintype") String loginType); + + /** + * 修改用户账号信息 + * + * @param user + * @return + */ + @UpdateProvider(type = Tbl_User_MapperSql.class, method = "updateUser") + Integer updateUser(@Param("user") Tbl_User user); + + /** + * 注册用户 + * + * @param user + * @return + */ + @InsertProvider(type = Tbl_User_MapperSql.class, method = "registerUser") + @SelectKey(statement = "select @@IDENTITY as user_id", keyProperty = "user.userId", keyColumn = "userId", before = false, resultType = int.class) + Integer insertUser(@Param("user") Tbl_User user); +} diff --git a/src/main/java/com/ifish/mapper/Tbl_User_MapperSql.java b/src/main/java/com/ifish/mapper/Tbl_User_MapperSql.java new file mode 100644 index 0000000..ec264cd --- /dev/null +++ b/src/main/java/com/ifish/mapper/Tbl_User_MapperSql.java @@ -0,0 +1,101 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.mapper; + +import com.ifish.bean.Tbl_User; +import org.apache.ibatis.annotations.Param; +import org.apache.commons.lang3.StringUtils; + +/** + * + * @author Administrator + */ +public class Tbl_User_MapperSql { + + public String updateUser(@Param("user") Tbl_User user) { + StringBuilder sb = new StringBuilder(); + + sb.append("Update tbl_User SET "); + if (user.getNickName() != null && StringUtils.isNotBlank(user.getNickName())) { + sb.append("nick_name = #{user.nickName}, "); + } + if (user.getUserPassword() != null && StringUtils.isNotBlank(user.getUserPassword())) { + sb.append("user_password = #{user.userPassword}, "); + } + if (user.getPhoneNumber() != null && StringUtils.isNotBlank(user.getPhoneNumber())) { + sb.append("phone_number = #{user.phoneNumber}, "); + } + if (user.getUserEmail() != null && StringUtils.isNotBlank(user.getUserEmail())) { + sb.append("user_email = #{user.userEmail}, "); + } +// if (user.getUserType() != null && StringUtils.isNotBlank(user.getUserType())) { +// sb.append("user_type = #{user.userType}, "); +// } + if (user.getUserImg() != null && StringUtils.isNotBlank(user.getUserImg())) { + sb.append("user_img = #{user.userImg}, "); + } + if (user.getUserSex() != null && StringUtils.isNotBlank(user.getUserSex())) { + sb.append("user_sex = #{user.userSex}, "); + } + //登陆次数有另外的Sql语句 + if (user.getUpdateTime() != null) { + sb.append("update_time = #{user.updateTime}, "); + } + if (user.getLoginTime() != null) { + sb.append("login_time = #{user.loginTime}, "); + } + //注册时间不予修改 + if (user.getLoginType() != null && StringUtils.isNotBlank(user.getLoginType())) { + sb.append("login_type = #{user.loginType}, "); + } + if (user.getRemarks() != null && StringUtils.isNotBlank(user.getRemarks())) { + sb.append("remarks = #{user.remarks}, "); + } + if (user.getAddress() != null && StringUtils.isNotBlank(user.getAddress())) { + sb.append("address = #{user.address}, "); + } + if (user.getP2pverifyCode1() != null && StringUtils.isNotBlank(user.getP2pverifyCode1())) { + sb.append("p2pverify_code1 = #{user.p2pverifyCode1}, "); + } + if (user.getP2pverifyCode2() != null && StringUtils.isNotBlank(user.getP2pverifyCode2())) { + sb.append("p2pverify_code2 = #{user.p2pverifyCode2}, "); + } + if (user.getGwellUserid() != null && StringUtils.isNotBlank(user.getGwellUserid())) { + sb.append("gwell_userid = #{user.gwellUserid}, "); + } + if (user.getIsRegisterGwell() != null && StringUtils.isNotBlank(user.getIsRegisterGwell())) { + sb.append("is_register_gwell = #{user.isRegisterGwell}, "); + } + if (user.getJiguangUserid() != null && StringUtils.isNotBlank(user.getJiguangUserid())) { + sb.append("jiguang_userID = #{user.jiguangUserid}, "); + } + if (user.getLatitude() != null && user.getLatitude() > 0) { + sb.append("latitude = #{user.latitude}, "); + } + if (user.getLongitude() != null && user.getLongitude() > 0) { + sb.append("longitude = #{iser.longitude}, "); + } + if (sb.lastIndexOf(",") == sb.length() - 2) { + sb.deleteCharAt(sb.length() - 2); + } + sb.append(" WHERE user_id = #{user.userId}"); + return sb.toString(); + } + + /** + * 游客注册接口 + * + * @param user + * @return + */ + public String registerUser(@Param("user") Tbl_User user) { + StringBuilder sb = new StringBuilder(); + + sb.append("INSERT tbl_user (user_type) value ('0')"); + + return sb.toString(); + } +} diff --git a/src/main/java/com/ifish/util/IfishFilePath.java b/src/main/java/com/ifish/util/IfishFilePath.java new file mode 100644 index 0000000..ca7e795 --- /dev/null +++ b/src/main/java/com/ifish/util/IfishFilePath.java @@ -0,0 +1,109 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.util; + +import com.ifish.enums.SubDirectoryEnum; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.util.Properties; + +/** + * + * @author Administrator + */ +public class IfishFilePath { + + //头像地址 + public static String path_img; + /** + * 图片头地址 + */ + public static String link_img_head; + //商家图片地址 + public static String path_shops; + //商品介绍图片 + public static String path_commodity; + //微信分享页面 + public static String path_share_html; + //微信分享页图片 + public static String path_share_img; + //看护报告页面 + public static String path_look_html; + //看护报告图片 + public static String path_look_img; + //html名字 + public static String html_name; + //图片上传格式 + public static String check_style; + //云信爱鱼奇官方帐号 + public static String ifish_account; + //IM官方手机号 + public static String netease_phone; + //直播间封面 + public static String path_room_img; + //FastDFS商家视频上传URL访问路径(本地和测试环境) + public static String fastDFS_url_local; + //FastDFS商家视频上传URL访问路径(正式环境) + public static String fastDFS_url_app; + //开发模式 + public static boolean devModel; + + static { + Properties prop = new Properties(); + InputStream in = IfishFilePath.class.getResourceAsStream("/property.properties"); + try { + prop.load(in); + //利用反射机制给属性赋值 + Field[] fields = IfishFilePath.class.getDeclaredFields(); + for (Field field : fields) { + String name = field.getName(); + //获取property.properties的值 + String value = prop.getProperty(name).trim(); + //判断这个值希望塞入的变量类型,并进行转换 + Object value1 = getValue(value, field); + //转换完成后塞入此变量 + field.set(IfishFilePath.class, value1); + + } + in.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 验证图片格式 + */ + public static String checkImgName(String fileName) { + //对格式进行验证 + int index = fileName.lastIndexOf("."); + String extEndName = fileName.substring(++index, fileName.length()); + if (check_style.indexOf(extEndName.toUpperCase()) == -1) { + return null; + } + //返回格式.png + return "." + extEndName; + } + + /** + * 获取图片链接地址 + * + * @param type + * @return + */ + public static String getPath(SubDirectoryEnum pictureEnum, String fileName) { + return link_img_head + pictureEnum.getKey() + fileName; + } + + private static Object getValue(String value, Field field) { + if (field.getType().equals(int.class)) { + return Integer.valueOf(value); + } else if (field.getType().equals(boolean.class)) { + return Boolean.valueOf(value); + } + return value; + } +} diff --git a/src/main/java/com/ifish/util/IfishUtil.java b/src/main/java/com/ifish/util/IfishUtil.java new file mode 100644 index 0000000..652a678 --- /dev/null +++ b/src/main/java/com/ifish/util/IfishUtil.java @@ -0,0 +1,470 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.util; + +import com.ifish.bean.PageResult; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.UnsupportedEncodingException; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.type.JavaType; +import org.springframework.web.multipart.MultipartFile; + +/** + * + * @author Administrator + */ +public class IfishUtil { + + private static final String formatDate = "yyyy-MM-dd HH:mm:ss"; + + private static final String formatDate3 = "MM-dd HH:mm"; + + private static final String formatDate2 = "yyyy-MM-dd HH:mm"; + + private static final String formatDate1 = "yyyy-MM-dd"; + + /** + * 测试缓存时间:一分钟;单位:秒 + */ + public static final int CacheTime_Test_SECONDS = 60; + /** + * 缓存时间:一秒;单位:秒 + */ + public static final int CacheTime_SECONDS = 1; + /** + * 缓存时间:一分钟;单位:分 + */ + public static final int CacheTime_MINUTES = 1; + /** + * 缓存时间:一小时;单位:小时 + */ + public static final int CacheTime_HOURS = 1; + /** + * 缓存时间:一天;单位:天 + */ + public static final int CacheTime_DAYS = 1; + + /** + * Object转Json + */ + public static String ObjectToJson(Object value) { + try { + if (value == null) { + return null; + } + ObjectMapper mapper = new ObjectMapper(); + String js = mapper.writeValueAsString(value); + return js; + } catch (Exception ex) { + System.out.println("【异常信息】 >>> " + ex.toString()); + return "Error"; + } + } + + /** + * Json转Object(List) + * + * @param json 需要转换的JSON字符串 + * @param bean JavaBean, + * @return 拿到结果需要强转一次,因为你拿到的是Object, 例如这样调用和强转: List<School> lst + * =(List<School>)StringUtil.JsonToObjectList(value, School.class); + */ + public static Object JsonToList(String json, Class bean) throws Exception { + ObjectMapper mapper = new ObjectMapper(); + JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, bean); + return mapper.readValue(json, javaType); + } + + /** + * Json转Object(JavaBean) + * + * @param json 需要转换的JSON字符串 + * @param bean JavaBean, + * @return 拿到结果需要强转一次,因为你拿到的是Object, 例如这样调用和强转: School lst + * =(School)StringUtil.JsonToObjectList(value, School.class); + */ + public static Object JsonToBean(String json, Class bean) throws Exception { + ObjectMapper mapper = new ObjectMapper(); + JavaType javaType = mapper.getTypeFactory().uncheckedSimpleType(bean); + return mapper.readValue(json, javaType); + } + + /** + * 将json格式的字符串解析成Map对象 + */ + public static Map> JsonToMap(String json) { + try { + ObjectMapper mapper = new ObjectMapper(); + Map> maps = mapper.readValue(json, Map.class); + return maps; + } catch (Exception e) { + System.out.println("【异常信息】 >>> " + e.toString()); + return null; + } + } + + public static Map JsonToMapContainMap(String json) { + try { + ObjectMapper mapper = new ObjectMapper(); + Map maps = mapper.readValue(json, Map.class); + return maps; + } catch (Exception e) { + System.out.println("【异常信息】 >>> " + e.toString()); + return null; + } + } + + public static Map JsonToRealMap(String json) { + try { + ObjectMapper mapper = new ObjectMapper(); + Map maps = mapper.readValue(json, Map.class); + return maps; + } catch (Exception e) { + System.out.println("【异常信息】 >>> " + e.toString()); + return null; + } + } + + /** + * 返回分页数据 + * + * @param str + * @return + */ + public static Object returnPageData(PageResult page, String resultKey) { + Map map = new HashMap(); + map.put("result", resultKey); + //实际的行数 + map.put("total", page.getTotalCount()); + //数据 + map.put("data", page.getList()); + return map; + } + + //返回时分秒的时间字符串 + public static String TimestampToStringAndSecond(Object timestamp) { + DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + try { + return (format.format(timestamp)); + } catch (Exception e) { + System.out.println("【isGaokaoYearExpire 异常】:" + e); + return ""; + } + } + + //返回时分秒的时间字符串 + public static String TimestampToStringAndSecond(Object timestamp, String geshi) { + DateFormat format = new SimpleDateFormat(geshi); + try { + return (format.format(timestamp)); + } catch (Exception e) { + System.out.println("【isGaokaoYearExpire 异常】:" + e); + return ""; + } + } + + /** + * 返回当前日期yyyy-MM-dd + * + * @return + * @throws ParseException + */ + public static Date getCurDate() { + DateFormat df = DateFormat.getDateInstance(); + try { + return df.parse(df.format(new Date())); + } catch (ParseException e) { + } + return null; + } + + /** + * 格式化日期yyyy-MM-dd HH:mm:ss + * + * @param date + * @return + */ + public static String format(Date date) { + SimpleDateFormat format = new SimpleDateFormat(formatDate); + return format.format(date); + } + + /** + * 格式化日期 + * + * @param date + * @return + */ + public static String format1(Date date) { + SimpleDateFormat format = new SimpleDateFormat(formatDate1); + return format.format(date); + } + + /** + * 格式化日期 + * + * @param date + * @return + */ + public static String format2(Date date) { + SimpleDateFormat format = new SimpleDateFormat(formatDate2); + return format.format(date); + } + + /** + * 格式化日期 + * + * @param date + * @return + */ + public static String format3(Date date) { + SimpleDateFormat format = new SimpleDateFormat(formatDate3); + return format.format(date); + } + + /** + * 字符串转换成日期 + * + * @param str + * @return date + */ + public static Date StrToDate(String str) { + SimpleDateFormat format = new SimpleDateFormat(formatDate1); + Date date = null; + try { + date = format.parse(str); + } catch (ParseException e) { + e.printStackTrace(); + } + return date; + } + + /** + * 随机生成字母与数字组合 + * + * @param length + * @return + */ + public static String getCharAndNumr(int length) { + String val = ""; + Random random = new Random(); + for (int i = 0; i < length; i++) { + // 输出字母还是数字 + String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num"; + // 字符串 + if ("char".equalsIgnoreCase(charOrNum)) { + // 取得大写字母还是小写字母 + int choice = random.nextInt(2) % 2 == 0 ? 65 : 97; + val += (char) (choice + random.nextInt(26)); + // 数字 + } else if ("num".equalsIgnoreCase(charOrNum)) { + val += String.valueOf(random.nextInt(10)); + } + } + return val; + } + + /** + * 返回json数据 + * + * @param str + * @return + */ + public static Map returnJson(String key, Object value) { + Map map = new HashMap(); + map.put("result", key); + if (value.equals("")) { + map.put("data", null); + } else { + map.put("data", value); + } + return map; + } + + /** + * 返回json数据 + * + * @param str + * @return + */ + public static Map toJson(String key, Object value) { + Map map = new HashMap(); + map.put("result", key); + if (value.equals("")) { + map.put("data", null); + } else { + map.put("data", value); + } + return map; + } + + /** + * 上传图片文件 + * + * @param fileUpload + * @param path + * @return + */ + public static String uploadFile(MultipartFile fileUpload, String path) { + //根据时间得文件名 + Calendar calendar = Calendar.getInstance(); + String fileName = String.valueOf(calendar.getTimeInMillis()); + //保存文件 + if (fileUpload == null) { + return "base/default.png"; + } + if (!fileUpload.isEmpty()) { + try { + if (!fileUpload.getOriginalFilename().equals("")) { + File picFile = new File(path, fileName + ".png"); + //不存在则创建 + if (!picFile.exists()) { + picFile.mkdirs(); + } + //保存 + fileUpload.transferTo(picFile); + } + return "share/" + fileName + ".png"; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + return ""; + } + + /** + * 生成微信分享页面 + * + * @param title + * @param base64 + * @return + */ + public static String getHtmlFile(String title, String pngName, String modelFile, String filePath) { + try { + if (pngName != null && !pngName.equals("")) { + //读取模板文件 + FileInputStream fileinputstream = new FileInputStream(filePath + modelFile); + int lenght = fileinputstream.available(); + byte bytes[] = new byte[lenght]; + fileinputstream.read(bytes); + fileinputstream.close(); + String templateContent = new String(bytes); + //替换掉模板中相应的地方 + templateContent = templateContent.replaceAll("###title###", title); + templateContent = templateContent.replaceAll("###fileName###", pngName); + //根据时间得文件名 + Calendar calendar = Calendar.getInstance(); + String fileName = String.valueOf(calendar.getTimeInMillis()); + fileName = fileName + ".html"; + //建立文件输出流 + FileOutputStream fileoutputstream = new FileOutputStream(filePath + fileName); + byte tag_bytes[] = templateContent.getBytes(); + fileoutputstream.write(tag_bytes); + fileoutputstream.close(); + return fileName; + } + } catch (Exception e) { + throw new RuntimeException(e); + } + return ""; + } + + /** + * 随即区间整数 + * + * @param min + * @param max + * @return + */ + public static int getRandom(int min, int max) { + int r = new Random().nextInt(max - min); + return r + min; + } + + /** + * URL 解码 + * + * @return String + * @author lifq + * @date 2015-3-17 下午04:09:51 + */ + public static String getURLDecoderString(String str) { + String result = ""; + if (null == str) { + return ""; + } + try { + result = java.net.URLDecoder.decode(str, "GBK"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return result; + } + + /** + * URL 转码 + * + * @return String + * @author lifq + * @date 2015-3-17 下午04:10:28 + */ + public static String getURLEncoderString(String str) { + String result = ""; + if (null == str) { + return ""; + } + try { + result = java.net.URLEncoder.encode(str, "GBK"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return result; + } + + /** + * 正则表达式截取字符串 + * + * @param str + * @param regex + * @return + */ + public static String regex(String str, String regex) { + Matcher matcher = Pattern.compile(regex).matcher(str); + if (matcher.find()) { + return matcher.group(0); + } else { + return ""; + } + } + + public static String regexToChinese(String str) { + String regex = "([\\u4e00-\\u9fa5]+)"; + return regex(str, regex); + } + + /** + * 验证当前系统是windows(本地,返回true),还是unix(服务器,返回false) + * + * @return + */ + public static boolean IsWinOrUnix() { + String os = System.getProperty("os.name");//获取当前操作系统 + return os.toLowerCase().startsWith("win"); + } +} diff --git a/src/main/java/com/ifish/util/JdbcProperties.java b/src/main/java/com/ifish/util/JdbcProperties.java new file mode 100644 index 0000000..9260ea9 --- /dev/null +++ b/src/main/java/com/ifish/util/JdbcProperties.java @@ -0,0 +1,61 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.util; + +import java.io.InputStream; +import java.lang.reflect.Field; +import java.util.Properties; + +/** + * + * @author Administrator + */ +public class JdbcProperties { + + public static String driverClassName; + public static String url; + public static String username; + public static String password; + public static boolean autoCommitOnClose; + public static int initialPoolSize; + public static int minPoolSize; + public static int maxPoolSize; + public static int acquireIncrement; + public static int checkoutTimeout; + public static int maxIdleTime; + public static int idleConnectionTestPeriod; + + static { + Properties prop = new Properties(); + InputStream in = IfishFilePath.class.getResourceAsStream("/jdbc.properties"); + try { + prop.load(in); + //利用反射机制给属性赋值 + Field[] fields = JdbcProperties.class.getDeclaredFields(); + for (Field field : fields) { + String name = field.getName(); + //获取property.properties的值 + String value = prop.getProperty(name).trim(); + //判断这个值希望塞入的变量类型,并进行转换 + Object value1 = getValue(value, field); + //转换完成后塞入此变量 + field.set(IfishFilePath.class, value1); + } + in.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private static Object getValue(String value, Field field) { + if (field.getType().equals(int.class)) { + return Integer.valueOf(value); + } else if (field.getType().equals(boolean.class)) { + return Boolean.valueOf(value); + } + return value; + } +} diff --git a/src/main/java/com/ifish/util/RedisKey.java b/src/main/java/com/ifish/util/RedisKey.java new file mode 100644 index 0000000..4035628 --- /dev/null +++ b/src/main/java/com/ifish/util/RedisKey.java @@ -0,0 +1,73 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.ifish.util; + +/** + * + * @author Administrator + */ +public class RedisKey { + + /** + * 用户缓存前缀 + */ + public static final String User_Key = "userE:"; + + /** + * 商家信息缓存前缀 + */ + public static final String ShopsInfo_Key = "shopsInfoE:"; + + /** + * 用户绑定设备缓存前缀 + */ + public static final String DeviceUser_Key = "deviceUserE:"; + + /** + * 设备绑定摄像头缓存前缀 + */ + public static final String DeviceCamera_key = "deviceCameraE:"; + + /** + * 设备详情缓存前缀 + */ + public static final String Device_key = "deviceE:"; + + /** + * 设备类型缓存前缀 + */ + public static final String HardWareType_key = "hardwaretypeE:"; + + /** + * 厂家列表缓存前缀 + */ + public static final String VenderList_key = "venderlistE:"; + + /** + * 用户和摄像头的绑定关系存前缀 + */ + public static final String CameraUser_key = "cameraUserE:"; + + /** + * 摄像头详情缓存前缀 + */ + public static final String Camera_key = "cameraE:"; + + /** + * 设备统计信息表缓存前缀 + */ + public static final String DeviceStatistic_key = "deviceStaticticsE:"; + + /** + * 直播间详情表缓存前缀 + */ + public static final String LiveRoom_key = "liveroomE:"; + + /** + * 推送消息缓存前缀 + */ + public static final String PUSHLIST_KEY = "pushlistE:"; +} diff --git a/src/main/resources/fdfs_client_ifish7.conf b/src/main/resources/fdfs_client_ifish7.conf new file mode 100644 index 0000000..9661bfb --- /dev/null +++ b/src/main/resources/fdfs_client_ifish7.conf @@ -0,0 +1,7 @@ +connect_timeout = 2 +network_timeout = 30 +charset = UTF-8 +http.tracker_http_port = 85 +http.anti_steal_token = no +http.secret_key = FastDFS1234567890 +tracker_server = 120.55.190.56:22131 \ No newline at end of file diff --git a/src/main/resources/fdfs_client_zhangxinyanv5.conf b/src/main/resources/fdfs_client_zhangxinyanv5.conf new file mode 100644 index 0000000..6a88c9e --- /dev/null +++ b/src/main/resources/fdfs_client_zhangxinyanv5.conf @@ -0,0 +1,8 @@ +connect_timeout = 2 +network_timeout = 30 +charset = UTF-8 +http.tracker_http_port = 8017 +http.anti_steal_token = no +http.secret_key = FastDFS1234567890 +tracker_server = 139.196.24.156:22122 + diff --git a/src/main/resources/jdbc.properties b/src/main/resources/jdbc.properties new file mode 100644 index 0000000..1b38a52 --- /dev/null +++ b/src/main/resources/jdbc.properties @@ -0,0 +1,40 @@ +#c3p0.driverClassName=com.mysql.jdbc.Driver +#c3p0.url=jdbc\:mysql\://localhost\:3306/myfishdbenglish?characterEncoding\=UTF-8 +#c3p0.username=ifish +#c3p0.password=ifish7pwd +#c3p0.autoCommitOnClose=true +#c3p0.initialPoolSize=20 +#c3p0.minPoolSize=20 +#c3p0.maxPoolSize=50 +#c3p0.acquireIncrement=3 + +#c3p0.checkoutTimeout=5000 +#c3p0.maxIdleTime=7200 +#c3p0.idleConnectionTestPeriod=18000 +#c3p0.maxIdleTimeExcessConnections=1800 + +#c3p0.automaticTestTable=C3P0TestTable +#c3p0.testConnectionOnCheckout=false +#c3p0.testConnectionOnCheckin=false + +#\u8fd9\u91cc\u662f\u4e0a\u9762\u53d6\u6d88\u524d\u7f00\u7684\u5f15\u7528,\u5982\u679c\u4fee\u6539\uff0c\u8bf7\u4fee\u6539\u8fd9\u91cc +driverClassName=com.mysql.jdbc.Driver +url=jdbc\:mysql\://localhost\:3306/myfishdbenglish?characterEncoding\=UTF-8 +username=ifish +password=ifish7pwd +autoCommitOnClose=true +initialPoolSize=20 +minPoolSize=20 +maxPoolSize=50 +acquireIncrement=3 +checkoutTimeout=5000 +maxIdleTime=7200 +idleConnectionTestPeriod=18000 + +#org.hibernate.dialect.MySQLInnoDBDialect +hibernate.dialect=org.hibernate.dialect.MySQLDialect +hibernate.show_sql=false +hibernate.format_sql=true +hibernate.hbm2ddl.auto=false +hibernate.jdbc.batch_size=50 +hibernate.query.substitutions=true 1,false 0 diff --git a/src/main/resources/property.properties b/src/main/resources/property.properties new file mode 100644 index 0000000..2c6c76c --- /dev/null +++ b/src/main/resources/property.properties @@ -0,0 +1,36 @@ +#\u5934\u50cf\u5b58\u50a8\u8def\u5f84 +path_img=/mydata/tmp/Img/app +#\u5546\u5bb6\u8ba4\u8bc1\u56fe\u7247 +path_shops=/mydata/tmp/Img/shops +#\u5546\u54c1\u4ecb\u7ecd\u56fe\u7247 +path_commodity=/mydata/tmp/Img/commodity +#\u76f4\u64ad\u95f4\u5c01\u9762 +path_room_img=/mydata/tmp/Img/room +#\u5fae\u4fe1\u5206\u4eab\u9875\u9762 +path_share_html=/mydata/tmp/html/ +#\u5fae\u4fe1\u5206\u4eab\u9875\u56fe\u7247 +path_share_img=/mydata/tmp/html/images/share +#\u770b\u62a4\u62a5\u544a\u9875\u9762 +path_look_html=/mydata/tmp/look/ +#\u770b\u62a4\u62a5\u544a\u56fe\u7247 +path_look_img=/mydata/tmp/look/images/share +#\u770b\u62a4\u62a5\u544a\u6a21\u7248html\u540d\u5b57 +html_name=index.html +#\u4e91\u4fe1\u7231\u9c7c\u5947\u5b98\u65b9\u5e10\u53f7 +ifish_account=ifish +#IM\u5b98\u65b9\u624b\u673a\u53f7 +netease_phone=18501773036 +#FastDFS\u6587\u4ef6URL\u8bbf\u95ee\u8def\u5f84(\u672c\u5730\u548c\u6d4b\u8bd5\u73af\u5883) +fastDFS_url_local=https://app.zhangxinyanv5.top/ +#FastDFS\u6587\u4ef6URL\u8bbf\u95ee\u8def\u5f84(\u6b63\u5f0f\u73af\u5883) +fastDFS_url_app=http://app.ifish7.com/ +#\u672c\u5730 +#link_img_head=http://192.168.61.128:81/ +#\u6d4b\u8bd5\u73af\u5883 +#link_img_head=https://app.zhangxinyanv5.top/ +#\u6b63\u5f0f\u73af\u5883 +link_img_head=https://app.ifish7.com/ +#\u56fe\u7247\u683c\u5f0f\u9a8c\u8bc1 +check_style=GIF,PNG,BMP,JPG,JPEG +#\u662f\u5426\u5f00\u53d1\u6a21\u5f0f\uff0cfalse\u5219\u4ee3\u8868\u8981\u53d1\u5e03\u5230\u6d4b\u8bd5\u6216\u8005\u6b63\u5f0f\u73af\u5883\uff0c\u4f1a\u8fdb\u884c\u5168\u5c40\u5934\u90e8\u9a8c\u8bc1\uff0ctrue\u4ee3\u8868\u5728\u672c\u5730\u8fdb\u884c\u4ee3\u7801\u7f16\u5199\uff0c\u4e0d\u4f1a\u8fdb\u884c\u9a8c\u8bc1 +devModel=true \ No newline at end of file diff --git a/src/main/webapp/META-INF/context.xml b/src/main/webapp/META-INF/context.xml new file mode 100644 index 0000000..5bee3dc --- /dev/null +++ b/src/main/webapp/META-INF/context.xml @@ -0,0 +1,2 @@ + + diff --git a/src/main/webapp/WEB-INF/lib/fastdfs-client-java-1.25.jar b/src/main/webapp/WEB-INF/lib/fastdfs-client-java-1.25.jar new file mode 100644 index 0000000000000000000000000000000000000000..74adb9294c5580275b3cd37fefcb9311db2073bf GIT binary patch literal 91061 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 + + + + + + API接口 + + +

访问正常!

+ +