diff --git a/springboot/ry.bat b/springboot/ry.bat deleted file mode 100644 index d63f9b14..00000000 --- a/springboot/ry.bat +++ /dev/null @@ -1,67 +0,0 @@ -@echo off - -rem jarƽ��Ŀ¼ -set AppName=wumei-admin.jar - -rem JVM���� -set JVM_OPTS="-Dname=%AppName% -Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC" - - -ECHO. - ECHO. [1] ����%AppName% - ECHO. [2] �ر�%AppName% - ECHO. [3] ����%AppName% - ECHO. [4] ����״̬ %AppName% - ECHO. [5] �� �� -ECHO. - -ECHO.������ѡ����Ŀ�����: -set /p ID= - IF "%id%"=="1" GOTO start - IF "%id%"=="2" GOTO stop - IF "%id%"=="3" GOTO restart - IF "%id%"=="4" GOTO status - IF "%id%"=="5" EXIT -PAUSE -:start - for /f "usebackq tokens=1-2" %%a in (`jps -l ^| findstr %AppName%`) do ( - set pid=%%a - set image_name=%%b - ) - if defined pid ( - echo %%is running - PAUSE - ) - -start javaw %JAVA_OPTS% -jar %AppName% - -echo starting���� -echo Start %AppName% success... -goto:eof - -rem ����stopͨ��jps�������pid���������� -:stop - for /f "usebackq tokens=1-2" %%a in (`jps -l ^| findstr %AppName%`) do ( - set pid=%%a - set image_name=%%b - ) - if not defined pid (echo process %AppName% does not exists) else ( - echo prepare to kill %image_name% - echo start kill %pid% ... - rem ���ݽ���ID��kill���� - taskkill /f /pid %pid% - ) -goto:eof -:restart - call :stop - call :start -goto:eof -:status - for /f "usebackq tokens=1-2" %%a in (`jps -l ^| findstr %AppName%`) do ( - set pid=%%a - set image_name=%%b - ) - if not defined pid (echo process %AppName% is dead ) else ( - echo %image_name% is running - ) -goto:eof diff --git a/springboot/ry.sh b/springboot/ry.sh deleted file mode 100644 index 9770af79..00000000 --- a/springboot/ry.sh +++ /dev/null @@ -1,86 +0,0 @@ -#!/bin/sh -# ./ry.sh start 启动 stop 停止 restart 重启 status 状态 -AppName=wumei-admin.jar - -# JVM参数 -JVM_OPTS="-Dname=$AppName -Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC" -APP_HOME=`pwd` -LOG_PATH=$APP_HOME/logs/$AppName.log - -if [ "$1" = "" ]; -then - echo -e "\033[0;31m 未输入操作名 \033[0m \033[0;34m {start|stop|restart|status} \033[0m" - exit 1 -fi - -if [ "$AppName" = "" ]; -then - echo -e "\033[0;31m 未输入应用名 \033[0m" - exit 1 -fi - -function start() -{ - PID=`ps -ef |grep java|grep $AppName|grep -v grep|awk '{print $2}'` - - if [ x"$PID" != x"" ]; then - echo "$AppName is running..." - else - nohup java $JVM_OPTS -jar $AppName > /dev/null 2>&1 & - echo "Start $AppName success..." - fi -} - -function stop() -{ - echo "Stop $AppName" - - PID="" - query(){ - PID=`ps -ef |grep java|grep $AppName|grep -v grep|awk '{print $2}'` - } - - query - if [ x"$PID" != x"" ]; then - kill -TERM $PID - echo "$AppName (pid:$PID) exiting..." - while [ x"$PID" != x"" ] - do - sleep 1 - query - done - echo "$AppName exited." - else - echo "$AppName already stopped." - fi -} - -function restart() -{ - stop - sleep 2 - start -} - -function status() -{ - PID=`ps -ef |grep java|grep $AppName|grep -v grep|wc -l` - if [ $PID != 0 ];then - echo "$AppName is running..." - else - echo "$AppName is not running..." - fi -} - -case $1 in - start) - start;; - stop) - stop;; - restart) - restart;; - status) - status;; - *) - -esac diff --git a/springboot/wumei-admin/pom.xml b/springboot/wumei-admin/pom.xml deleted file mode 100644 index e84aba32..00000000 --- a/springboot/wumei-admin/pom.xml +++ /dev/null @@ -1,102 +0,0 @@ - - - - wumei - com.wumei - 3.8.0 - - 4.0.0 - jar - wumei-admin - - - web服务入口 - - - - - - - org.springframework.boot - spring-boot-devtools - true - - - - - io.springfox - springfox-boot-starter - - - - - io.swagger - swagger-models - 1.6.2 - - - - - mysql - mysql-connector-java - - - - - com.wumei - wumei-framework - - - - - com.wumei - wumei-quartz - - - - - com.wumei - wumei-generator - - - - - com.wumei - wumei-iot - - - - - - - - org.springframework.boot - spring-boot-maven-plugin - 2.1.1.RELEASE - - true - - - - - repackage - - - - - - org.apache.maven.plugins - maven-war-plugin - 3.1.0 - - false - ${project.artifactId} - - - - ${project.artifactId} - - - \ No newline at end of file diff --git a/springboot/wumei-admin/src/main/java/com/ruoyi/WumeiSmartApplication.java b/springboot/wumei-admin/src/main/java/com/ruoyi/WumeiSmartApplication.java deleted file mode 100644 index 362ddb85..00000000 --- a/springboot/wumei-admin/src/main/java/com/ruoyi/WumeiSmartApplication.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.ruoyi; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; -import org.springframework.core.annotation.Order; - -/** - * 启动程序 - * - * @author ruoyi - */ -@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) -public class WumeiSmartApplication -{ - public static void main(String[] args) - { - // System.setProperty("spring.devtools.restart.enabled", "false"); - SpringApplication.run(WumeiSmartApplication.class, args); - System.out.println(" _ _ \n" + - " (_) | | \n" + - "__ ___ _ _ __ ___ ___ _ ___ _ __ ___ __ _ _ __| |_ \n" + - "\\ \\ /\\ / / | | | '_ ` _ \\ / _ \\ | / __| '_ ` _ \\ / _` | '__| __| \n" + - " \\ V V /| |_| | | | | | | __/ | \\__ \\ | | | | | (_| | | | |_ \n" + - " \\_/\\_/ \\__,_|_| |_| |_|\\___|_| |___/_| |_| |_|\\__,_|_| \\__| \n"); - System.out.println( - " ----------开源生活物联网平台-----------\n" + - " =========wumei-smart启动成功=========\n"); - } -} diff --git a/springboot/wumei-admin/src/main/java/com/ruoyi/WumeiSmartServletInitializer.java b/springboot/wumei-admin/src/main/java/com/ruoyi/WumeiSmartServletInitializer.java deleted file mode 100644 index 7412edb1..00000000 --- a/springboot/wumei-admin/src/main/java/com/ruoyi/WumeiSmartServletInitializer.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.ruoyi; - -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; - -/** - * web容器中进行部署 - * - * @author ruoyi - */ -public class WumeiSmartServletInitializer extends SpringBootServletInitializer -{ - @Override - protected SpringApplicationBuilder configure(SpringApplicationBuilder application) - { - return application.sources(WumeiSmartApplication.class); - } -} diff --git a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java b/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java deleted file mode 100644 index 6bd8ddd6..00000000 --- a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.ruoyi.web.controller.common; - -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.util.concurrent.TimeUnit; -import javax.annotation.Resource; -import javax.imageio.ImageIO; -import javax.servlet.http.HttpServletResponse; -import com.ruoyi.common.config.RuoYiConfig; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.util.FastByteArrayOutputStream; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; -import com.google.code.kaptcha.Producer; -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.redis.RedisCache; -import com.ruoyi.common.utils.sign.Base64; -import com.ruoyi.common.utils.uuid.IdUtils; -import com.ruoyi.system.service.ISysConfigService; - -/** - * 验证码操作处理 - * - * @author ruoyi - */ -@RestController -public class CaptchaController -{ - @Resource(name = "captchaProducer") - private Producer captchaProducer; - - @Resource(name = "captchaProducerMath") - private Producer captchaProducerMath; - - @Autowired - private RedisCache redisCache; - - @Autowired - private ISysConfigService configService; - /** - * 生成验证码 - */ - @GetMapping("/captchaImage") - public AjaxResult getCode(HttpServletResponse response) throws IOException - { - AjaxResult ajax = AjaxResult.success(); - boolean captchaOnOff = configService.selectCaptchaOnOff(); - ajax.put("captchaOnOff", captchaOnOff); - if (!captchaOnOff) - { - return ajax; - } - - // 保存验证码信息 - String uuid = IdUtils.simpleUUID(); - String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid; - - String capStr = null, code = null; - BufferedImage image = null; - - // 生成验证码 - String captchaType = RuoYiConfig.getCaptchaType(); - if ("math".equals(captchaType)) - { - String capText = captchaProducerMath.createText(); - capStr = capText.substring(0, capText.lastIndexOf("@")); - code = capText.substring(capText.lastIndexOf("@") + 1); - image = captchaProducerMath.createImage(capStr); - } - else if ("char".equals(captchaType)) - { - capStr = code = captchaProducer.createText(); - image = captchaProducer.createImage(capStr); - } - - redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES); - // 转换流信息写出 - FastByteArrayOutputStream os = new FastByteArrayOutputStream(); - try - { - ImageIO.write(image, "jpg", os); - } - catch (IOException e) - { - return AjaxResult.error(e.getMessage()); - } - - ajax.put("uuid", uuid); - ajax.put("img", Base64.encode(os.toByteArray())); - return ajax; - } -} diff --git a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java b/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java deleted file mode 100644 index e0c728fa..00000000 --- a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java +++ /dev/null @@ -1,118 +0,0 @@ -package com.ruoyi.web.controller.common; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.MediaType; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.multipart.MultipartFile; -import com.ruoyi.common.config.RuoYiConfig; -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.file.FileUploadUtils; -import com.ruoyi.common.utils.file.FileUtils; -import com.ruoyi.framework.config.ServerConfig; - -/** - * 通用请求处理 - * - * @author ruoyi - */ -@RestController -public class CommonController -{ - private static final Logger log = LoggerFactory.getLogger(CommonController.class); - - @Autowired - private ServerConfig serverConfig; - - /** - * 通用下载请求 - * - * @param fileName 文件名称 - * @param delete 是否删除 - */ - @GetMapping("common/download") - public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request) - { - try - { - if (!FileUtils.checkAllowDownload(fileName)) - { - throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName)); - } - String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1); - String filePath = RuoYiConfig.getDownloadPath() + fileName; - - response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); - FileUtils.setAttachmentResponseHeader(response, realFileName); - FileUtils.writeBytes(filePath, response.getOutputStream()); - if (delete) - { - FileUtils.deleteFile(filePath); - } - } - catch (Exception e) - { - log.error("下载文件失败", e); - } - } - - /** - * 通用上传请求 - */ - @PostMapping("/common/upload") - public AjaxResult uploadFile(MultipartFile file) throws Exception - { - try - { - // 上传文件路径 - String filePath = RuoYiConfig.getUploadPath(); - // 上传并返回新文件名称 - String fileName = FileUploadUtils.upload(filePath, file); - String url = serverConfig.getUrl() + fileName; - AjaxResult ajax = AjaxResult.success(); - ajax.put("fileName", fileName); - ajax.put("url", url); - return ajax; - } - catch (Exception e) - { - return AjaxResult.error(e.getMessage()); - } - } - - /** - * 本地资源通用下载 - */ - @GetMapping("/common/download/resource") - public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response) - throws Exception - { - try - { - if (!FileUtils.checkAllowDownload(resource)) - { - throw new Exception(StringUtils.format("资源文件({})非法,不允许下载。 ", resource)); - } - // 本地资源路径 - String localPath = RuoYiConfig.getProfile(); - // 数据库资源地址 - String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX); - // 下载名称 - String downloadName = StringUtils.substringAfterLast(downloadPath, "/"); - response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); - FileUtils.setAttachmentResponseHeader(response, downloadName); - FileUtils.writeBytes(downloadPath, response.getOutputStream()); - } - catch (Exception e) - { - log.error("下载文件失败", e); - } - } -} diff --git a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java b/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java deleted file mode 100644 index 7b97de24..00000000 --- a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.ruoyi.web.controller.monitor; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.core.RedisCallback; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.utils.StringUtils; - -/** - * 缓存监控 - * - * @author ruoyi - */ -@RestController -@RequestMapping("/monitor/cache") -public class CacheController -{ - @Autowired - private RedisTemplate redisTemplate; - - @PreAuthorize("@ss.hasPermi('monitor:cache:list')") - @GetMapping() - public AjaxResult getInfo() throws Exception - { - Properties info = (Properties) redisTemplate.execute((RedisCallback) connection -> connection.info()); - Properties commandStats = (Properties) redisTemplate.execute((RedisCallback) connection -> connection.info("commandstats")); - Object dbSize = redisTemplate.execute((RedisCallback) connection -> connection.dbSize()); - - Map result = new HashMap<>(3); - result.put("info", info); - result.put("dbSize", dbSize); - - List> pieList = new ArrayList<>(); - commandStats.stringPropertyNames().forEach(key -> { - Map data = new HashMap<>(2); - String property = commandStats.getProperty(key); - data.put("name", StringUtils.removeStart(key, "cmdstat_")); - data.put("value", StringUtils.substringBetween(property, "calls=", ",usec")); - pieList.add(data); - }); - result.put("commandStats", pieList); - return AjaxResult.success(result); - } -} diff --git a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java b/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java deleted file mode 100644 index cc805ad8..00000000 --- a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.ruoyi.web.controller.monitor; - -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.framework.web.domain.Server; - -/** - * 服务器监控 - * - * @author ruoyi - */ -@RestController -@RequestMapping("/monitor/server") -public class ServerController -{ - @PreAuthorize("@ss.hasPermi('monitor:server:list')") - @GetMapping() - public AjaxResult getInfo() throws Exception - { - Server server = new Server(); - server.copyTo(); - return AjaxResult.success(server); - } -} diff --git a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java b/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java deleted file mode 100644 index 41dcf981..00000000 --- a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.ruoyi.web.controller.monitor; - -import java.util.List; -import javax.servlet.http.HttpServletResponse; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.page.TableDataInfo; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.system.domain.SysLogininfor; -import com.ruoyi.system.service.ISysLogininforService; - -/** - * 系统访问记录 - * - * @author ruoyi - */ -@RestController -@RequestMapping("/monitor/logininfor") -public class SysLogininforController extends BaseController -{ - @Autowired - private ISysLogininforService logininforService; - - @PreAuthorize("@ss.hasPermi('monitor:logininfor:list')") - @GetMapping("/list") - public TableDataInfo list(SysLogininfor logininfor) - { - startPage(); - List list = logininforService.selectLogininforList(logininfor); - return getDataTable(list); - } - - @Log(title = "登录日志", businessType = BusinessType.EXPORT) - @PreAuthorize("@ss.hasPermi('monitor:logininfor:export')") - @PostMapping("/export") - public void export(HttpServletResponse response, SysLogininfor logininfor) - { - List list = logininforService.selectLogininforList(logininfor); - ExcelUtil util = new ExcelUtil(SysLogininfor.class); - util.exportExcel(response, list, "登录日志"); - } - - @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')") - @Log(title = "登录日志", businessType = BusinessType.DELETE) - @DeleteMapping("/{infoIds}") - public AjaxResult remove(@PathVariable Long[] infoIds) - { - return toAjax(logininforService.deleteLogininforByIds(infoIds)); - } - - @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')") - @Log(title = "登录日志", businessType = BusinessType.CLEAN) - @DeleteMapping("/clean") - public AjaxResult clean() - { - logininforService.cleanLogininfor(); - return AjaxResult.success(); - } -} diff --git a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java b/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java deleted file mode 100644 index b6ba56be..00000000 --- a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.ruoyi.web.controller.monitor; - -import java.util.List; -import javax.servlet.http.HttpServletResponse; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.page.TableDataInfo; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.system.domain.SysOperLog; -import com.ruoyi.system.service.ISysOperLogService; - -/** - * 操作日志记录 - * - * @author ruoyi - */ -@RestController -@RequestMapping("/monitor/operlog") -public class SysOperlogController extends BaseController -{ - @Autowired - private ISysOperLogService operLogService; - - @PreAuthorize("@ss.hasPermi('monitor:operlog:list')") - @GetMapping("/list") - public TableDataInfo list(SysOperLog operLog) - { - startPage(); - List list = operLogService.selectOperLogList(operLog); - return getDataTable(list); - } - - @Log(title = "操作日志", businessType = BusinessType.EXPORT) - @PreAuthorize("@ss.hasPermi('monitor:operlog:export')") - @PostMapping("/export") - public void export(HttpServletResponse response, SysOperLog operLog) - { - List list = operLogService.selectOperLogList(operLog); - ExcelUtil util = new ExcelUtil(SysOperLog.class); - util.exportExcel(response, list, "操作日志"); - } - - @Log(title = "操作日志", businessType = BusinessType.DELETE) - @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')") - @DeleteMapping("/{operIds}") - public AjaxResult remove(@PathVariable Long[] operIds) - { - return toAjax(operLogService.deleteOperLogByIds(operIds)); - } - - @Log(title = "操作日志", businessType = BusinessType.CLEAN) - @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')") - @DeleteMapping("/clean") - public AjaxResult clean() - { - operLogService.cleanOperLog(); - return AjaxResult.success(); - } -} diff --git a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java b/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java deleted file mode 100644 index 9b157ea7..00000000 --- a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.ruoyi.web.controller.monitor; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.domain.model.LoginUser; -import com.ruoyi.common.core.page.TableDataInfo; -import com.ruoyi.common.core.redis.RedisCache; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.system.domain.SysUserOnline; -import com.ruoyi.system.service.ISysUserOnlineService; - -/** - * 在线用户监控 - * - * @author ruoyi - */ -@RestController -@RequestMapping("/monitor/online") -public class SysUserOnlineController extends BaseController -{ - @Autowired - private ISysUserOnlineService userOnlineService; - - @Autowired - private RedisCache redisCache; - - @PreAuthorize("@ss.hasPermi('monitor:online:list')") - @GetMapping("/list") - public TableDataInfo list(String ipaddr, String userName) - { - Collection keys = redisCache.keys(Constants.LOGIN_TOKEN_KEY + "*"); - List userOnlineList = new ArrayList(); - for (String key : keys) - { - LoginUser user = redisCache.getCacheObject(key); - if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) - { - if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername())) - { - userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user)); - } - } - else if (StringUtils.isNotEmpty(ipaddr)) - { - if (StringUtils.equals(ipaddr, user.getIpaddr())) - { - userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user)); - } - } - else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser())) - { - if (StringUtils.equals(userName, user.getUsername())) - { - userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user)); - } - } - else - { - userOnlineList.add(userOnlineService.loginUserToUserOnline(user)); - } - } - Collections.reverse(userOnlineList); - userOnlineList.removeAll(Collections.singleton(null)); - return getDataTable(userOnlineList); - } - - /** - * 强退用户 - */ - @PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')") - @Log(title = "在线用户", businessType = BusinessType.FORCE) - @DeleteMapping("/{tokenId}") - public AjaxResult forceLogout(@PathVariable String tokenId) - { - redisCache.deleteObject(Constants.LOGIN_TOKEN_KEY + tokenId); - return AjaxResult.success(); - } -} diff --git a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java b/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java deleted file mode 100644 index b6f0518c..00000000 --- a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java +++ /dev/null @@ -1,134 +0,0 @@ -package com.ruoyi.web.controller.system; - -import java.util.List; -import javax.servlet.http.HttpServletResponse; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.constant.UserConstants; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.page.TableDataInfo; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.system.domain.SysConfig; -import com.ruoyi.system.service.ISysConfigService; - -/** - * 参数配置 信息操作处理 - * - * @author ruoyi - */ -@RestController -@RequestMapping("/system/config") -public class SysConfigController extends BaseController -{ - @Autowired - private ISysConfigService configService; - - /** - * 获取参数配置列表 - */ - @PreAuthorize("@ss.hasPermi('system:config:list')") - @GetMapping("/list") - public TableDataInfo list(SysConfig config) - { - startPage(); - List list = configService.selectConfigList(config); - return getDataTable(list); - } - - @Log(title = "参数管理", businessType = BusinessType.EXPORT) - @PreAuthorize("@ss.hasPermi('system:config:export')") - @PostMapping("/export") - public void export(HttpServletResponse response, SysConfig config) - { - List list = configService.selectConfigList(config); - ExcelUtil util = new ExcelUtil(SysConfig.class); - util.exportExcel(response, list, "参数数据"); - } - - /** - * 根据参数编号获取详细信息 - */ - @PreAuthorize("@ss.hasPermi('system:config:query')") - @GetMapping(value = "/{configId}") - public AjaxResult getInfo(@PathVariable Long configId) - { - return AjaxResult.success(configService.selectConfigById(configId)); - } - - /** - * 根据参数键名查询参数值 - */ - @GetMapping(value = "/configKey/{configKey}") - public AjaxResult getConfigKey(@PathVariable String configKey) - { - return AjaxResult.success(configService.selectConfigByKey(configKey)); - } - - /** - * 新增参数配置 - */ - @PreAuthorize("@ss.hasPermi('system:config:add')") - @Log(title = "参数管理", businessType = BusinessType.INSERT) - @PostMapping - public AjaxResult add(@Validated @RequestBody SysConfig config) - { - if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) - { - return AjaxResult.error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在"); - } - config.setCreateBy(getUsername()); - return toAjax(configService.insertConfig(config)); - } - - /** - * 修改参数配置 - */ - @PreAuthorize("@ss.hasPermi('system:config:edit')") - @Log(title = "参数管理", businessType = BusinessType.UPDATE) - @PutMapping - public AjaxResult edit(@Validated @RequestBody SysConfig config) - { - if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) - { - return AjaxResult.error("修改参数'" + config.getConfigName() + "'失败,参数键名已存在"); - } - config.setUpdateBy(getUsername()); - return toAjax(configService.updateConfig(config)); - } - - /** - * 删除参数配置 - */ - @PreAuthorize("@ss.hasPermi('system:config:remove')") - @Log(title = "参数管理", businessType = BusinessType.DELETE) - @DeleteMapping("/{configIds}") - public AjaxResult remove(@PathVariable Long[] configIds) - { - configService.deleteConfigByIds(configIds); - return success(); - } - - /** - * 刷新参数缓存 - */ - @PreAuthorize("@ss.hasPermi('system:config:remove')") - @Log(title = "参数管理", businessType = BusinessType.CLEAN) - @DeleteMapping("/refreshCache") - public AjaxResult refreshCache() - { - configService.resetConfigCache(); - return AjaxResult.success(); - } -} diff --git a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java b/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java deleted file mode 100644 index a6030ea3..00000000 --- a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java +++ /dev/null @@ -1,163 +0,0 @@ -package com.ruoyi.web.controller.system; - -import java.util.Iterator; -import java.util.List; -import org.apache.commons.lang3.ArrayUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.constant.UserConstants; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.domain.entity.SysDept; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.system.service.ISysDeptService; - -/** - * 部门信息 - * - * @author ruoyi - */ -@RestController -@RequestMapping("/system/dept") -public class SysDeptController extends BaseController -{ - @Autowired - private ISysDeptService deptService; - - /** - * 获取部门列表 - */ - @PreAuthorize("@ss.hasPermi('system:dept:list')") - @GetMapping("/list") - public AjaxResult list(SysDept dept) - { - List depts = deptService.selectDeptList(dept); - return AjaxResult.success(depts); - } - - /** - * 查询部门列表(排除节点) - */ - @PreAuthorize("@ss.hasPermi('system:dept:list')") - @GetMapping("/list/exclude/{deptId}") - public AjaxResult excludeChild(@PathVariable(value = "deptId", required = false) Long deptId) - { - List depts = deptService.selectDeptList(new SysDept()); - Iterator it = depts.iterator(); - while (it.hasNext()) - { - SysDept d = (SysDept) it.next(); - if (d.getDeptId().intValue() == deptId - || ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), deptId + "")) - { - it.remove(); - } - } - return AjaxResult.success(depts); - } - - /** - * 根据部门编号获取详细信息 - */ - @PreAuthorize("@ss.hasPermi('system:dept:query')") - @GetMapping(value = "/{deptId}") - public AjaxResult getInfo(@PathVariable Long deptId) - { - deptService.checkDeptDataScope(deptId); - return AjaxResult.success(deptService.selectDeptById(deptId)); - } - - /** - * 获取部门下拉树列表 - */ - @GetMapping("/treeselect") - public AjaxResult treeselect(SysDept dept) - { - List depts = deptService.selectDeptList(dept); - return AjaxResult.success(deptService.buildDeptTreeSelect(depts)); - } - - /** - * 加载对应角色部门列表树 - */ - @GetMapping(value = "/roleDeptTreeselect/{roleId}") - public AjaxResult roleDeptTreeselect(@PathVariable("roleId") Long roleId) - { - List depts = deptService.selectDeptList(new SysDept()); - AjaxResult ajax = AjaxResult.success(); - ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId)); - ajax.put("depts", deptService.buildDeptTreeSelect(depts)); - return ajax; - } - - /** - * 新增部门 - */ - @PreAuthorize("@ss.hasPermi('system:dept:add')") - @Log(title = "部门管理", businessType = BusinessType.INSERT) - @PostMapping - public AjaxResult add(@Validated @RequestBody SysDept dept) - { - if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) - { - return AjaxResult.error("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在"); - } - dept.setCreateBy(getUsername()); - return toAjax(deptService.insertDept(dept)); - } - - /** - * 修改部门 - */ - @PreAuthorize("@ss.hasPermi('system:dept:edit')") - @Log(title = "部门管理", businessType = BusinessType.UPDATE) - @PutMapping - public AjaxResult edit(@Validated @RequestBody SysDept dept) - { - if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) - { - return AjaxResult.error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在"); - } - else if (dept.getParentId().equals(dept.getDeptId())) - { - return AjaxResult.error("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己"); - } - else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus()) - && deptService.selectNormalChildrenDeptById(dept.getDeptId()) > 0) - { - return AjaxResult.error("该部门包含未停用的子部门!"); - } - dept.setUpdateBy(getUsername()); - return toAjax(deptService.updateDept(dept)); - } - - /** - * 删除部门 - */ - @PreAuthorize("@ss.hasPermi('system:dept:remove')") - @Log(title = "部门管理", businessType = BusinessType.DELETE) - @DeleteMapping("/{deptId}") - public AjaxResult remove(@PathVariable Long deptId) - { - if (deptService.hasChildByDeptId(deptId)) - { - return AjaxResult.error("存在下级部门,不允许删除"); - } - if (deptService.checkDeptExistUser(deptId)) - { - return AjaxResult.error("部门存在用户,不允许删除"); - } - return toAjax(deptService.deleteDeptById(deptId)); - } -} diff --git a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java b/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java deleted file mode 100644 index b53fe478..00000000 --- a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java +++ /dev/null @@ -1,121 +0,0 @@ -package com.ruoyi.web.controller.system; - -import java.util.ArrayList; -import java.util.List; -import javax.servlet.http.HttpServletResponse; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.domain.entity.SysDictData; -import com.ruoyi.common.core.page.TableDataInfo; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.system.service.ISysDictDataService; -import com.ruoyi.system.service.ISysDictTypeService; - -/** - * 数据字典信息 - * - * @author ruoyi - */ -@RestController -@RequestMapping("/system/dict/data") -public class SysDictDataController extends BaseController -{ - @Autowired - private ISysDictDataService dictDataService; - - @Autowired - private ISysDictTypeService dictTypeService; - - @PreAuthorize("@ss.hasPermi('system:dict:list')") - @GetMapping("/list") - public TableDataInfo list(SysDictData dictData) - { - startPage(); - List list = dictDataService.selectDictDataList(dictData); - return getDataTable(list); - } - - @Log(title = "字典数据", businessType = BusinessType.EXPORT) - @PreAuthorize("@ss.hasPermi('system:dict:export')") - @PostMapping("/export") - public void export(HttpServletResponse response, SysDictData dictData) - { - List list = dictDataService.selectDictDataList(dictData); - ExcelUtil util = new ExcelUtil(SysDictData.class); - util.exportExcel(response, list, "字典数据"); - } - - /** - * 查询字典数据详细 - */ - @PreAuthorize("@ss.hasPermi('system:dict:query')") - @GetMapping(value = "/{dictCode}") - public AjaxResult getInfo(@PathVariable Long dictCode) - { - return AjaxResult.success(dictDataService.selectDictDataById(dictCode)); - } - - /** - * 根据字典类型查询字典数据信息 - */ - @GetMapping(value = "/type/{dictType}") - public AjaxResult dictType(@PathVariable String dictType) - { - List data = dictTypeService.selectDictDataByType(dictType); - if (StringUtils.isNull(data)) - { - data = new ArrayList(); - } - return AjaxResult.success(data); - } - - /** - * 新增字典类型 - */ - @PreAuthorize("@ss.hasPermi('system:dict:add')") - @Log(title = "字典数据", businessType = BusinessType.INSERT) - @PostMapping - public AjaxResult add(@Validated @RequestBody SysDictData dict) - { - dict.setCreateBy(getUsername()); - return toAjax(dictDataService.insertDictData(dict)); - } - - /** - * 修改保存字典类型 - */ - @PreAuthorize("@ss.hasPermi('system:dict:edit')") - @Log(title = "字典数据", businessType = BusinessType.UPDATE) - @PutMapping - public AjaxResult edit(@Validated @RequestBody SysDictData dict) - { - dict.setUpdateBy(getUsername()); - return toAjax(dictDataService.updateDictData(dict)); - } - - /** - * 删除字典类型 - */ - @PreAuthorize("@ss.hasPermi('system:dict:remove')") - @Log(title = "字典类型", businessType = BusinessType.DELETE) - @DeleteMapping("/{dictCodes}") - public AjaxResult remove(@PathVariable Long[] dictCodes) - { - dictDataService.deleteDictDataByIds(dictCodes); - return success(); - } -} diff --git a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java b/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java deleted file mode 100644 index f8b7dbc0..00000000 --- a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java +++ /dev/null @@ -1,132 +0,0 @@ -package com.ruoyi.web.controller.system; - -import java.util.List; -import javax.servlet.http.HttpServletResponse; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.constant.UserConstants; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.domain.entity.SysDictType; -import com.ruoyi.common.core.page.TableDataInfo; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.system.service.ISysDictTypeService; - -/** - * 数据字典信息 - * - * @author ruoyi - */ -@RestController -@RequestMapping("/system/dict/type") -public class SysDictTypeController extends BaseController -{ - @Autowired - private ISysDictTypeService dictTypeService; - - @PreAuthorize("@ss.hasPermi('system:dict:list')") - @GetMapping("/list") - public TableDataInfo list(SysDictType dictType) - { - startPage(); - List list = dictTypeService.selectDictTypeList(dictType); - return getDataTable(list); - } - - @Log(title = "字典类型", businessType = BusinessType.EXPORT) - @PreAuthorize("@ss.hasPermi('system:dict:export')") - @PostMapping("/export") - public void export(HttpServletResponse response, SysDictType dictType) - { - List list = dictTypeService.selectDictTypeList(dictType); - ExcelUtil util = new ExcelUtil(SysDictType.class); - util.exportExcel(response, list, "字典类型"); - } - - /** - * 查询字典类型详细 - */ - @PreAuthorize("@ss.hasPermi('system:dict:query')") - @GetMapping(value = "/{dictId}") - public AjaxResult getInfo(@PathVariable Long dictId) - { - return AjaxResult.success(dictTypeService.selectDictTypeById(dictId)); - } - - /** - * 新增字典类型 - */ - @PreAuthorize("@ss.hasPermi('system:dict:add')") - @Log(title = "字典类型", businessType = BusinessType.INSERT) - @PostMapping - public AjaxResult add(@Validated @RequestBody SysDictType dict) - { - if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict))) - { - return AjaxResult.error("新增字典'" + dict.getDictName() + "'失败,字典类型已存在"); - } - dict.setCreateBy(getUsername()); - return toAjax(dictTypeService.insertDictType(dict)); - } - - /** - * 修改字典类型 - */ - @PreAuthorize("@ss.hasPermi('system:dict:edit')") - @Log(title = "字典类型", businessType = BusinessType.UPDATE) - @PutMapping - public AjaxResult edit(@Validated @RequestBody SysDictType dict) - { - if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict))) - { - return AjaxResult.error("修改字典'" + dict.getDictName() + "'失败,字典类型已存在"); - } - dict.setUpdateBy(getUsername()); - return toAjax(dictTypeService.updateDictType(dict)); - } - - /** - * 删除字典类型 - */ - @PreAuthorize("@ss.hasPermi('system:dict:remove')") - @Log(title = "字典类型", businessType = BusinessType.DELETE) - @DeleteMapping("/{dictIds}") - public AjaxResult remove(@PathVariable Long[] dictIds) - { - dictTypeService.deleteDictTypeByIds(dictIds); - return success(); - } - - /** - * 刷新字典缓存 - */ - @PreAuthorize("@ss.hasPermi('system:dict:remove')") - @Log(title = "字典类型", businessType = BusinessType.CLEAN) - @DeleteMapping("/refreshCache") - public AjaxResult refreshCache() - { - dictTypeService.resetDictCache(); - return AjaxResult.success(); - } - - /** - * 获取字典选择框列表 - */ - @GetMapping("/optionselect") - public AjaxResult optionselect() - { - List dictTypes = dictTypeService.selectDictTypeAll(); - return AjaxResult.success(dictTypes); - } -} diff --git a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java b/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java deleted file mode 100644 index 13007eb1..00000000 --- a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.ruoyi.web.controller.system; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.config.RuoYiConfig; -import com.ruoyi.common.utils.StringUtils; - -/** - * 首页 - * - * @author ruoyi - */ -@RestController -public class SysIndexController -{ - /** 系统基础配置 */ - @Autowired - private RuoYiConfig ruoyiConfig; - - /** - * 访问首页,提示语 - */ - @RequestMapping("/") - public String index() - { - return StringUtils.format("欢迎使用{}后台管理框架,当前版本:v{},请通过前端地址访问。", ruoyiConfig.getName(), ruoyiConfig.getVersion()); - } -} diff --git a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java b/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java deleted file mode 100644 index d959a17e..00000000 --- a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.ruoyi.web.controller.system; - -import java.util.List; -import java.util.Set; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.domain.entity.SysMenu; -import com.ruoyi.common.core.domain.entity.SysUser; -import com.ruoyi.common.core.domain.model.LoginBody; -import com.ruoyi.common.utils.SecurityUtils; -import com.ruoyi.framework.web.service.SysLoginService; -import com.ruoyi.framework.web.service.SysPermissionService; -import com.ruoyi.system.service.ISysMenuService; - -/** - * 登录验证 - * - * @author ruoyi - */ -@RestController -public class SysLoginController -{ - @Autowired - private SysLoginService loginService; - - @Autowired - private ISysMenuService menuService; - - @Autowired - private SysPermissionService permissionService; - - /** - * 登录方法 - * - * @param loginBody 登录信息 - * @return 结果 - */ - @PostMapping("/login") - public AjaxResult login(@RequestBody LoginBody loginBody) - { - AjaxResult ajax = AjaxResult.success(); - // 生成令牌 - String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(), - loginBody.getUuid()); - ajax.put(Constants.TOKEN, token); - return ajax; - } - - /** - * 获取用户信息 - * - * @return 用户信息 - */ - @GetMapping("getInfo") - public AjaxResult getInfo() - { - SysUser user = SecurityUtils.getLoginUser().getUser(); - // 角色集合 - Set roles = permissionService.getRolePermission(user); - // 权限集合 - Set permissions = permissionService.getMenuPermission(user); - AjaxResult ajax = AjaxResult.success(); - ajax.put("user", user); - ajax.put("roles", roles); - ajax.put("permissions", permissions); - return ajax; - } - - /** - * 获取路由信息 - * - * @return 路由信息 - */ - @GetMapping("getRouters") - public AjaxResult getRouters() - { - Long userId = SecurityUtils.getUserId(); - List menus = menuService.selectMenuTreeByUserId(userId); - return AjaxResult.success(menuService.buildMenus(menus)); - } -} diff --git a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java b/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java deleted file mode 100644 index 4a9f73f8..00000000 --- a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java +++ /dev/null @@ -1,142 +0,0 @@ -package com.ruoyi.web.controller.system; - -import java.util.List; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.constant.UserConstants; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.domain.entity.SysMenu; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.system.service.ISysMenuService; - -/** - * 菜单信息 - * - * @author ruoyi - */ -@RestController -@RequestMapping("/system/menu") -public class SysMenuController extends BaseController -{ - @Autowired - private ISysMenuService menuService; - - /** - * 获取菜单列表 - */ - @PreAuthorize("@ss.hasPermi('system:menu:list')") - @GetMapping("/list") - public AjaxResult list(SysMenu menu) - { - List menus = menuService.selectMenuList(menu, getUserId()); - return AjaxResult.success(menus); - } - - /** - * 根据菜单编号获取详细信息 - */ - @PreAuthorize("@ss.hasPermi('system:menu:query')") - @GetMapping(value = "/{menuId}") - public AjaxResult getInfo(@PathVariable Long menuId) - { - return AjaxResult.success(menuService.selectMenuById(menuId)); - } - - /** - * 获取菜单下拉树列表 - */ - @GetMapping("/treeselect") - public AjaxResult treeselect(SysMenu menu) - { - List menus = menuService.selectMenuList(menu, getUserId()); - return AjaxResult.success(menuService.buildMenuTreeSelect(menus)); - } - - /** - * 加载对应角色菜单列表树 - */ - @GetMapping(value = "/roleMenuTreeselect/{roleId}") - public AjaxResult roleMenuTreeselect(@PathVariable("roleId") Long roleId) - { - List menus = menuService.selectMenuList(getUserId()); - AjaxResult ajax = AjaxResult.success(); - ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId)); - ajax.put("menus", menuService.buildMenuTreeSelect(menus)); - return ajax; - } - - /** - * 新增菜单 - */ - @PreAuthorize("@ss.hasPermi('system:menu:add')") - @Log(title = "菜单管理", businessType = BusinessType.INSERT) - @PostMapping - public AjaxResult add(@Validated @RequestBody SysMenu menu) - { - if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu))) - { - return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); - } - else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) - { - return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头"); - } - menu.setCreateBy(getUsername()); - return toAjax(menuService.insertMenu(menu)); - } - - /** - * 修改菜单 - */ - @PreAuthorize("@ss.hasPermi('system:menu:edit')") - @Log(title = "菜单管理", businessType = BusinessType.UPDATE) - @PutMapping - public AjaxResult edit(@Validated @RequestBody SysMenu menu) - { - if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu))) - { - return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); - } - else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) - { - return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头"); - } - else if (menu.getMenuId().equals(menu.getParentId())) - { - return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己"); - } - menu.setUpdateBy(getUsername()); - return toAjax(menuService.updateMenu(menu)); - } - - /** - * 删除菜单 - */ - @PreAuthorize("@ss.hasPermi('system:menu:remove')") - @Log(title = "菜单管理", businessType = BusinessType.DELETE) - @DeleteMapping("/{menuId}") - public AjaxResult remove(@PathVariable("menuId") Long menuId) - { - if (menuService.hasChildByMenuId(menuId)) - { - return AjaxResult.error("存在子菜单,不允许删除"); - } - if (menuService.checkMenuExistRole(menuId)) - { - return AjaxResult.error("菜单已分配,不允许删除"); - } - return toAjax(menuService.deleteMenuById(menuId)); - } -} \ No newline at end of file diff --git a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java b/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java deleted file mode 100644 index 4da9f04b..00000000 --- a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.ruoyi.web.controller.system; - -import java.util.List; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.page.TableDataInfo; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.system.domain.SysNotice; -import com.ruoyi.system.service.ISysNoticeService; - -/** - * 公告 信息操作处理 - * - * @author ruoyi - */ -@RestController -@RequestMapping("/system/notice") -public class SysNoticeController extends BaseController -{ - @Autowired - private ISysNoticeService noticeService; - - /** - * 获取通知公告列表 - */ - @PreAuthorize("@ss.hasPermi('system:notice:list')") - @GetMapping("/list") - public TableDataInfo list(SysNotice notice) - { - startPage(); - List list = noticeService.selectNoticeList(notice); - return getDataTable(list); - } - - /** - * 根据通知公告编号获取详细信息 - */ - @PreAuthorize("@ss.hasPermi('system:notice:query')") - @GetMapping(value = "/{noticeId}") - public AjaxResult getInfo(@PathVariable Long noticeId) - { - return AjaxResult.success(noticeService.selectNoticeById(noticeId)); - } - - /** - * 新增通知公告 - */ - @PreAuthorize("@ss.hasPermi('system:notice:add')") - @Log(title = "通知公告", businessType = BusinessType.INSERT) - @PostMapping - public AjaxResult add(@Validated @RequestBody SysNotice notice) - { - notice.setCreateBy(getUsername()); - return toAjax(noticeService.insertNotice(notice)); - } - - /** - * 修改通知公告 - */ - @PreAuthorize("@ss.hasPermi('system:notice:edit')") - @Log(title = "通知公告", businessType = BusinessType.UPDATE) - @PutMapping - public AjaxResult edit(@Validated @RequestBody SysNotice notice) - { - notice.setUpdateBy(getUsername()); - return toAjax(noticeService.updateNotice(notice)); - } - - /** - * 删除通知公告 - */ - @PreAuthorize("@ss.hasPermi('system:notice:remove')") - @Log(title = "通知公告", businessType = BusinessType.DELETE) - @DeleteMapping("/{noticeIds}") - public AjaxResult remove(@PathVariable Long[] noticeIds) - { - return toAjax(noticeService.deleteNoticeByIds(noticeIds)); - } -} diff --git a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java b/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java deleted file mode 100644 index f73cea4d..00000000 --- a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java +++ /dev/null @@ -1,130 +0,0 @@ -package com.ruoyi.web.controller.system; - -import java.util.List; -import javax.servlet.http.HttpServletResponse; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.constant.UserConstants; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.page.TableDataInfo; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.system.domain.SysPost; -import com.ruoyi.system.service.ISysPostService; - -/** - * 岗位信息操作处理 - * - * @author ruoyi - */ -@RestController -@RequestMapping("/system/post") -public class SysPostController extends BaseController -{ - @Autowired - private ISysPostService postService; - - /** - * 获取岗位列表 - */ - @PreAuthorize("@ss.hasPermi('system:post:list')") - @GetMapping("/list") - public TableDataInfo list(SysPost post) - { - startPage(); - List list = postService.selectPostList(post); - return getDataTable(list); - } - - @Log(title = "岗位管理", businessType = BusinessType.EXPORT) - @PreAuthorize("@ss.hasPermi('system:post:export')") - @PostMapping("/export") - public void export(HttpServletResponse response, SysPost post) - { - List list = postService.selectPostList(post); - ExcelUtil util = new ExcelUtil(SysPost.class); - util.exportExcel(response, list, "岗位数据"); - } - - /** - * 根据岗位编号获取详细信息 - */ - @PreAuthorize("@ss.hasPermi('system:post:query')") - @GetMapping(value = "/{postId}") - public AjaxResult getInfo(@PathVariable Long postId) - { - return AjaxResult.success(postService.selectPostById(postId)); - } - - /** - * 新增岗位 - */ - @PreAuthorize("@ss.hasPermi('system:post:add')") - @Log(title = "岗位管理", businessType = BusinessType.INSERT) - @PostMapping - public AjaxResult add(@Validated @RequestBody SysPost post) - { - if (UserConstants.NOT_UNIQUE.equals(postService.checkPostNameUnique(post))) - { - return AjaxResult.error("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在"); - } - else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post))) - { - return AjaxResult.error("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在"); - } - post.setCreateBy(getUsername()); - return toAjax(postService.insertPost(post)); - } - - /** - * 修改岗位 - */ - @PreAuthorize("@ss.hasPermi('system:post:edit')") - @Log(title = "岗位管理", businessType = BusinessType.UPDATE) - @PutMapping - public AjaxResult edit(@Validated @RequestBody SysPost post) - { - if (UserConstants.NOT_UNIQUE.equals(postService.checkPostNameUnique(post))) - { - return AjaxResult.error("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在"); - } - else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post))) - { - return AjaxResult.error("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在"); - } - post.setUpdateBy(getUsername()); - return toAjax(postService.updatePost(post)); - } - - /** - * 删除岗位 - */ - @PreAuthorize("@ss.hasPermi('system:post:remove')") - @Log(title = "岗位管理", businessType = BusinessType.DELETE) - @DeleteMapping("/{postIds}") - public AjaxResult remove(@PathVariable Long[] postIds) - { - return toAjax(postService.deletePostByIds(postIds)); - } - - /** - * 获取岗位选择框列表 - */ - @GetMapping("/optionselect") - public AjaxResult optionselect() - { - List posts = postService.selectPostAll(); - return AjaxResult.success(posts); - } -} diff --git a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java b/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java deleted file mode 100644 index 6473df33..00000000 --- a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java +++ /dev/null @@ -1,140 +0,0 @@ -package com.ruoyi.web.controller.system; - -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.config.RuoYiConfig; -import com.ruoyi.common.constant.UserConstants; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.domain.entity.SysUser; -import com.ruoyi.common.core.domain.model.LoginUser; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.common.utils.SecurityUtils; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.file.FileUploadUtils; -import com.ruoyi.framework.web.service.TokenService; -import com.ruoyi.iot.service.IUserSocialProfileService; -import com.ruoyi.system.service.ISysUserService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import java.io.IOException; - -/** - * 个人信息 业务处理 - * - * @author ruoyi - */ -@RestController -@RequestMapping("/system/user/profile") -public class SysProfileController extends BaseController { - @Autowired - private ISysUserService userService; - - @Autowired - private TokenService tokenService; - - @Autowired - private IUserSocialProfileService iUserSocialProfileService; - - /** - * 个人信息 - */ - @GetMapping - public AjaxResult profile() { - LoginUser loginUser = getLoginUser(); - SysUser user = loginUser.getUser(); - AjaxResult ajax = AjaxResult.success(user); - ajax.put("roleGroup", userService.selectUserRoleGroup(loginUser.getUsername())); - ajax.put("postGroup", userService.selectUserPostGroup(loginUser.getUsername())); - ajax.put("socialGroup", iUserSocialProfileService.selectUserSocialProfile(loginUser.getUserId())); - return ajax; - } - - /** - * 修改用户 - */ - @Log(title = "个人信息", businessType = BusinessType.UPDATE) - @PutMapping - public AjaxResult updateProfile(@RequestBody SysUser user) - { - LoginUser loginUser = getLoginUser(); - SysUser sysUser = loginUser.getUser(); - user.setUserName(sysUser.getUserName()); - if (StringUtils.isNotEmpty(user.getPhonenumber()) - && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) - { - return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); - } - if (StringUtils.isNotEmpty(user.getEmail()) - && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) - { - return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); - } - user.setUserId(sysUser.getUserId()); - user.setPassword(null); - if (userService.updateUserProfile(user) > 0) - { - // 更新缓存用户信息 - sysUser.setNickName(user.getNickName()); - sysUser.setPhonenumber(user.getPhonenumber()); - sysUser.setEmail(user.getEmail()); - sysUser.setSex(user.getSex()); - tokenService.setLoginUser(loginUser); - return AjaxResult.success(); - } - return AjaxResult.error("修改个人信息异常,请联系管理员"); - } - - /** - * 重置密码 - */ - @Log(title = "个人信息", businessType = BusinessType.UPDATE) - @PutMapping("/updatePwd") - public AjaxResult updatePwd(String oldPassword, String newPassword) - { - LoginUser loginUser = getLoginUser(); - String userName = loginUser.getUsername(); - String password = loginUser.getPassword(); - if (!SecurityUtils.matchesPassword(oldPassword, password)) - { - return AjaxResult.error("修改密码失败,旧密码错误"); - } - if (SecurityUtils.matchesPassword(newPassword, password)) - { - return AjaxResult.error("新密码不能与旧密码相同"); - } - if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0) - { - // 更新缓存用户密码 - loginUser.getUser().setPassword(SecurityUtils.encryptPassword(newPassword)); - tokenService.setLoginUser(loginUser); - return AjaxResult.success(); - } - return AjaxResult.error("修改密码异常,请联系管理员"); - } - - /** - * 头像上传 - */ - @Log(title = "用户头像", businessType = BusinessType.UPDATE) - @PostMapping("/avatar") - public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws IOException - { - if (!file.isEmpty()) - { - LoginUser loginUser = getLoginUser(); - String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file); - if (userService.updateUserAvatar(loginUser.getUsername(), avatar)) - { - AjaxResult ajax = AjaxResult.success(); - ajax.put("imgUrl", avatar); - // 更新缓存用户头像 - loginUser.getUser().setAvatar(avatar); - tokenService.setLoginUser(loginUser); - return ajax; - } - } - return AjaxResult.error("上传图片异常,请联系管理员"); - } -} diff --git a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java b/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java deleted file mode 100644 index fe192492..00000000 --- a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.ruoyi.web.controller.system; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.domain.model.RegisterBody; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.framework.web.service.SysRegisterService; -import com.ruoyi.system.service.ISysConfigService; - -/** - * 注册验证 - * - * @author ruoyi - */ -@RestController -public class SysRegisterController extends BaseController -{ - @Autowired - private SysRegisterService registerService; - - @Autowired - private ISysConfigService configService; - - @PostMapping("/register") - public AjaxResult register(@RequestBody RegisterBody user) - { - if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser")))) - { - return error("当前系统没有开启注册功能!"); - } - String msg = registerService.register(user); - return StringUtils.isEmpty(msg) ? success() : error(msg); - } -} diff --git a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java b/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java deleted file mode 100644 index a5948deb..00000000 --- a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java +++ /dev/null @@ -1,241 +0,0 @@ -package com.ruoyi.web.controller.system; - -import java.util.List; -import javax.servlet.http.HttpServletResponse; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.constant.UserConstants; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.domain.entity.SysRole; -import com.ruoyi.common.core.domain.entity.SysUser; -import com.ruoyi.common.core.domain.model.LoginUser; -import com.ruoyi.common.core.page.TableDataInfo; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.framework.web.service.SysPermissionService; -import com.ruoyi.framework.web.service.TokenService; -import com.ruoyi.system.domain.SysUserRole; -import com.ruoyi.system.service.ISysRoleService; -import com.ruoyi.system.service.ISysUserService; - -/** - * 角色信息 - * - * @author ruoyi - */ -@RestController -@RequestMapping("/system/role") -public class SysRoleController extends BaseController -{ - @Autowired - private ISysRoleService roleService; - - @Autowired - private TokenService tokenService; - - @Autowired - private SysPermissionService permissionService; - - @Autowired - private ISysUserService userService; - - @PreAuthorize("@ss.hasPermi('system:role:list')") - @GetMapping("/list") - public TableDataInfo list(SysRole role) - { - startPage(); - List list = roleService.selectRoleList(role); - return getDataTable(list); - } - - @Log(title = "角色管理", businessType = BusinessType.EXPORT) - @PreAuthorize("@ss.hasPermi('system:role:export')") - @PostMapping("/export") - public void export(HttpServletResponse response, SysRole role) - { - List list = roleService.selectRoleList(role); - ExcelUtil util = new ExcelUtil(SysRole.class); - util.exportExcel(response, list, "角色数据"); - } - - /** - * 根据角色编号获取详细信息 - */ - @PreAuthorize("@ss.hasPermi('system:role:query')") - @GetMapping(value = "/{roleId}") - public AjaxResult getInfo(@PathVariable Long roleId) - { - roleService.checkRoleDataScope(roleId); - return AjaxResult.success(roleService.selectRoleById(roleId)); - } - - /** - * 新增角色 - */ - @PreAuthorize("@ss.hasPermi('system:role:add')") - @Log(title = "角色管理", businessType = BusinessType.INSERT) - @PostMapping - public AjaxResult add(@Validated @RequestBody SysRole role) - { - if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) - { - return AjaxResult.error("新增角色'" + role.getRoleName() + "'失败,角色名称已存在"); - } - else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) - { - return AjaxResult.error("新增角色'" + role.getRoleName() + "'失败,角色权限已存在"); - } - role.setCreateBy(getUsername()); - return toAjax(roleService.insertRole(role)); - - } - - /** - * 修改保存角色 - */ - @PreAuthorize("@ss.hasPermi('system:role:edit')") - @Log(title = "角色管理", businessType = BusinessType.UPDATE) - @PutMapping - public AjaxResult edit(@Validated @RequestBody SysRole role) - { - roleService.checkRoleAllowed(role); - if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) - { - return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在"); - } - else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) - { - return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在"); - } - role.setUpdateBy(getUsername()); - - if (roleService.updateRole(role) > 0) - { - // 更新缓存用户权限 - LoginUser loginUser = getLoginUser(); - if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin()) - { - loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser())); - loginUser.setUser(userService.selectUserByUserName(loginUser.getUser().getUserName())); - tokenService.setLoginUser(loginUser); - } - return AjaxResult.success(); - } - return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,请联系管理员"); - } - - /** - * 修改保存数据权限 - */ - @PreAuthorize("@ss.hasPermi('system:role:edit')") - @Log(title = "角色管理", businessType = BusinessType.UPDATE) - @PutMapping("/dataScope") - public AjaxResult dataScope(@RequestBody SysRole role) - { - roleService.checkRoleAllowed(role); - return toAjax(roleService.authDataScope(role)); - } - - /** - * 状态修改 - */ - @PreAuthorize("@ss.hasPermi('system:role:edit')") - @Log(title = "角色管理", businessType = BusinessType.UPDATE) - @PutMapping("/changeStatus") - public AjaxResult changeStatus(@RequestBody SysRole role) - { - roleService.checkRoleAllowed(role); - role.setUpdateBy(getUsername()); - return toAjax(roleService.updateRoleStatus(role)); - } - - /** - * 删除角色 - */ - @PreAuthorize("@ss.hasPermi('system:role:remove')") - @Log(title = "角色管理", businessType = BusinessType.DELETE) - @DeleteMapping("/{roleIds}") - public AjaxResult remove(@PathVariable Long[] roleIds) - { - return toAjax(roleService.deleteRoleByIds(roleIds)); - } - - /** - * 获取角色选择框列表 - */ - @PreAuthorize("@ss.hasPermi('system:role:query')") - @GetMapping("/optionselect") - public AjaxResult optionselect() - { - return AjaxResult.success(roleService.selectRoleAll()); - } - - /** - * 查询已分配用户角色列表 - */ - @PreAuthorize("@ss.hasPermi('system:role:list')") - @GetMapping("/authUser/allocatedList") - public TableDataInfo allocatedList(SysUser user) - { - startPage(); - List list = userService.selectAllocatedList(user); - return getDataTable(list); - } - - /** - * 查询未分配用户角色列表 - */ - @PreAuthorize("@ss.hasPermi('system:role:list')") - @GetMapping("/authUser/unallocatedList") - public TableDataInfo unallocatedList(SysUser user) - { - startPage(); - List list = userService.selectUnallocatedList(user); - return getDataTable(list); - } - - /** - * 取消授权用户 - */ - @PreAuthorize("@ss.hasPermi('system:role:edit')") - @Log(title = "角色管理", businessType = BusinessType.GRANT) - @PutMapping("/authUser/cancel") - public AjaxResult cancelAuthUser(@RequestBody SysUserRole userRole) - { - return toAjax(roleService.deleteAuthUser(userRole)); - } - - /** - * 批量取消授权用户 - */ - @PreAuthorize("@ss.hasPermi('system:role:edit')") - @Log(title = "角色管理", businessType = BusinessType.GRANT) - @PutMapping("/authUser/cancelAll") - public AjaxResult cancelAuthUserAll(Long roleId, Long[] userIds) - { - return toAjax(roleService.deleteAuthUsers(roleId, userIds)); - } - - /** - * 批量选择用户授权 - */ - @PreAuthorize("@ss.hasPermi('system:role:edit')") - @Log(title = "角色管理", businessType = BusinessType.GRANT) - @PutMapping("/authUser/selectAll") - public AjaxResult selectAuthUserAll(Long roleId, Long[] userIds) - { - return toAjax(roleService.insertAuthUsers(roleId, userIds)); - } -} diff --git a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java b/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java deleted file mode 100644 index 688e57a7..00000000 --- a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java +++ /dev/null @@ -1,232 +0,0 @@ -package com.ruoyi.web.controller.system; - -import java.util.List; -import java.util.stream.Collectors; -import javax.servlet.http.HttpServletResponse; -import org.apache.commons.lang3.ArrayUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.multipart.MultipartFile; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.constant.UserConstants; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.domain.entity.SysRole; -import com.ruoyi.common.core.domain.entity.SysUser; -import com.ruoyi.common.core.page.TableDataInfo; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.common.utils.SecurityUtils; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.system.service.ISysPostService; -import com.ruoyi.system.service.ISysRoleService; -import com.ruoyi.system.service.ISysUserService; - -/** - * 用户信息 - * - * @author ruoyi - */ -@RestController -@RequestMapping("/system/user") -public class SysUserController extends BaseController -{ - @Autowired - private ISysUserService userService; - - @Autowired - private ISysRoleService roleService; - - @Autowired - private ISysPostService postService; - - /** - * 获取用户列表 - */ - @PreAuthorize("@ss.hasPermi('system:user:list')") - @GetMapping("/list") - public TableDataInfo list(SysUser user) - { - startPage(); - List list = userService.selectUserList(user); - return getDataTable(list); - } - - @Log(title = "用户管理", businessType = BusinessType.EXPORT) - @PreAuthorize("@ss.hasPermi('system:user:export')") - @PostMapping("/export") - public void export(HttpServletResponse response, SysUser user) - { - List list = userService.selectUserList(user); - ExcelUtil util = new ExcelUtil(SysUser.class); - util.exportExcel(response, list, "用户数据"); - } - - @Log(title = "用户管理", businessType = BusinessType.IMPORT) - @PreAuthorize("@ss.hasPermi('system:user:import')") - @PostMapping("/importData") - public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception - { - ExcelUtil util = new ExcelUtil(SysUser.class); - List userList = util.importExcel(file.getInputStream()); - String operName = getUsername(); - String message = userService.importUser(userList, updateSupport, operName); - return AjaxResult.success(message); - } - - @PostMapping("/importTemplate") - public void importTemplate(HttpServletResponse response) - { - ExcelUtil util = new ExcelUtil(SysUser.class); - util.importTemplateExcel(response, "用户数据"); - } - - /** - * 根据用户编号获取详细信息 - */ - @PreAuthorize("@ss.hasPermi('system:user:query')") - @GetMapping(value = { "/", "/{userId}" }) - public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId) - { - userService.checkUserDataScope(userId); - AjaxResult ajax = AjaxResult.success(); - List roles = roleService.selectRoleAll(); - ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); - ajax.put("posts", postService.selectPostAll()); - if (StringUtils.isNotNull(userId)) - { - ajax.put(AjaxResult.DATA_TAG, userService.selectUserById(userId)); - ajax.put("postIds", postService.selectPostListByUserId(userId)); - ajax.put("roleIds", roleService.selectRoleListByUserId(userId)); - } - return ajax; - } - - /** - * 新增用户 - */ - @PreAuthorize("@ss.hasPermi('system:user:add')") - @Log(title = "用户管理", businessType = BusinessType.INSERT) - @PostMapping - public AjaxResult add(@Validated @RequestBody SysUser user) - { - if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user.getUserName()))) - { - return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,登录账号已存在"); - } - else if (StringUtils.isNotEmpty(user.getPhonenumber()) - && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) - { - return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,手机号码已存在"); - } - else if (StringUtils.isNotEmpty(user.getEmail()) - && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) - { - return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在"); - } - user.setCreateBy(getUsername()); - user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); - return toAjax(userService.insertUser(user)); - } - - /** - * 修改用户 - */ - @PreAuthorize("@ss.hasPermi('system:user:edit')") - @Log(title = "用户管理", businessType = BusinessType.UPDATE) - @PutMapping - public AjaxResult edit(@Validated @RequestBody SysUser user) - { - userService.checkUserAllowed(user); - if (StringUtils.isNotEmpty(user.getPhonenumber()) - && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) - { - return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); - } - else if (StringUtils.isNotEmpty(user.getEmail()) - && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) - { - return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); - } - user.setUpdateBy(getUsername()); - return toAjax(userService.updateUser(user)); - } - - /** - * 删除用户 - */ - @PreAuthorize("@ss.hasPermi('system:user:remove')") - @Log(title = "用户管理", businessType = BusinessType.DELETE) - @DeleteMapping("/{userIds}") - public AjaxResult remove(@PathVariable Long[] userIds) - { - if (ArrayUtils.contains(userIds, getUserId())) - { - return error("当前用户不能删除"); - } - return toAjax(userService.deleteUserByIds(userIds)); - } - - /** - * 重置密码 - */ - @PreAuthorize("@ss.hasPermi('system:user:resetPwd')") - @Log(title = "用户管理", businessType = BusinessType.UPDATE) - @PutMapping("/resetPwd") - public AjaxResult resetPwd(@RequestBody SysUser user) - { - userService.checkUserAllowed(user); - user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); - user.setUpdateBy(getUsername()); - return toAjax(userService.resetPwd(user)); - } - - /** - * 状态修改 - */ - @PreAuthorize("@ss.hasPermi('system:user:edit')") - @Log(title = "用户管理", businessType = BusinessType.UPDATE) - @PutMapping("/changeStatus") - public AjaxResult changeStatus(@RequestBody SysUser user) - { - userService.checkUserAllowed(user); - user.setUpdateBy(getUsername()); - return toAjax(userService.updateUserStatus(user)); - } - - /** - * 根据用户编号获取授权角色 - */ - @PreAuthorize("@ss.hasPermi('system:user:query')") - @GetMapping("/authRole/{userId}") - public AjaxResult authRole(@PathVariable("userId") Long userId) - { - AjaxResult ajax = AjaxResult.success(); - SysUser user = userService.selectUserById(userId); - List roles = roleService.selectRolesByUserId(userId); - ajax.put("user", user); - ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); - return ajax; - } - - /** - * 用户授权角色 - */ - @PreAuthorize("@ss.hasPermi('system:user:edit')") - @Log(title = "用户管理", businessType = BusinessType.GRANT) - @PutMapping("/authRole") - public AjaxResult insertAuthRole(Long userId, Long[] roleIds) - { - userService.insertUserAuth(userId, roleIds); - return success(); - } -} diff --git a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/tool/SwaggerController.java b/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/tool/SwaggerController.java deleted file mode 100644 index f66ca24e..00000000 --- a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/tool/SwaggerController.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.ruoyi.web.controller.tool; - -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import com.ruoyi.common.core.controller.BaseController; - -/** - * swagger 接口 - * - * @author ruoyi - */ -@Controller -@RequestMapping("/tool/swagger") -public class SwaggerController extends BaseController -{ - @PreAuthorize("@ss.hasPermi('tool:swagger:view')") - @GetMapping() - public String index() - { - return redirect("/swagger-ui.html"); - } -} diff --git a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java b/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java deleted file mode 100644 index 3361ef90..00000000 --- a/springboot/wumei-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java +++ /dev/null @@ -1,181 +0,0 @@ -package com.ruoyi.web.controller.tool; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.utils.StringUtils; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiImplicitParam; -import io.swagger.annotations.ApiImplicitParams; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import io.swagger.annotations.ApiOperation; - -/** - * swagger 用户测试方法 - * - * @author ruoyi - */ -@Api("用户信息管理") -@RestController -@RequestMapping("/test/user") -public class TestController extends BaseController -{ - private final static Map users = new LinkedHashMap(); - { - users.put(1, new UserEntity(1, "admin", "admin123", "15888888888")); - users.put(2, new UserEntity(2, "ry", "admin123", "15666666666")); - } - - @ApiOperation("获取用户列表") - @GetMapping("/list") - public AjaxResult userList() - { - List userList = new ArrayList(users.values()); - return AjaxResult.success(userList); - } - - @ApiOperation("获取用户详细") - @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class) - @GetMapping("/{userId}") - public AjaxResult getUser(@PathVariable Integer userId) - { - if (!users.isEmpty() && users.containsKey(userId)) - { - return AjaxResult.success(users.get(userId)); - } - else - { - return error("用户不存在"); - } - } - - @ApiOperation("新增用户") - @ApiImplicitParams({ - @ApiImplicitParam(name = "userId", value = "用户id", dataType = "Integer", dataTypeClass = Integer.class), - @ApiImplicitParam(name = "username", value = "用户名称", dataType = "String", dataTypeClass = String.class), - @ApiImplicitParam(name = "password", value = "用户密码", dataType = "String", dataTypeClass = String.class), - @ApiImplicitParam(name = "mobile", value = "用户手机", dataType = "String", dataTypeClass = String.class) - }) - @PostMapping("/save") - public AjaxResult save(UserEntity user) - { - if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId())) - { - return error("用户ID不能为空"); - } - return AjaxResult.success(users.put(user.getUserId(), user)); - } - - @ApiOperation("更新用户") - @PutMapping("/update") - public AjaxResult update(@RequestBody UserEntity user) - { - if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId())) - { - return error("用户ID不能为空"); - } - if (users.isEmpty() || !users.containsKey(user.getUserId())) - { - return error("用户不存在"); - } - users.remove(user.getUserId()); - return AjaxResult.success(users.put(user.getUserId(), user)); - } - - @ApiOperation("删除用户信息") - @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class) - @DeleteMapping("/{userId}") - public AjaxResult delete(@PathVariable Integer userId) - { - if (!users.isEmpty() && users.containsKey(userId)) - { - users.remove(userId); - return success(); - } - else - { - return error("用户不存在"); - } - } -} - -@ApiModel(value = "UserEntity", description = "用户实体") -class UserEntity -{ - @ApiModelProperty("用户ID") - private Integer userId; - - @ApiModelProperty("用户名称") - private String username; - - @ApiModelProperty("用户密码") - private String password; - - @ApiModelProperty("用户手机") - private String mobile; - - public UserEntity() - { - - } - - public UserEntity(Integer userId, String username, String password, String mobile) - { - this.userId = userId; - this.username = username; - this.password = password; - this.mobile = mobile; - } - - public Integer getUserId() - { - return userId; - } - - public void setUserId(Integer userId) - { - this.userId = userId; - } - - public String getUsername() - { - return username; - } - - public void setUsername(String username) - { - this.username = username; - } - - public String getPassword() - { - return password; - } - - public void setPassword(String password) - { - this.password = password; - } - - public String getMobile() - { - return mobile; - } - - public void setMobile(String mobile) - { - this.mobile = mobile; - } -} diff --git a/springboot/wumei-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java b/springboot/wumei-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java deleted file mode 100644 index 8b6bcb8c..00000000 --- a/springboot/wumei-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java +++ /dev/null @@ -1,125 +0,0 @@ -package com.ruoyi.web.core.config; - -import java.util.ArrayList; -import java.util.List; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import com.ruoyi.common.config.RuoYiConfig; -import io.swagger.annotations.ApiOperation; -import io.swagger.models.auth.In; -import springfox.documentation.builders.ApiInfoBuilder; -import springfox.documentation.builders.PathSelectors; -import springfox.documentation.builders.RequestHandlerSelectors; -import springfox.documentation.service.ApiInfo; -import springfox.documentation.service.ApiKey; -import springfox.documentation.service.AuthorizationScope; -import springfox.documentation.service.Contact; -import springfox.documentation.service.SecurityReference; -import springfox.documentation.service.SecurityScheme; -import springfox.documentation.spi.DocumentationType; -import springfox.documentation.spi.service.contexts.SecurityContext; -import springfox.documentation.spring.web.plugins.Docket; - -/** - * Swagger2的接口配置 - * - * @author ruoyi - */ -@Configuration -public class SwaggerConfig -{ - /** 系统基础配置 */ - @Autowired - private RuoYiConfig ruoyiConfig; - - /** 是否开启swagger */ - @Value("${swagger.enabled}") - private boolean enabled; - - /** 设置请求的统一前缀 */ - @Value("${swagger.pathMapping}") - private String pathMapping; - - /** - * 创建API - */ - @Bean - public Docket createRestApi() - { - return new Docket(DocumentationType.OAS_30) - // 是否启用Swagger - .enable(enabled) - // 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息) - .apiInfo(apiInfo()) - // 设置哪些接口暴露给Swagger展示 - .select() - // 扫描所有有注解的api,用这种方式更灵活 - .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) - // 扫描指定包中的swagger注解 - // .apis(RequestHandlerSelectors.basePackage("com.ruoyi.project.tool.swagger")) - // 扫描所有 .apis(RequestHandlerSelectors.any()) - .paths(PathSelectors.any()) - .build() - /* 设置安全模式,swagger可以设置访问token */ - .securitySchemes(securitySchemes()) - .securityContexts(securityContexts()) - .pathMapping(pathMapping); - } - - /** - * 安全模式,这里指定token通过Authorization头请求头传递 - */ - private List securitySchemes() - { - List apiKeyList = new ArrayList(); - apiKeyList.add(new ApiKey("Authorization", "Authorization", In.HEADER.toValue())); - return apiKeyList; - } - - /** - * 安全上下文 - */ - private List securityContexts() - { - List securityContexts = new ArrayList<>(); - securityContexts.add( - SecurityContext.builder() - .securityReferences(defaultAuth()) - .operationSelector(o -> o.requestMappingPattern().matches("/.*")) - .build()); - return securityContexts; - } - - /** - * 默认的安全上引用 - */ - private List defaultAuth() - { - AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); - AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; - authorizationScopes[0] = authorizationScope; - List securityReferences = new ArrayList<>(); - securityReferences.add(new SecurityReference("Authorization", authorizationScopes)); - return securityReferences; - } - - /** - * 添加摘要信息 - */ - private ApiInfo apiInfo() - { - // 用ApiInfoBuilder进行定制 - return new ApiInfoBuilder() - // 设置标题 - .title("标题:wumei-smart接口文档") - // 描述 - .description("描述:开源生活物联网平台") - // 作者信息 - .contact(new Contact(ruoyiConfig.getName(), null, null)) - // 版本 - .version("版本号:" + ruoyiConfig.getVersion()) - .build(); - } -} diff --git a/springboot/wumei-admin/src/main/resources/META-INF/spring-devtools.properties b/springboot/wumei-admin/src/main/resources/META-INF/spring-devtools.properties deleted file mode 100644 index 2b23f85a..00000000 --- a/springboot/wumei-admin/src/main/resources/META-INF/spring-devtools.properties +++ /dev/null @@ -1 +0,0 @@ -restart.include.json=/com.alibaba.fastjson.*.jar \ No newline at end of file diff --git a/springboot/wumei-admin/src/main/resources/application-dev.yml b/springboot/wumei-admin/src/main/resources/application-dev.yml deleted file mode 100644 index f683d2a6..00000000 --- a/springboot/wumei-admin/src/main/resources/application-dev.yml +++ /dev/null @@ -1,113 +0,0 @@ - -# 日志配置 -logging: - level: - com.ruoyi: debug - org.springframework: warn - -# Spring配置 -spring: - datasource: - type: com.alibaba.druid.pool.DruidDataSource - driverClassName: com.mysql.cj.jdbc.Driver - druid: - # 主库数据源 - master: - url: jdbc:mysql://177.7.0.11/wumeismart?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 - username: root - password: wumei-smart - # 从库数据源 - slave: - # 从数据源开关/默认关闭 - enabled: false - url: - username: - password: - - # TDengine数据库 - tdengine-server: - # 默认不启用TDengine,true=启用,false=不启用 - enabled: false - driverClassName: com.taosdata.jdbc.TSDBDriver - url: jdbc:TAOS://localhost:6030/wumei_smart_log?timezone=Asia/Beijing&charset=utf-8 - username: root - password: taosdata - dbName: wumei_smart_log - - # 初始连接数 - initialSize: 5 - # 最小连接池数量 - minIdle: 10 - # 最大连接池数量 - maxActive: 20 - # 配置获取连接等待超时的时间 - maxWait: 60000 - # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 - timeBetweenEvictionRunsMillis: 60000 - # 配置一个连接在池中最小生存的时间,单位是毫秒 - minEvictableIdleTimeMillis: 300000 - # 配置一个连接在池中最大生存的时间,单位是毫秒 - maxEvictableIdleTimeMillis: 900000 - # 配置检测连接是否有效 - validationQuery: SELECT 1 FROM DUAL - testWhileIdle: true - testOnBorrow: false - testOnReturn: false - webStatFilter: - enabled: true - statViewServlet: - enabled: true - # 设置白名单,不填则允许所有访问 - allow: - url-pattern: /druid/* - # 控制台管理用户名和密码 - login-username: wumei-smart - login-password: wumei-smart - filter: - stat: - enabled: true - # 慢SQL记录 - log-slow-sql: true - slow-sql-millis: 1000 - merge-sql: true - wall: - config: - multi-statement-allow: true - # redis 配置 - redis: - # 地址 - host: 177.7.0.10 - # 端口,默认为6379 - port: 6379 - # 数据库索引 - database: 0 - # 密码 - password: wumei-smart - # 连接超时时间 - timeout: 10s - lettuce: - pool: - # 连接池中的最小空闲连接 - min-idle: 0 - # 连接池中的最大空闲连接 - max-idle: 8 - # 连接池的最大数据库连接数 - max-active: 8 - # #连接池最大阻塞等待时间(使用负值表示没有限制) - max-wait: -1ms - # mqtt 配置 - mqtt: - username: wumei-smart # 账号 - password: wumei-smart # 密码 - host-url: tcp://177.7.0.12:1883 # mqtt连接tcp地址 - client-id: ${random.int} # 客户端Id,不能相同,采用随机数 ${random.value} - default-topic: test # 默认主题 - timeout: 30 # 超时时间 - keepalive: 30 # 保持连接 - clearSession: true # 清除会话(设置为false,断开连接,重连后使用原来的会话 保留订阅的主题,能接收离线期间的消息) - task: - execution: - pool: - core-size: 10 # 最小连接数 - max-size: 30 # 最大连接数 - queue-capacity: 3000 # 最大容量 diff --git a/springboot/wumei-admin/src/main/resources/application-prod.yml b/springboot/wumei-admin/src/main/resources/application-prod.yml deleted file mode 100644 index 8bd60fc4..00000000 --- a/springboot/wumei-admin/src/main/resources/application-prod.yml +++ /dev/null @@ -1,112 +0,0 @@ -# 日志配置 -logging: - level: - com.ruoyi: debug - org.springframework: warn - -# Spring配置 -spring: - datasource: - type: com.alibaba.druid.pool.DruidDataSource - driverClassName: com.mysql.cj.jdbc.Driver - druid: - # 主库数据源 - master: - url: jdbc:mysql://mysql/wumeismart?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 - username: root - password: wumei-smart - # 从库数据源 - slave: - # 从数据源开关/默认关闭 - enabled: false - url: - username: - password: - - # TDengine数据库 - tdengine-server: - # 默认不启用TDengine,true=启用,false=不启用 - enabled: false - driverClassName: com.taosdata.jdbc.TSDBDriver - url: jdbc:TAOS://localhost:6030/wumei_smart_log?timezone=Asia/Beijing&charset=utf-8 - username: root - password: taosdata - dbName: wumei_smart_log - - # 初始连接数 - initialSize: 5 - # 最小连接池数量 - minIdle: 10 - # 最大连接池数量 - maxActive: 20 - # 配置获取连接等待超时的时间 - maxWait: 60000 - # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 - timeBetweenEvictionRunsMillis: 60000 - # 配置一个连接在池中最小生存的时间,单位是毫秒 - minEvictableIdleTimeMillis: 300000 - # 配置一个连接在池中最大生存的时间,单位是毫秒 - maxEvictableIdleTimeMillis: 900000 - # 配置检测连接是否有效 - validationQuery: SELECT 1 FROM DUAL - testWhileIdle: true - testOnBorrow: false - testOnReturn: false - webStatFilter: - enabled: true - statViewServlet: - enabled: true - # 设置白名单,不填则允许所有访问 - allow: - url-pattern: /druid/* - # 控制台管理用户名和密码 - login-username: wumei-smart - login-password: wumei-smart - filter: - stat: - enabled: true - # 慢SQL记录 - log-slow-sql: true - slow-sql-millis: 1000 - merge-sql: true - wall: - config: - multi-statement-allow: true - # redis 配置 - redis: - # 地址 - host: redis - # 端口,默认为6379 - port: 6379 - # 数据库索引 - database: 0 - # 密码 - password: wumei-smart - # 连接超时时间 - timeout: 10s - lettuce: - pool: - # 连接池中的最小空闲连接 - min-idle: 0 - # 连接池中的最大空闲连接 - max-idle: 8 - # 连接池的最大数据库连接数 - max-active: 8 - # #连接池最大阻塞等待时间(使用负值表示没有限制) - max-wait: -1ms - # mqtt 配置 - mqtt: - username: wumei-smart # 账号 - password: wumei-smart # 密码 - host-url: tcp://emqx:1883 # mqtt连接tcp地址 - client-id: ${random.int} # 客户端Id,不能相同,采用随机数 ${random.value} - default-topic: test # 默认主题 - timeout: 30 # 超时时间 - keepalive: 30 # 保持连接 - clearSession: true # 清除会话(设置为false,断开连接,重连后使用原来的会话 保留订阅的主题,能接收离线期间的消息) - task: - execution: - pool: - core-size: 10 # 最小连接数 - max-size: 30 # 最大连接数 - queue-capacity: 3000 # 最大容量 diff --git a/springboot/wumei-admin/src/main/resources/application.yml b/springboot/wumei-admin/src/main/resources/application.yml deleted file mode 100644 index ab25dbef..00000000 --- a/springboot/wumei-admin/src/main/resources/application.yml +++ /dev/null @@ -1,92 +0,0 @@ -# 项目相关配置 -ruoyi: - # 名称 - name: ruoyi - # 版本 - version: 3.8.0 - # 版权年份 - copyrightYear: 2021 - # 实例演示开关 - demoEnabled: true - # 文件路径,以uploadPath结尾 示例( Windows配置 D:/uploadPath,Linux配置 /uploadPath) - profile: /var/data/java/uploadPath - # 获取ip地址开关 - addressEnabled: true - # 验证码类型 math 数组计算 char 字符验证 - captchaType: math - -# 开发环境配置 -server: - # 服务器的HTTP端口,默认为8080 - port: 8080 - servlet: - # 应用的访问路径 - context-path: / - tomcat: - # tomcat的URI编码 - uri-encoding: UTF-8 - # tomcat最大线程数,默认为200 - max-threads: 800 - # Tomcat启动初始化的线程数,默认值25 - min-spare-threads: 30 - -# Spring配置 -spring: - # 资源信息 - messages: - # 国际化资源文件路径 - basename: i18n/messages - profiles: - active: prod - # 文件上传 - servlet: - multipart: - # 单个文件大小 - max-file-size: 10MB - # 设置总上传的文件大小 - max-request-size: 20MB - # 服务模块 - devtools: - restart: - # 热部署开关 - enabled: true - -# token配置 -token: - # 令牌自定义标识 - header: Authorization - # 令牌密钥 - secret: abcdefghijklwumeismartrstuvwxyz - # 令牌有效期(默认30分钟)1440为一天 - expireTime: 1440 - -# MyBatis配置 -mybatis: - # 搜索指定包别名 - typeAliasesPackage: com.ruoyi.**.domain - # 配置mapper的扫描,找到所有的mapper.xml映射文件 - mapperLocations: classpath*:mapper/**/*Mapper.xml - # 加载全局的配置文件 - configLocation: classpath:mybatis/mybatis-config.xml - -# PageHelper分页插件 -pagehelper: - helperDialect: mysql - supportMethodsArguments: true - params: count=countSql - -# Swagger配置 -swagger: - # 是否开启swagger - enabled: true - # 请求前缀 - pathMapping: /dev-api - -# 防止XSS攻击 -xss: - # 过滤开关 - enabled: true - # 排除链接(多个用逗号分隔) - excludes: /system/notice - # 匹配链接 - urlPatterns: /system/*,/monitor/*,/tool/* diff --git a/springboot/wumei-admin/src/main/resources/banner.txt b/springboot/wumei-admin/src/main/resources/banner.txt deleted file mode 100644 index fee1ce3b..00000000 --- a/springboot/wumei-admin/src/main/resources/banner.txt +++ /dev/null @@ -1,2 +0,0 @@ -Application Version: ${ruoyi.version} -Spring Boot Version: ${spring-boot.version} \ No newline at end of file diff --git a/springboot/wumei-admin/src/main/resources/i18n/messages.properties b/springboot/wumei-admin/src/main/resources/i18n/messages.properties deleted file mode 100644 index 71cf52d9..00000000 --- a/springboot/wumei-admin/src/main/resources/i18n/messages.properties +++ /dev/null @@ -1,37 +0,0 @@ -#错误消息 -not.null=* 必须填写 -user.jcaptcha.error=验证码错误 -user.jcaptcha.expire=验证码已失效 -user.not.exists=用户不存在/密码错误 -user.password.not.match=用户不存在/密码错误 -user.password.retry.limit.count=密码输入错误{0}次 -user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定10分钟 -user.password.delete=对不起,您的账号已被删除 -user.blocked=用户已封禁,请联系管理员 -role.blocked=角色已封禁,请联系管理员 -user.logout.success=退出成功 - -length.not.valid=长度必须在{min}到{max}个字符之间 - -user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成,且必须以非数字开头 -user.password.not.valid=* 5-50个字符 - -user.email.not.valid=邮箱格式错误 -user.mobile.phone.number.not.valid=手机号格式错误 -user.login.success=登录成功 -user.register.success=注册成功 -user.notfound=请重新登录 -user.forcelogout=管理员强制退出,请重新登录 -user.unknown.error=未知错误,请重新登录 - -##文件上传消息 -upload.exceed.maxSize=上传的文件大小超出限制的文件大小!
允许的文件最大大小是:{0}MB! -upload.filename.exceed.length=上传的文件名最长{0}个字符 - -##权限 -no.permission=您没有数据的权限,请联系管理员添加权限 [{0}] -no.create.permission=您没有创建数据的权限,请联系管理员添加权限 [{0}] -no.update.permission=您没有修改数据的权限,请联系管理员添加权限 [{0}] -no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}] -no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}] -no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}] diff --git a/springboot/wumei-admin/src/main/resources/logback.xml b/springboot/wumei-admin/src/main/resources/logback.xml deleted file mode 100644 index 6ac6cb31..00000000 --- a/springboot/wumei-admin/src/main/resources/logback.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - ${log.pattern} - - - - - - ${log.path}/sys-info.log - - - - ${log.path}/sys-info.%d{yyyy-MM-dd}.log - - 60 - - - ${log.pattern} - - - - INFO - - ACCEPT - - DENY - - - - - ${log.path}/sys-error.log - - - - ${log.path}/sys-error.%d{yyyy-MM-dd}.log - - 60 - - - ${log.pattern} - - - - ERROR - - ACCEPT - - DENY - - - - - - ${log.path}/sys-user.log - - - ${log.path}/sys-user.%d{yyyy-MM-dd}.log - - 60 - - - ${log.pattern} - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/springboot/wumei-admin/src/main/resources/mybatis/mybatis-config.xml b/springboot/wumei-admin/src/main/resources/mybatis/mybatis-config.xml deleted file mode 100644 index ac47c038..00000000 --- a/springboot/wumei-admin/src/main/resources/mybatis/mybatis-config.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/springboot/wumei-common/pom.xml b/springboot/wumei-common/pom.xml deleted file mode 100644 index f1dcae65..00000000 --- a/springboot/wumei-common/pom.xml +++ /dev/null @@ -1,130 +0,0 @@ - - - - wumei - com.wumei - 3.8.0 - - 4.0.0 - - wumei-common - - - common通用工具 - - - - - - - org.springframework - spring-context-support - - - - - org.springframework - spring-web - - - - - org.springframework.boot - spring-boot-starter-security - - - - - com.github.pagehelper - pagehelper-spring-boot-starter - - - - - org.springframework.boot - spring-boot-starter-validation - - - - - org.apache.commons - commons-lang3 - - - - - com.fasterxml.jackson.core - jackson-databind - - - - - com.alibaba - fastjson - - - - - commons-io - commons-io - - - - - commons-fileupload - commons-fileupload - - - - - org.apache.poi - poi-ooxml - - - - - org.yaml - snakeyaml - - - - - io.jsonwebtoken - jjwt - - - - - javax.xml.bind - jaxb-api - - - - - org.springframework.boot - spring-boot-starter-data-redis - - - - - org.apache.commons - commons-pool2 - - - - - eu.bitwalker - UserAgentUtils - - - - - javax.servlet - javax.servlet-api - - - - - \ No newline at end of file diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/annotation/DataScope.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/annotation/DataScope.java deleted file mode 100644 index 176878e9..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/annotation/DataScope.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.ruoyi.common.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * 数据权限过滤注解 - * - * @author ruoyi - */ -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface DataScope -{ - /** - * 部门表的别名 - */ - public String deptAlias() default ""; - - /** - * 用户表的别名 - */ - public String userAlias() default ""; -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/annotation/DataSource.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/annotation/DataSource.java deleted file mode 100644 index 79cd191f..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/annotation/DataSource.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.ruoyi.common.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import com.ruoyi.common.enums.DataSourceType; - -/** - * 自定义多数据源切换注解 - * - * 优先级:先方法,后类,如果方法覆盖了类上的数据源类型,以方法的为准,否则以类上的为准 - * - * @author ruoyi - */ -@Target({ ElementType.METHOD, ElementType.TYPE }) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@Inherited -public @interface DataSource -{ - /** - * 切换数据源名称 - */ - public DataSourceType value() default DataSourceType.MASTER; -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/annotation/Excel.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/annotation/Excel.java deleted file mode 100644 index 3754e0e0..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/annotation/Excel.java +++ /dev/null @@ -1,176 +0,0 @@ -package com.ruoyi.common.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.math.BigDecimal; -import com.ruoyi.common.utils.poi.ExcelHandlerAdapter; - -/** - * 自定义导出Excel数据注解 - * - * @author ruoyi - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -public @interface Excel -{ - /** - * 导出时在excel中排序 - */ - public int sort() default Integer.MAX_VALUE; - - /** - * 导出到Excel中的名字. - */ - public String name() default ""; - - /** - * 日期格式, 如: yyyy-MM-dd - */ - public String dateFormat() default ""; - - /** - * 如果是字典类型,请设置字典的type值 (如: sys_user_sex) - */ - public String dictType() default ""; - - /** - * 读取内容转表达式 (如: 0=男,1=女,2=未知) - */ - public String readConverterExp() default ""; - - /** - * 分隔符,读取字符串组内容 - */ - public String separator() default ","; - - /** - * BigDecimal 精度 默认:-1(默认不开启BigDecimal格式化) - */ - public int scale() default -1; - - /** - * BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN - */ - public int roundingMode() default BigDecimal.ROUND_HALF_EVEN; - - /** - * 导出类型(0数字 1字符串) - */ - public ColumnType cellType() default ColumnType.STRING; - - /** - * 导出时在excel中每个列的高度 单位为字符 - */ - public double height() default 14; - - /** - * 导出时在excel中每个列的宽 单位为字符 - */ - public double width() default 16; - - /** - * 文字后缀,如% 90 变成90% - */ - public String suffix() default ""; - - /** - * 当值为空时,字段的默认值 - */ - public String defaultValue() default ""; - - /** - * 提示信息 - */ - public String prompt() default ""; - - /** - * 设置只能选择不能输入的列内容. - */ - public String[] combo() default {}; - - /** - * 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写. - */ - public boolean isExport() default true; - - /** - * 另一个类中的属性名称,支持多级获取,以小数点隔开 - */ - public String targetAttr() default ""; - - /** - * 是否自动统计数据,在最后追加一行统计数据总和 - */ - public boolean isStatistics() default false; - - /** - * 导出字段对齐方式(0:默认;1:靠左;2:居中;3:靠右) - */ - public Align align() default Align.AUTO; - - /** - * 自定义数据处理器 - */ - public Class handler() default ExcelHandlerAdapter.class; - - /** - * 自定义数据处理器参数 - */ - public String[] args() default {}; - - public enum Align - { - AUTO(0), LEFT(1), CENTER(2), RIGHT(3); - private final int value; - - Align(int value) - { - this.value = value; - } - - public int value() - { - return this.value; - } - } - - /** - * 字段类型(0:导出导入;1:仅导出;2:仅导入) - */ - Type type() default Type.ALL; - - public enum Type - { - ALL(0), EXPORT(1), IMPORT(2); - private final int value; - - Type(int value) - { - this.value = value; - } - - public int value() - { - return this.value; - } - } - - public enum ColumnType - { - NUMERIC(0), STRING(1), IMAGE(2); - private final int value; - - ColumnType(int value) - { - this.value = value; - } - - public int value() - { - return this.value; - } - } -} \ No newline at end of file diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/annotation/Excels.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/annotation/Excels.java deleted file mode 100644 index 1f1cc81b..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/annotation/Excels.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.ruoyi.common.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Excel注解集 - * - * @author ruoyi - */ -@Target(ElementType.FIELD) -@Retention(RetentionPolicy.RUNTIME) -public @interface Excels -{ - public Excel[] value(); -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/annotation/Log.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/annotation/Log.java deleted file mode 100644 index ca02c6c4..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/annotation/Log.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.ruoyi.common.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.common.enums.OperatorType; - -/** - * 自定义操作日志记录注解 - * - * @author ruoyi - * - */ -@Target({ ElementType.PARAMETER, ElementType.METHOD }) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface Log -{ - /** - * 模块 - */ - public String title() default ""; - - /** - * 功能 - */ - public BusinessType businessType() default BusinessType.OTHER; - - /** - * 操作人类别 - */ - public OperatorType operatorType() default OperatorType.MANAGE; - - /** - * 是否保存请求的参数 - */ - public boolean isSaveRequestData() default true; - - /** - * 是否保存响应的参数 - */ - public boolean isSaveResponseData() default true; -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java deleted file mode 100644 index 69461ead..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.ruoyi.common.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.enums.LimitType; - -/** - * 限流注解 - * - * @author ruoyi - */ -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface RateLimiter -{ - /** - * 限流key - */ - public String key() default Constants.RATE_LIMIT_KEY; - - /** - * 限流时间,单位秒 - */ - public int time() default 60; - - /** - * 限流次数 - */ - public int count() default 100; - - /** - * 限流类型 - */ - public LimitType limitType() default LimitType.DEFAULT; -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java deleted file mode 100644 index b7697481..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.ruoyi.common.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * 自定义注解防止表单重复提交 - * - * @author ruoyi - * - */ -@Inherited -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface RepeatSubmit -{ - /** - * 间隔时间(ms),小于此时间视为重复提交 - */ - public int interval() default 5000; - - /** - * 提示消息 - */ - public String message() default "不允许重复提交,请稍候再试"; -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java deleted file mode 100644 index 00f70f64..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java +++ /dev/null @@ -1,135 +0,0 @@ -package com.ruoyi.common.config; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; - -/** - * 读取项目相关配置 - * - * @author ruoyi - */ -@Component -@ConfigurationProperties(prefix = "ruoyi") -public class RuoYiConfig -{ - /** 项目名称 */ - private String name; - - /** 版本 */ - private String version; - - /** 版权年份 */ - private String copyrightYear; - - /** 实例演示开关 */ - private boolean demoEnabled; - - /** 上传路径 */ - private static String profile; - - /** 获取地址开关 */ - private static boolean addressEnabled; - - /** 验证码类型 */ - private static String captchaType; - - public String getName() - { - return name; - } - - public void setName(String name) - { - this.name = name; - } - - public String getVersion() - { - return version; - } - - public void setVersion(String version) - { - this.version = version; - } - - public String getCopyrightYear() - { - return copyrightYear; - } - - public void setCopyrightYear(String copyrightYear) - { - this.copyrightYear = copyrightYear; - } - - public boolean isDemoEnabled() - { - return demoEnabled; - } - - public void setDemoEnabled(boolean demoEnabled) - { - this.demoEnabled = demoEnabled; - } - - public static String getProfile() - { - return profile; - } - - public void setProfile(String profile) - { - RuoYiConfig.profile = profile; - } - - public static boolean isAddressEnabled() - { - return addressEnabled; - } - - public void setAddressEnabled(boolean addressEnabled) - { - RuoYiConfig.addressEnabled = addressEnabled; - } - - public static String getCaptchaType() { - return captchaType; - } - - public void setCaptchaType(String captchaType) { - RuoYiConfig.captchaType = captchaType; - } - - /** - * 获取导入上传路径 - */ - public static String getImportPath() - { - return getProfile() + "/import"; - } - - /** - * 获取头像上传路径 - */ - public static String getAvatarPath() - { - return getProfile() + "/avatar"; - } - - /** - * 获取下载路径 - */ - public static String getDownloadPath() - { - return getProfile() + "/download/"; - } - - /** - * 获取上传路径 - */ - public static String getUploadPath() - { - return getProfile() + "/upload"; - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/constant/Constants.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/constant/Constants.java deleted file mode 100644 index 33b745b0..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/constant/Constants.java +++ /dev/null @@ -1,157 +0,0 @@ -package com.ruoyi.common.constant; - -import io.jsonwebtoken.Claims; - -/** - * 通用常量信息 - * - * @author ruoyi - */ -public class Constants -{ - /** - * UTF-8 字符集 - */ - public static final String UTF8 = "UTF-8"; - - /** - * GBK 字符集 - */ - public static final String GBK = "GBK"; - - /** - * http请求 - */ - public static final String HTTP = "http://"; - - /** - * https请求 - */ - public static final String HTTPS = "https://"; - - /** - * 通用成功标识 - */ - public static final String SUCCESS = "0"; - - /** - * 通用失败标识 - */ - public static final String FAIL = "1"; - - /** - * 登录成功 - */ - public static final String LOGIN_SUCCESS = "Success"; - - /** - * 注销 - */ - public static final String LOGOUT = "Logout"; - - /** - * 注册 - */ - public static final String REGISTER = "Register"; - - /** - * 登录失败 - */ - public static final String LOGIN_FAIL = "Error"; - - /** - * 验证码 redis key - */ - public static final String CAPTCHA_CODE_KEY = "captcha_codes:"; - - /** - * 登录用户 redis key - */ - public static final String LOGIN_TOKEN_KEY = "login_tokens:"; - - /** - * 防重提交 redis key - */ - public static final String REPEAT_SUBMIT_KEY = "repeat_submit:"; - - /** - * 限流 redis key - */ - public static final String RATE_LIMIT_KEY = "rate_limit:"; - - /** - * 验证码有效期(分钟) - */ - public static final Integer CAPTCHA_EXPIRATION = 2; - - /** - * 令牌 - */ - public static final String TOKEN = "token"; - - /** - * 令牌前缀 - */ - public static final String TOKEN_PREFIX = "Bearer "; - - /** - * 令牌前缀 - */ - public static final String LOGIN_USER_KEY = "login_user_key"; - - /** - * 用户ID - */ - public static final String JWT_USERID = "userid"; - - /** - * 用户名称 - */ - public static final String JWT_USERNAME = Claims.SUBJECT; - - /** - * 用户头像 - */ - public static final String JWT_AVATAR = "avatar"; - - /** - * 创建时间 - */ - public static final String JWT_CREATED = "created"; - - /** - * 用户权限 - */ - public static final String JWT_AUTHORITIES = "authorities"; - - /** - * 参数管理 cache key - */ - public static final String SYS_CONFIG_KEY = "sys_config:"; - - /** - * 字典管理 cache key - */ - public static final String SYS_DICT_KEY = "sys_dict:"; - - /** - * 资源映射路径 前缀 - */ - public static final String RESOURCE_PREFIX = "/profile"; - - /** - * RMI 远程方法调用 - */ - public static final String LOOKUP_RMI = "rmi://"; - - /** - * LDAP 远程方法调用 - */ - public static final String LOOKUP_LDAP = "ldap://"; - - /** - * 定时任务违规的字符 - */ - public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml", - "org.springframework.jndi" }; -} \ No newline at end of file diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/constant/GenConstants.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/constant/GenConstants.java deleted file mode 100644 index 1fa328e4..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/constant/GenConstants.java +++ /dev/null @@ -1,114 +0,0 @@ -package com.ruoyi.common.constant; - -/** - * 代码生成通用常量 - * - * @author ruoyi - */ -public class GenConstants -{ - /** 单表(增删改查) */ - public static final String TPL_CRUD = "crud"; - - /** 树表(增删改查) */ - public static final String TPL_TREE = "tree"; - - /** 主子表(增删改查) */ - public static final String TPL_SUB = "sub"; - - /** 树编码字段 */ - public static final String TREE_CODE = "treeCode"; - - /** 树父编码字段 */ - public static final String TREE_PARENT_CODE = "treeParentCode"; - - /** 树名称字段 */ - public static final String TREE_NAME = "treeName"; - - /** 上级菜单ID字段 */ - public static final String PARENT_MENU_ID = "parentMenuId"; - - /** 上级菜单名称字段 */ - public static final String PARENT_MENU_NAME = "parentMenuName"; - - /** 数据库字符串类型 */ - public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" }; - - /** 数据库文本类型 */ - public static final String[] COLUMNTYPE_TEXT = { "tinytext", "text", "mediumtext", "longtext" }; - - /** 数据库时间类型 */ - public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" }; - - /** 数据库数字类型 */ - public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer", - "bit", "bigint", "float", "double", "decimal" }; - - /** 页面不需要编辑字段 */ - public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" }; - - /** 页面不需要显示的列表字段 */ - public static final String[] COLUMNNAME_NOT_LIST = { "id", "create_by", "create_time", "del_flag", "update_by", - "update_time" }; - - /** 页面不需要查询字段 */ - public static final String[] COLUMNNAME_NOT_QUERY = { "id", "create_by", "create_time", "del_flag", "update_by", - "update_time", "remark" }; - - /** Entity基类字段 */ - public static final String[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime", "remark" }; - - /** Tree基类字段 */ - public static final String[] TREE_ENTITY = { "parentName", "parentId", "orderNum", "ancestors", "children" }; - - /** 文本框 */ - public static final String HTML_INPUT = "input"; - - /** 文本域 */ - public static final String HTML_TEXTAREA = "textarea"; - - /** 下拉框 */ - public static final String HTML_SELECT = "select"; - - /** 单选框 */ - public static final String HTML_RADIO = "radio"; - - /** 复选框 */ - public static final String HTML_CHECKBOX = "checkbox"; - - /** 日期控件 */ - public static final String HTML_DATETIME = "datetime"; - - /** 图片上传控件 */ - public static final String HTML_IMAGE_UPLOAD = "imageUpload"; - - /** 文件上传控件 */ - public static final String HTML_FILE_UPLOAD = "fileUpload"; - - /** 富文本控件 */ - public static final String HTML_EDITOR = "editor"; - - /** 字符串类型 */ - public static final String TYPE_STRING = "String"; - - /** 整型 */ - public static final String TYPE_INTEGER = "Integer"; - - /** 长整型 */ - public static final String TYPE_LONG = "Long"; - - /** 浮点型 */ - public static final String TYPE_DOUBLE = "Double"; - - /** 高精度计算类型 */ - public static final String TYPE_BIGDECIMAL = "BigDecimal"; - - /** 时间类型 */ - public static final String TYPE_DATE = "Date"; - - /** 模糊查询 */ - public static final String QUERY_LIKE = "LIKE"; - - /** 需要 */ - public static final String REQUIRE = "1"; -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java deleted file mode 100644 index cec2f9cf..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.ruoyi.common.constant; - -/** - * 返回状态码 - * - * @author ruoyi - */ -public class HttpStatus -{ - /** - * 操作成功 - */ - public static final int SUCCESS = 200; - - /** - * 对象创建成功 - */ - public static final int CREATED = 201; - - /** - * 请求已经被接受 - */ - public static final int ACCEPTED = 202; - - /** - * 操作已经执行成功,但是没有返回数据 - */ - public static final int NO_CONTENT = 204; - - /** - * 资源已被移除 - */ - public static final int MOVED_PERM = 301; - - /** - * 重定向 - */ - public static final int SEE_OTHER = 303; - - /** - * 资源没有被修改 - */ - public static final int NOT_MODIFIED = 304; - - /** - * 参数列表错误(缺少,格式不匹配) - */ - public static final int BAD_REQUEST = 400; - - /** - * 未授权 - */ - public static final int UNAUTHORIZED = 401; - - /** - * 访问受限,授权过期 - */ - public static final int FORBIDDEN = 403; - - /** - * 资源,服务未找到 - */ - public static final int NOT_FOUND = 404; - - /** - * 不允许的http方法 - */ - public static final int BAD_METHOD = 405; - - /** - * 资源冲突,或者资源被锁 - */ - public static final int CONFLICT = 409; - - /** - * 不支持的数据,媒体类型 - */ - public static final int UNSUPPORTED_TYPE = 415; - - /** - * 系统内部错误 - */ - public static final int ERROR = 500; - - /** - * 接口未实现 - */ - public static final int NOT_IMPLEMENTED = 501; - - /** - * 不弹窗显示 - */ - public static final int NO_MESSAGE_ALERT = 502; -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java deleted file mode 100644 index 62ad8154..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.ruoyi.common.constant; - -/** - * 任务调度通用常量 - * - * @author ruoyi - */ -public class ScheduleConstants -{ - public static final String TASK_CLASS_NAME = "TASK_CLASS_NAME"; - - /** 执行目标key */ - public static final String TASK_PROPERTIES = "TASK_PROPERTIES"; - - /** 默认 */ - public static final String MISFIRE_DEFAULT = "0"; - - /** 立即触发执行 */ - public static final String MISFIRE_IGNORE_MISFIRES = "1"; - - /** 触发一次执行 */ - public static final String MISFIRE_FIRE_AND_PROCEED = "2"; - - /** 不触发立即执行 */ - public static final String MISFIRE_DO_NOTHING = "3"; - - public enum Status - { - /** - * 正常 - */ - NORMAL("0"), - /** - * 暂停 - */ - PAUSE("1"); - - private String value; - - private Status(String value) - { - this.value = value; - } - - public String getValue() - { - return value; - } - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/constant/UserConstants.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/constant/UserConstants.java deleted file mode 100644 index 4ed60095..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/constant/UserConstants.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.ruoyi.common.constant; - -/** - * 用户常量信息 - * - * @author ruoyi - */ -public class UserConstants -{ - /** - * 平台内系统用户的唯一标志 - */ - public static final String SYS_USER = "SYS_USER"; - - /** 正常状态 */ - public static final String NORMAL = "0"; - - /** 异常状态 */ - public static final String EXCEPTION = "1"; - - /** 用户封禁状态 */ - public static final String USER_DISABLE = "1"; - - /** 角色封禁状态 */ - public static final String ROLE_DISABLE = "1"; - - /** 部门正常状态 */ - public static final String DEPT_NORMAL = "0"; - - /** 部门停用状态 */ - public static final String DEPT_DISABLE = "1"; - - /** 字典正常状态 */ - public static final String DICT_NORMAL = "0"; - - /** 是否为系统默认(是) */ - public static final String YES = "Y"; - - /** 是否菜单外链(是) */ - public static final String YES_FRAME = "0"; - - /** 是否菜单外链(否) */ - public static final String NO_FRAME = "1"; - - /** 菜单类型(目录) */ - public static final String TYPE_DIR = "M"; - - /** 菜单类型(菜单) */ - public static final String TYPE_MENU = "C"; - - /** 菜单类型(按钮) */ - public static final String TYPE_BUTTON = "F"; - - /** Layout组件标识 */ - public final static String LAYOUT = "Layout"; - - /** ParentView组件标识 */ - public final static String PARENT_VIEW = "ParentView"; - - /** InnerLink组件标识 */ - public final static String INNER_LINK = "InnerLink"; - - /** 校验返回结果码 */ - public final static String UNIQUE = "0"; - public final static String NOT_UNIQUE = "1"; - - /** - * 用户名长度限制 - */ - public static final int USERNAME_MIN_LENGTH = 2; - public static final int USERNAME_MAX_LENGTH = 20; - - /** - * 密码长度限制 - */ - public static final int PASSWORD_MIN_LENGTH = 5; - public static final int PASSWORD_MAX_LENGTH = 20; -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java deleted file mode 100644 index 9b3d9c71..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java +++ /dev/null @@ -1,185 +0,0 @@ -package com.ruoyi.common.core.controller; - -import java.beans.PropertyEditorSupport; -import java.util.Date; -import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.web.bind.WebDataBinder; -import org.springframework.web.bind.annotation.InitBinder; -import com.github.pagehelper.PageHelper; -import com.github.pagehelper.PageInfo; -import com.ruoyi.common.constant.HttpStatus; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.domain.model.LoginUser; -import com.ruoyi.common.core.page.PageDomain; -import com.ruoyi.common.core.page.TableDataInfo; -import com.ruoyi.common.core.page.TableSupport; -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.common.utils.SecurityUtils; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.sql.SqlUtil; - -/** - * web层通用数据处理 - * - * @author ruoyi - */ -public class BaseController -{ - protected final Logger logger = LoggerFactory.getLogger(this.getClass()); - - /** - * 将前台传递过来的日期格式的字符串,自动转化为Date类型 - */ - @InitBinder - public void initBinder(WebDataBinder binder) - { - // Date 类型转换 - binder.registerCustomEditor(Date.class, new PropertyEditorSupport() - { - @Override - public void setAsText(String text) - { - setValue(DateUtils.parseDate(text)); - } - }); - } - - /** - * 设置请求分页数据 - */ - protected void startPage() - { - PageDomain pageDomain = TableSupport.buildPageRequest(); - Integer pageNum = pageDomain.getPageNum(); - Integer pageSize = pageDomain.getPageSize(); - if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize)) - { - String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy()); - Boolean reasonable = pageDomain.getReasonable(); - PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable); - } - } - - /** - * 设置请求排序数据 - */ - protected void startOrderBy() - { - PageDomain pageDomain = TableSupport.buildPageRequest(); - if (StringUtils.isNotEmpty(pageDomain.getOrderBy())) - { - String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy()); - PageHelper.orderBy(orderBy); - } - } - - /** - * 响应请求分页数据 - */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - protected TableDataInfo getDataTable(List list) - { - TableDataInfo rspData = new TableDataInfo(); - rspData.setCode(HttpStatus.SUCCESS); - rspData.setMsg("查询成功"); - rspData.setRows(list); - rspData.setTotal(new PageInfo(list).getTotal()); - return rspData; - } - - /** - * 返回成功 - */ - public AjaxResult success() - { - return AjaxResult.success(); - } - - /** - * 返回失败消息 - */ - public AjaxResult error() - { - return AjaxResult.error(); - } - - /** - * 返回成功消息 - */ - public AjaxResult success(String message) - { - return AjaxResult.success(message); - } - - /** - * 返回失败消息 - */ - public AjaxResult error(String message) - { - return AjaxResult.error(message); - } - - /** - * 响应返回结果 - * - * @param rows 影响行数 - * @return 操作结果 - */ - protected AjaxResult toAjax(int rows) - { - return rows > 0 ? AjaxResult.success() : AjaxResult.error(); - } - - /** - * 响应返回结果 - * - * @param result 结果 - * @return 操作结果 - */ - protected AjaxResult toAjax(boolean result) - { - return result ? success() : error(); - } - - /** - * 页面跳转 - */ - public String redirect(String url) - { - return StringUtils.format("redirect:{}", url); - } - - /** - * 获取用户缓存信息 - */ - public LoginUser getLoginUser() - { - return SecurityUtils.getLoginUser(); - } - - /** - * 获取登录用户id - */ - public Long getUserId() - { - return getLoginUser().getUserId(); - } - - /** - * 获取登录部门id - */ - public Long getDeptId() - { - return getLoginUser().getDeptId(); - } - - /** - * 获取登录用户名 - */ - public String getUsername() - { - return getLoginUser().getUsername(); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java deleted file mode 100644 index 4950bd00..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java +++ /dev/null @@ -1,162 +0,0 @@ -package com.ruoyi.common.core.domain; - -import java.util.HashMap; -import com.ruoyi.common.constant.HttpStatus; -import com.ruoyi.common.utils.StringUtils; - -/** - * 操作消息提醒 - * - * @author ruoyi - */ -public class AjaxResult extends HashMap -{ - private static final long serialVersionUID = 1L; - - /** 状态码 */ - public static final String CODE_TAG = "code"; - - /** 返回内容 */ - public static final String MSG_TAG = "msg"; - - /** 数据对象 */ - public static final String DATA_TAG = "data"; - - /** - * 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。 - */ - public AjaxResult() - { - } - - /** - * 初始化一个新创建的 AjaxResult 对象 - * - * @param code 状态码 - * @param msg 返回内容 - */ - public AjaxResult(int code, String msg) - { - super.put(CODE_TAG, code); - super.put(MSG_TAG, msg); - } - - /** - * 初始化一个新创建的 AjaxResult 对象 - * - * @param code 状态码 - * @param msg 返回内容 - * @param data 数据对象 - */ - public AjaxResult(int code, String msg, Object data) - { - super.put(CODE_TAG, code); - super.put(MSG_TAG, msg); - if (StringUtils.isNotNull(data)) - { - super.put(DATA_TAG, data); - } - } - - /** - * 返回成功消息 - * - * @return 成功消息 - */ - public static AjaxResult success() - { - return AjaxResult.success("操作成功"); - } - - /** - * 返回成功数据 - * - * @return 成功消息 - */ - public static AjaxResult success(Object data) - { - return AjaxResult.success("操作成功", data); - } - - /** - * 返回成功消息 - * - * @param msg 返回内容 - * @return 成功消息 - */ - public static AjaxResult success(String msg) - { - return AjaxResult.success(msg, null); - } - - /** - * 返回成功消息 - * - * @param msg 返回内容 - * @param data 数据对象 - * @return 成功消息 - */ - public static AjaxResult success(String msg, Object data) - { - return new AjaxResult(HttpStatus.SUCCESS, msg, data); - } - - /** - * 返回错误消息 - * - * @return - */ - public static AjaxResult error() - { - return AjaxResult.error("操作失败"); - } - - /** - * 返回错误消息 - * - * @param msg 返回内容 - * @return 警告消息 - */ - public static AjaxResult error(String msg) - { - return AjaxResult.error(msg, null); - } - - /** - * 返回错误消息 - * - * @param msg 返回内容 - * @param data 数据对象 - * @return 警告消息 - */ - public static AjaxResult error(String msg, Object data) - { - return new AjaxResult(HttpStatus.ERROR, msg, data); - } - - /** - * 返回错误消息 - * - * @param code 状态码 - * @param msg 返回内容 - * @return 警告消息 - */ - public static AjaxResult error(int code, String msg) - { - return new AjaxResult(code, msg, null); - } - - /** - * 方便链式调用 - * - * @param key 键 - * @param value 值 - * @return 数据对象 - */ - @Override - public AjaxResult put(String key, Object value) - { - super.put(key, value); - return this; - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java deleted file mode 100644 index f7d5bf46..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java +++ /dev/null @@ -1,114 +0,0 @@ -package com.ruoyi.common.core.domain; - -import java.io.Serializable; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import com.fasterxml.jackson.annotation.JsonFormat; - -/** - * Entity基类 - * - * @author ruoyi - */ -public class BaseEntity implements Serializable -{ - private static final long serialVersionUID = 1L; - - /** 搜索值 */ - private String searchValue; - - /** 创建者 */ - private String createBy; - - /** 创建时间 */ - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private Date createTime; - - /** 更新者 */ - private String updateBy; - - /** 更新时间 */ - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private Date updateTime; - - /** 备注 */ - private String remark; - - /** 请求参数 */ - private Map params; - - public String getSearchValue() - { - return searchValue; - } - - public void setSearchValue(String searchValue) - { - this.searchValue = searchValue; - } - - public String getCreateBy() - { - return createBy; - } - - public void setCreateBy(String createBy) - { - this.createBy = createBy; - } - - public Date getCreateTime() - { - return createTime; - } - - public void setCreateTime(Date createTime) - { - this.createTime = createTime; - } - - public String getUpdateBy() - { - return updateBy; - } - - public void setUpdateBy(String updateBy) - { - this.updateBy = updateBy; - } - - public Date getUpdateTime() - { - return updateTime; - } - - public void setUpdateTime(Date updateTime) - { - this.updateTime = updateTime; - } - - public String getRemark() - { - return remark; - } - - public void setRemark(String remark) - { - this.remark = remark; - } - - public Map getParams() - { - if (params == null) - { - params = new HashMap<>(); - } - return params; - } - - public void setParams(Map params) - { - this.params = params; - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java deleted file mode 100644 index a180a18c..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.ruoyi.common.core.domain; - -import java.util.ArrayList; -import java.util.List; - -/** - * Tree基类 - * - * @author ruoyi - */ -public class TreeEntity extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 父菜单名称 */ - private String parentName; - - /** 父菜单ID */ - private Long parentId; - - /** 显示顺序 */ - private Integer orderNum; - - /** 祖级列表 */ - private String ancestors; - - /** 子部门 */ - private List children = new ArrayList<>(); - - public String getParentName() - { - return parentName; - } - - public void setParentName(String parentName) - { - this.parentName = parentName; - } - - public Long getParentId() - { - return parentId; - } - - public void setParentId(Long parentId) - { - this.parentId = parentId; - } - - public Integer getOrderNum() - { - return orderNum; - } - - public void setOrderNum(Integer orderNum) - { - this.orderNum = orderNum; - } - - public String getAncestors() - { - return ancestors; - } - - public void setAncestors(String ancestors) - { - this.ancestors = ancestors; - } - - public List getChildren() - { - return children; - } - - public void setChildren(List children) - { - this.children = children; - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java deleted file mode 100644 index bd835db9..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.ruoyi.common.core.domain; - -import java.io.Serializable; -import java.util.List; -import java.util.stream.Collectors; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.ruoyi.common.core.domain.entity.SysDept; -import com.ruoyi.common.core.domain.entity.SysMenu; - -/** - * Treeselect树结构实体类 - * - * @author ruoyi - */ -public class TreeSelect implements Serializable -{ - private static final long serialVersionUID = 1L; - - /** 节点ID */ - private Long id; - - /** 节点名称 */ - private String label; - - /** 子节点 */ - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private List children; - - public TreeSelect() - { - - } - - public TreeSelect(SysDept dept) - { - this.id = dept.getDeptId(); - this.label = dept.getDeptName(); - this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList()); - } - - public TreeSelect(SysMenu menu) - { - this.id = menu.getMenuId(); - this.label = menu.getMenuName(); - this.children = menu.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList()); - } - - public Long getId() - { - return id; - } - - public void setId(Long id) - { - this.id = id; - } - - public String getLabel() - { - return label; - } - - public void setLabel(String label) - { - this.label = label; - } - - public List getChildren() - { - return children; - } - - public void setChildren(List children) - { - this.children = children; - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java deleted file mode 100644 index c9238e23..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java +++ /dev/null @@ -1,202 +0,0 @@ -package com.ruoyi.common.core.domain.entity; - -import java.util.ArrayList; -import java.util.List; -import javax.validation.constraints.Email; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Size; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.common.core.domain.BaseEntity; - -/** - * 部门表 sys_dept - * - * @author ruoyi - */ -public class SysDept extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 部门ID */ - private Long deptId; - - /** 父部门ID */ - private Long parentId; - - /** 祖级列表 */ - private String ancestors; - - /** 部门名称 */ - private String deptName; - - /** 显示顺序 */ - private String orderNum; - - /** 负责人 */ - private String leader; - - /** 联系电话 */ - private String phone; - - /** 邮箱 */ - private String email; - - /** 部门状态:0正常,1停用 */ - private String status; - - /** 删除标志(0代表存在 2代表删除) */ - private String delFlag; - - /** 父部门名称 */ - private String parentName; - - /** 子部门 */ - private List children = new ArrayList(); - - public Long getDeptId() - { - return deptId; - } - - public void setDeptId(Long deptId) - { - this.deptId = deptId; - } - - public Long getParentId() - { - return parentId; - } - - public void setParentId(Long parentId) - { - this.parentId = parentId; - } - - public String getAncestors() - { - return ancestors; - } - - public void setAncestors(String ancestors) - { - this.ancestors = ancestors; - } - - @NotBlank(message = "部门名称不能为空") - @Size(min = 0, max = 30, message = "部门名称长度不能超过30个字符") - public String getDeptName() - { - return deptName; - } - - public void setDeptName(String deptName) - { - this.deptName = deptName; - } - - @NotBlank(message = "显示顺序不能为空") - public String getOrderNum() - { - return orderNum; - } - - public void setOrderNum(String orderNum) - { - this.orderNum = orderNum; - } - - public String getLeader() - { - return leader; - } - - public void setLeader(String leader) - { - this.leader = leader; - } - - @Size(min = 0, max = 11, message = "联系电话长度不能超过11个字符") - public String getPhone() - { - return phone; - } - - public void setPhone(String phone) - { - this.phone = phone; - } - - @Email(message = "邮箱格式不正确") - @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符") - public String getEmail() - { - return email; - } - - public void setEmail(String email) - { - this.email = email; - } - - public String getStatus() - { - return status; - } - - public void setStatus(String status) - { - this.status = status; - } - - public String getDelFlag() - { - return delFlag; - } - - public void setDelFlag(String delFlag) - { - this.delFlag = delFlag; - } - - public String getParentName() - { - return parentName; - } - - public void setParentName(String parentName) - { - this.parentName = parentName; - } - - public List getChildren() - { - return children; - } - - public void setChildren(List children) - { - this.children = children; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("deptId", getDeptId()) - .append("parentId", getParentId()) - .append("ancestors", getAncestors()) - .append("deptName", getDeptName()) - .append("orderNum", getOrderNum()) - .append("leader", getLeader()) - .append("phone", getPhone()) - .append("email", getEmail()) - .append("status", getStatus()) - .append("delFlag", getDelFlag()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .toString(); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java deleted file mode 100644 index 3f152b34..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java +++ /dev/null @@ -1,176 +0,0 @@ -package com.ruoyi.common.core.domain.entity; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Size; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.common.annotation.Excel; -import com.ruoyi.common.annotation.Excel.ColumnType; -import com.ruoyi.common.constant.UserConstants; -import com.ruoyi.common.core.domain.BaseEntity; - -/** - * 字典数据表 sys_dict_data - * - * @author ruoyi - */ -public class SysDictData extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 字典编码 */ - @Excel(name = "字典编码", cellType = ColumnType.NUMERIC) - private Long dictCode; - - /** 字典排序 */ - @Excel(name = "字典排序", cellType = ColumnType.NUMERIC) - private Long dictSort; - - /** 字典标签 */ - @Excel(name = "字典标签") - private String dictLabel; - - /** 字典键值 */ - @Excel(name = "字典键值") - private String dictValue; - - /** 字典类型 */ - @Excel(name = "字典类型") - private String dictType; - - /** 样式属性(其他样式扩展) */ - private String cssClass; - - /** 表格字典样式 */ - private String listClass; - - /** 是否默认(Y是 N否) */ - @Excel(name = "是否默认", readConverterExp = "Y=是,N=否") - private String isDefault; - - /** 状态(0正常 1停用) */ - @Excel(name = "状态", readConverterExp = "0=正常,1=停用") - private String status; - - public Long getDictCode() - { - return dictCode; - } - - public void setDictCode(Long dictCode) - { - this.dictCode = dictCode; - } - - public Long getDictSort() - { - return dictSort; - } - - public void setDictSort(Long dictSort) - { - this.dictSort = dictSort; - } - - @NotBlank(message = "字典标签不能为空") - @Size(min = 0, max = 100, message = "字典标签长度不能超过100个字符") - public String getDictLabel() - { - return dictLabel; - } - - public void setDictLabel(String dictLabel) - { - this.dictLabel = dictLabel; - } - - @NotBlank(message = "字典键值不能为空") - @Size(min = 0, max = 100, message = "字典键值长度不能超过100个字符") - public String getDictValue() - { - return dictValue; - } - - public void setDictValue(String dictValue) - { - this.dictValue = dictValue; - } - - @NotBlank(message = "字典类型不能为空") - @Size(min = 0, max = 100, message = "字典类型长度不能超过100个字符") - public String getDictType() - { - return dictType; - } - - public void setDictType(String dictType) - { - this.dictType = dictType; - } - - @Size(min = 0, max = 100, message = "样式属性长度不能超过100个字符") - public String getCssClass() - { - return cssClass; - } - - public void setCssClass(String cssClass) - { - this.cssClass = cssClass; - } - - public String getListClass() - { - return listClass; - } - - public void setListClass(String listClass) - { - this.listClass = listClass; - } - - public boolean getDefault() - { - return UserConstants.YES.equals(this.isDefault) ? true : false; - } - - public String getIsDefault() - { - return isDefault; - } - - public void setIsDefault(String isDefault) - { - this.isDefault = isDefault; - } - - public String getStatus() - { - return status; - } - - public void setStatus(String status) - { - this.status = status; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("dictCode", getDictCode()) - .append("dictSort", getDictSort()) - .append("dictLabel", getDictLabel()) - .append("dictValue", getDictValue()) - .append("dictType", getDictType()) - .append("cssClass", getCssClass()) - .append("listClass", getListClass()) - .append("isDefault", getIsDefault()) - .append("status", getStatus()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("remark", getRemark()) - .toString(); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java deleted file mode 100644 index d2c42498..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.ruoyi.common.core.domain.entity; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Size; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.common.annotation.Excel; -import com.ruoyi.common.annotation.Excel.ColumnType; -import com.ruoyi.common.core.domain.BaseEntity; - -/** - * 字典类型表 sys_dict_type - * - * @author ruoyi - */ -public class SysDictType extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 字典主键 */ - @Excel(name = "字典主键", cellType = ColumnType.NUMERIC) - private Long dictId; - - /** 字典名称 */ - @Excel(name = "字典名称") - private String dictName; - - /** 字典类型 */ - @Excel(name = "字典类型") - private String dictType; - - /** 状态(0正常 1停用) */ - @Excel(name = "状态", readConverterExp = "0=正常,1=停用") - private String status; - - public Long getDictId() - { - return dictId; - } - - public void setDictId(Long dictId) - { - this.dictId = dictId; - } - - @NotBlank(message = "字典名称不能为空") - @Size(min = 0, max = 100, message = "字典类型名称长度不能超过100个字符") - public String getDictName() - { - return dictName; - } - - public void setDictName(String dictName) - { - this.dictName = dictName; - } - - @NotBlank(message = "字典类型不能为空") - @Size(min = 0, max = 100, message = "字典类型类型长度不能超过100个字符") - public String getDictType() - { - return dictType; - } - - public void setDictType(String dictType) - { - this.dictType = dictType; - } - - public String getStatus() - { - return status; - } - - public void setStatus(String status) - { - this.status = status; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("dictId", getDictId()) - .append("dictName", getDictName()) - .append("dictType", getDictType()) - .append("status", getStatus()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("remark", getRemark()) - .toString(); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java deleted file mode 100644 index 5e79fc9c..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java +++ /dev/null @@ -1,258 +0,0 @@ -package com.ruoyi.common.core.domain.entity; - -import java.util.ArrayList; -import java.util.List; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Size; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.common.core.domain.BaseEntity; - -/** - * 菜单权限表 sys_menu - * - * @author ruoyi - */ -public class SysMenu extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 菜单ID */ - private Long menuId; - - /** 菜单名称 */ - private String menuName; - - /** 父菜单名称 */ - private String parentName; - - /** 父菜单ID */ - private Long parentId; - - /** 显示顺序 */ - private String orderNum; - - /** 路由地址 */ - private String path; - - /** 组件路径 */ - private String component; - - /** 路由参数 */ - private String query; - - /** 是否为外链(0是 1否) */ - private String isFrame; - - /** 是否缓存(0缓存 1不缓存) */ - private String isCache; - - /** 类型(M目录 C菜单 F按钮) */ - private String menuType; - - /** 显示状态(0显示 1隐藏) */ - private String visible; - - /** 菜单状态(0显示 1隐藏) */ - private String status; - - /** 权限字符串 */ - private String perms; - - /** 菜单图标 */ - private String icon; - - /** 子菜单 */ - private List children = new ArrayList(); - - public Long getMenuId() - { - return menuId; - } - - public void setMenuId(Long menuId) - { - this.menuId = menuId; - } - - @NotBlank(message = "菜单名称不能为空") - @Size(min = 0, max = 50, message = "菜单名称长度不能超过50个字符") - public String getMenuName() - { - return menuName; - } - - public void setMenuName(String menuName) - { - this.menuName = menuName; - } - - public String getParentName() - { - return parentName; - } - - public void setParentName(String parentName) - { - this.parentName = parentName; - } - - public Long getParentId() - { - return parentId; - } - - public void setParentId(Long parentId) - { - this.parentId = parentId; - } - - @NotBlank(message = "显示顺序不能为空") - public String getOrderNum() - { - return orderNum; - } - - public void setOrderNum(String orderNum) - { - this.orderNum = orderNum; - } - - @Size(min = 0, max = 200, message = "路由地址不能超过200个字符") - public String getPath() - { - return path; - } - - public void setPath(String path) - { - this.path = path; - } - - @Size(min = 0, max = 200, message = "组件路径不能超过255个字符") - public String getComponent() - { - return component; - } - - public void setComponent(String component) - { - this.component = component; - } - - public String getQuery() - { - return query; - } - - public void setQuery(String query) - { - this.query = query; - } - - public String getIsFrame() - { - return isFrame; - } - - public void setIsFrame(String isFrame) - { - this.isFrame = isFrame; - } - - public String getIsCache() - { - return isCache; - } - - public void setIsCache(String isCache) - { - this.isCache = isCache; - } - - @NotBlank(message = "菜单类型不能为空") - public String getMenuType() - { - return menuType; - } - - public void setMenuType(String menuType) - { - this.menuType = menuType; - } - - public String getVisible() - { - return visible; - } - - public void setVisible(String visible) - { - this.visible = visible; - } - - public String getStatus() - { - return status; - } - - public void setStatus(String status) - { - this.status = status; - } - - @Size(min = 0, max = 100, message = "权限标识长度不能超过100个字符") - public String getPerms() - { - return perms; - } - - public void setPerms(String perms) - { - this.perms = perms; - } - - public String getIcon() - { - return icon; - } - - public void setIcon(String icon) - { - this.icon = icon; - } - - public List getChildren() - { - return children; - } - - public void setChildren(List children) - { - this.children = children; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("menuId", getMenuId()) - .append("menuName", getMenuName()) - .append("parentId", getParentId()) - .append("orderNum", getOrderNum()) - .append("path", getPath()) - .append("component", getComponent()) - .append("isFrame", getIsFrame()) - .append("IsCache", getIsCache()) - .append("menuType", getMenuType()) - .append("visible", getVisible()) - .append("status ", getStatus()) - .append("perms", getPerms()) - .append("icon", getIcon()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("remark", getRemark()) - .toString(); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java deleted file mode 100644 index 36629eb9..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java +++ /dev/null @@ -1,226 +0,0 @@ -package com.ruoyi.common.core.domain.entity; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Size; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.common.annotation.Excel; -import com.ruoyi.common.annotation.Excel.ColumnType; -import com.ruoyi.common.core.domain.BaseEntity; - -/** - * 角色表 sys_role - * - * @author ruoyi - */ -public class SysRole extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 角色ID */ - @Excel(name = "角色序号", cellType = ColumnType.NUMERIC) - private Long roleId; - - /** 角色名称 */ - @Excel(name = "角色名称") - private String roleName; - - /** 角色权限 */ - @Excel(name = "角色权限") - private String roleKey; - - /** 角色排序 */ - @Excel(name = "角色排序") - private String roleSort; - - /** 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限) */ - @Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限") - private String dataScope; - - /** 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示) */ - private boolean menuCheckStrictly; - - /** 部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 ) */ - private boolean deptCheckStrictly; - - /** 角色状态(0正常 1停用) */ - @Excel(name = "角色状态", readConverterExp = "0=正常,1=停用") - private String status; - - /** 删除标志(0代表存在 2代表删除) */ - private String delFlag; - - /** 用户是否存在此角色标识 默认不存在 */ - private boolean flag = false; - - /** 菜单组 */ - private Long[] menuIds; - - /** 部门组(数据权限) */ - private Long[] deptIds; - - public SysRole() - { - - } - - public SysRole(Long roleId) - { - this.roleId = roleId; - } - - public Long getRoleId() - { - return roleId; - } - - public void setRoleId(Long roleId) - { - this.roleId = roleId; - } - - public boolean isAdmin() - { - return isAdmin(this.roleId); - } - - public static boolean isAdmin(Long roleId) - { - return roleId != null && 1L == roleId; - } - - @NotBlank(message = "角色名称不能为空") - @Size(min = 0, max = 30, message = "角色名称长度不能超过30个字符") - public String getRoleName() - { - return roleName; - } - - public void setRoleName(String roleName) - { - this.roleName = roleName; - } - - @NotBlank(message = "权限字符不能为空") - @Size(min = 0, max = 100, message = "权限字符长度不能超过100个字符") - public String getRoleKey() - { - return roleKey; - } - - public void setRoleKey(String roleKey) - { - this.roleKey = roleKey; - } - - @NotBlank(message = "显示顺序不能为空") - public String getRoleSort() - { - return roleSort; - } - - public void setRoleSort(String roleSort) - { - this.roleSort = roleSort; - } - - public String getDataScope() - { - return dataScope; - } - - public void setDataScope(String dataScope) - { - this.dataScope = dataScope; - } - - public boolean isMenuCheckStrictly() - { - return menuCheckStrictly; - } - - public void setMenuCheckStrictly(boolean menuCheckStrictly) - { - this.menuCheckStrictly = menuCheckStrictly; - } - - public boolean isDeptCheckStrictly() - { - return deptCheckStrictly; - } - - public void setDeptCheckStrictly(boolean deptCheckStrictly) - { - this.deptCheckStrictly = deptCheckStrictly; - } - - public String getStatus() - { - return status; - } - - public void setStatus(String status) - { - this.status = status; - } - - public String getDelFlag() - { - return delFlag; - } - - public void setDelFlag(String delFlag) - { - this.delFlag = delFlag; - } - - public boolean isFlag() - { - return flag; - } - - public void setFlag(boolean flag) - { - this.flag = flag; - } - - public Long[] getMenuIds() - { - return menuIds; - } - - public void setMenuIds(Long[] menuIds) - { - this.menuIds = menuIds; - } - - public Long[] getDeptIds() - { - return deptIds; - } - - public void setDeptIds(Long[] deptIds) - { - this.deptIds = deptIds; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("roleId", getRoleId()) - .append("roleName", getRoleName()) - .append("roleKey", getRoleKey()) - .append("roleSort", getRoleSort()) - .append("dataScope", getDataScope()) - .append("menuCheckStrictly", isMenuCheckStrictly()) - .append("deptCheckStrictly", isDeptCheckStrictly()) - .append("status", getStatus()) - .append("delFlag", getDelFlag()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("remark", getRemark()) - .toString(); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java deleted file mode 100644 index f6968c05..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java +++ /dev/null @@ -1,341 +0,0 @@ -package com.ruoyi.common.core.domain.entity; - -import java.util.Date; -import java.util.List; -import javax.validation.constraints.Email; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Size; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.ruoyi.common.annotation.Excel; -import com.ruoyi.common.annotation.Excel.ColumnType; -import com.ruoyi.common.annotation.Excel.Type; -import com.ruoyi.common.annotation.Excels; -import com.ruoyi.common.core.domain.BaseEntity; - -/** - * 用户对象 sys_user - * - * @author ruoyi - */ -public class SysUser extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 用户ID */ - @Excel(name = "用户序号", cellType = ColumnType.NUMERIC, prompt = "用户编号") - private Long userId; - - /** 部门ID */ - @Excel(name = "部门编号", type = Type.IMPORT) - private Long deptId; - - /** 用户账号 */ - @Excel(name = "登录名称") - private String userName; - - /** 用户昵称 */ - @Excel(name = "用户名称") - private String nickName; - - /** 用户邮箱 */ - @Excel(name = "用户邮箱") - private String email; - - /** 手机号码 */ - @Excel(name = "手机号码") - private String phonenumber; - - /** 用户性别 */ - @Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知") - private String sex; - - /** 用户头像 */ - private String avatar; - - /** 密码 */ - private String password; - - /** 盐加密 */ - private String salt; - - /** 帐号状态(0正常 1停用) */ - @Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用") - private String status; - - /** 删除标志(0代表存在 2代表删除) */ - private String delFlag; - - /** 最后登录IP */ - @Excel(name = "最后登录IP", type = Type.EXPORT) - private String loginIp; - - /** 最后登录时间 */ - @Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT) - private Date loginDate; - - /** 部门对象 */ - @Excels({ - @Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT), - @Excel(name = "部门负责人", targetAttr = "leader", type = Type.EXPORT) - }) - private SysDept dept; - - /** 角色对象 */ - private List roles; - - /** 角色组 */ - private Long[] roleIds; - - /** 岗位组 */ - private Long[] postIds; - - /** 角色ID */ - private Long roleId; - - public SysUser() - { - - } - - public SysUser(Long userId) - { - this.userId = userId; - } - - public Long getUserId() - { - return userId; - } - - public void setUserId(Long userId) - { - this.userId = userId; - } - - public boolean isAdmin() - { - return isAdmin(this.userId); - } - - public static boolean isAdmin(Long userId) - { - return userId != null && 1L == userId; - } - - public Long getDeptId() - { - return deptId; - } - - public void setDeptId(Long deptId) - { - this.deptId = deptId; - } - - @Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符") - public String getNickName() - { - return nickName; - } - - public void setNickName(String nickName) - { - this.nickName = nickName; - } - - @NotBlank(message = "用户账号不能为空") - @Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符") - public String getUserName() - { - return userName; - } - - public void setUserName(String userName) - { - this.userName = userName; - } - - @Email(message = "邮箱格式不正确") - @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符") - public String getEmail() - { - return email; - } - - public void setEmail(String email) - { - this.email = email; - } - - @Size(min = 0, max = 11, message = "手机号码长度不能超过11个字符") - public String getPhonenumber() - { - return phonenumber; - } - - public void setPhonenumber(String phonenumber) - { - this.phonenumber = phonenumber; - } - - public String getSex() - { - return sex; - } - - public void setSex(String sex) - { - this.sex = sex; - } - - public String getAvatar() - { - return avatar; - } - - public void setAvatar(String avatar) - { - this.avatar = avatar; - } - - @JsonIgnore - @JsonProperty - public String getPassword() - { - return password; - } - - public void setPassword(String password) - { - this.password = password; - } - - public String getSalt() - { - return salt; - } - - public void setSalt(String salt) - { - this.salt = salt; - } - - public String getStatus() - { - return status; - } - - public void setStatus(String status) - { - this.status = status; - } - - public String getDelFlag() - { - return delFlag; - } - - public void setDelFlag(String delFlag) - { - this.delFlag = delFlag; - } - - public String getLoginIp() - { - return loginIp; - } - - public void setLoginIp(String loginIp) - { - this.loginIp = loginIp; - } - - public Date getLoginDate() - { - return loginDate; - } - - public void setLoginDate(Date loginDate) - { - this.loginDate = loginDate; - } - - public SysDept getDept() - { - return dept; - } - - public void setDept(SysDept dept) - { - this.dept = dept; - } - - public List getRoles() - { - return roles; - } - - public void setRoles(List roles) - { - this.roles = roles; - } - - public Long[] getRoleIds() - { - return roleIds; - } - - public void setRoleIds(Long[] roleIds) - { - this.roleIds = roleIds; - } - - public Long[] getPostIds() - { - return postIds; - } - - public void setPostIds(Long[] postIds) - { - this.postIds = postIds; - } - - public Long getRoleId() - { - return roleId; - } - - public void setRoleId(Long roleId) - { - this.roleId = roleId; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("userId", getUserId()) - .append("deptId", getDeptId()) - .append("userName", getUserName()) - .append("nickName", getNickName()) - .append("email", getEmail()) - .append("phonenumber", getPhonenumber()) - .append("sex", getSex()) - .append("avatar", getAvatar()) - .append("password", getPassword()) - .append("salt", getSalt()) - .append("status", getStatus()) - .append("delFlag", getDelFlag()) - .append("loginIp", getLoginIp()) - .append("loginDate", getLoginDate()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("remark", getRemark()) - .append("dept", getDept()) - .toString(); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/model/BindLoginBody.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/model/BindLoginBody.java deleted file mode 100644 index bd712c47..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/model/BindLoginBody.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.ruoyi.common.core.domain.model; - -/** - * 用户登录对象 - * - * @author ruoyi - */ -public class BindLoginBody extends LoginBody -{ - /** - * 绑定id - */ - private String bindId; - - public String getBindId() { - return bindId; - } - - public void setBindId(String bindId) { - this.bindId = bindId; - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/model/BindRegisterBody.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/model/BindRegisterBody.java deleted file mode 100644 index c8f64a05..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/model/BindRegisterBody.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.ruoyi.common.core.domain.model; - -/** - * 用户注册对象 - * - * @author ruoyi - */ -public class BindRegisterBody extends RegisterBody { - /** - * 绑定id - */ - private String bindId; - - public String getBindId() { - return bindId; - } - - public void setBindId(String bindId) { - this.bindId = bindId; - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java deleted file mode 100644 index 03948b43..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.ruoyi.common.core.domain.model; - -/** - * 用户登录对象 - * - * @author ruoyi - */ -public class LoginBody -{ - /** - * 用户名 - */ - private String username; - - /** - * 用户密码 - */ - private String password; - - /** - * 验证码 - */ - private String code; - - /** - * 唯一标识 - */ - private String uuid = ""; - - public String getUsername() - { - return username; - } - - public void setUsername(String username) - { - this.username = username; - } - - public String getPassword() - { - return password; - } - - public void setPassword(String password) - { - this.password = password; - } - - public String getCode() - { - return code; - } - - public void setCode(String code) - { - this.code = code; - } - - public String getUuid() - { - return uuid; - } - - public void setUuid(String uuid) - { - this.uuid = uuid; - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java deleted file mode 100644 index db4d2a5a..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java +++ /dev/null @@ -1,266 +0,0 @@ -package com.ruoyi.common.core.domain.model; - -import java.util.Collection; -import java.util.Set; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.userdetails.UserDetails; -import com.alibaba.fastjson.annotation.JSONField; -import com.ruoyi.common.core.domain.entity.SysUser; - -/** - * 登录用户身份权限 - * - * @author ruoyi - */ -public class LoginUser implements UserDetails -{ - private static final long serialVersionUID = 1L; - - /** - * 用户ID - */ - private Long userId; - - /** - * 部门ID - */ - private Long deptId; - - /** - * 用户唯一标识 - */ - private String token; - - /** - * 登录时间 - */ - private Long loginTime; - - /** - * 过期时间 - */ - private Long expireTime; - - /** - * 登录IP地址 - */ - private String ipaddr; - - /** - * 登录地点 - */ - private String loginLocation; - - /** - * 浏览器类型 - */ - private String browser; - - /** - * 操作系统 - */ - private String os; - - /** - * 权限列表 - */ - private Set permissions; - - /** - * 用户信息 - */ - private SysUser user; - - public Long getUserId() - { - return userId; - } - - public void setUserId(Long userId) - { - this.userId = userId; - } - - public Long getDeptId() - { - return deptId; - } - - public void setDeptId(Long deptId) - { - this.deptId = deptId; - } - - public String getToken() - { - return token; - } - - public void setToken(String token) - { - this.token = token; - } - - public LoginUser() - { - } - - public LoginUser(SysUser user, Set permissions) - { - this.user = user; - this.permissions = permissions; - } - - public LoginUser(Long userId, Long deptId, SysUser user, Set permissions) - { - this.userId = userId; - this.deptId = deptId; - this.user = user; - this.permissions = permissions; - } - - @JSONField(serialize = false) - @Override - public String getPassword() - { - return user.getPassword(); - } - - @Override - public String getUsername() - { - return user.getUserName(); - } - - /** - * 账户是否未过期,过期无法验证 - */ - @JSONField(serialize = false) - @Override - public boolean isAccountNonExpired() - { - return true; - } - - /** - * 指定用户是否解锁,锁定的用户无法进行身份验证 - * - * @return - */ - @JSONField(serialize = false) - @Override - public boolean isAccountNonLocked() - { - return true; - } - - /** - * 指示是否已过期的用户的凭据(密码),过期的凭据防止认证 - * - * @return - */ - @JSONField(serialize = false) - @Override - public boolean isCredentialsNonExpired() - { - return true; - } - - /** - * 是否可用 ,禁用的用户不能身份验证 - * - * @return - */ - @JSONField(serialize = false) - @Override - public boolean isEnabled() - { - return true; - } - - public Long getLoginTime() - { - return loginTime; - } - - public void setLoginTime(Long loginTime) - { - this.loginTime = loginTime; - } - - public String getIpaddr() - { - return ipaddr; - } - - public void setIpaddr(String ipaddr) - { - this.ipaddr = ipaddr; - } - - public String getLoginLocation() - { - return loginLocation; - } - - public void setLoginLocation(String loginLocation) - { - this.loginLocation = loginLocation; - } - - public String getBrowser() - { - return browser; - } - - public void setBrowser(String browser) - { - this.browser = browser; - } - - public String getOs() - { - return os; - } - - public void setOs(String os) - { - this.os = os; - } - - public Long getExpireTime() - { - return expireTime; - } - - public void setExpireTime(Long expireTime) - { - this.expireTime = expireTime; - } - - public Set getPermissions() - { - return permissions; - } - - public void setPermissions(Set permissions) - { - this.permissions = permissions; - } - - public SysUser getUser() - { - return user; - } - - public void setUser(SysUser user) - { - this.user = user; - } - - @Override - public Collection getAuthorities() - { - return null; - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java deleted file mode 100644 index 868a1fc5..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.ruoyi.common.core.domain.model; - -/** - * 用户注册对象 - * - * @author ruoyi - */ -public class RegisterBody extends LoginBody -{ - -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java deleted file mode 100644 index 8966cb4c..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.ruoyi.common.core.page; - -import com.ruoyi.common.utils.StringUtils; - -/** - * 分页数据 - * - * @author ruoyi - */ -public class PageDomain -{ - /** 当前记录起始索引 */ - private Integer pageNum; - - /** 每页显示记录数 */ - private Integer pageSize; - - /** 排序列 */ - private String orderByColumn; - - /** 排序的方向desc或者asc */ - private String isAsc = "asc"; - - /** 分页参数合理化 */ - private Boolean reasonable = true; - - public String getOrderBy() - { - if (StringUtils.isEmpty(orderByColumn)) - { - return ""; - } - return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc; - } - - public Integer getPageNum() - { - return pageNum; - } - - public void setPageNum(Integer pageNum) - { - this.pageNum = pageNum; - } - - public Integer getPageSize() - { - return pageSize; - } - - public void setPageSize(Integer pageSize) - { - this.pageSize = pageSize; - } - - public String getOrderByColumn() - { - return orderByColumn; - } - - public void setOrderByColumn(String orderByColumn) - { - this.orderByColumn = orderByColumn; - } - - public String getIsAsc() - { - return isAsc; - } - - public void setIsAsc(String isAsc) - { - if (StringUtils.isNotEmpty(isAsc)) - { - // 兼容前端排序类型 - if ("ascending".equals(isAsc)) - { - isAsc = "asc"; - } - else if ("descending".equals(isAsc)) - { - isAsc = "desc"; - } - this.isAsc = isAsc; - } - } - - public Boolean getReasonable() - { - if (StringUtils.isNull(reasonable)) - { - return Boolean.TRUE; - } - return reasonable; - } - - public void setReasonable(Boolean reasonable) - { - this.reasonable = reasonable; - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java deleted file mode 100644 index 847685ba..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.ruoyi.common.core.page; - -import java.io.Serializable; -import java.util.List; - -/** - * 表格分页数据对象 - * - * @author ruoyi - */ -public class TableDataInfo implements Serializable -{ - private static final long serialVersionUID = 1L; - - /** 总记录数 */ - private long total; - - /** 列表数据 */ - private List rows; - - /** 消息状态码 */ - private int code; - - /** 消息内容 */ - private String msg; - - /** - * 表格数据对象 - */ - public TableDataInfo() - { - } - - /** - * 分页 - * - * @param list 列表数据 - * @param total 总记录数 - */ - public TableDataInfo(List list, int total) - { - this.rows = list; - this.total = total; - } - - public long getTotal() - { - return total; - } - - public void setTotal(long total) - { - this.total = total; - } - - public List getRows() - { - return rows; - } - - public void setRows(List rows) - { - this.rows = rows; - } - - public int getCode() - { - return code; - } - - public void setCode(int code) - { - this.code = code; - } - - public String getMsg() - { - return msg; - } - - public void setMsg(String msg) - { - this.msg = msg; - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java deleted file mode 100644 index 5f301686..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.ruoyi.common.core.page; - -import com.ruoyi.common.utils.ServletUtils; - -/** - * 表格数据处理 - * - * @author ruoyi - */ -public class TableSupport -{ - /** - * 当前记录起始索引 - */ - public static final String PAGE_NUM = "pageNum"; - - /** - * 每页显示记录数 - */ - public static final String PAGE_SIZE = "pageSize"; - - /** - * 排序列 - */ - public static final String ORDER_BY_COLUMN = "orderByColumn"; - - /** - * 排序的方向 "desc" 或者 "asc". - */ - public static final String IS_ASC = "isAsc"; - - /** - * 分页参数合理化 - */ - public static final String REASONABLE = "reasonable"; - - /** - * 封装分页对象 - */ - public static PageDomain getPageDomain() - { - PageDomain pageDomain = new PageDomain(); - pageDomain.setPageNum(ServletUtils.getParameterToInt(PAGE_NUM)); - pageDomain.setPageSize(ServletUtils.getParameterToInt(PAGE_SIZE)); - pageDomain.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN)); - pageDomain.setIsAsc(ServletUtils.getParameter(IS_ASC)); - pageDomain.setReasonable(ServletUtils.getParameterToBool(REASONABLE)); - return pageDomain; - } - - public static PageDomain buildPageRequest() - { - return getPageDomain(); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java deleted file mode 100644 index 551a0cd8..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java +++ /dev/null @@ -1,257 +0,0 @@ -package com.ruoyi.common.core.redis; - -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.core.BoundSetOperations; -import org.springframework.data.redis.core.HashOperations; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.core.ValueOperations; -import org.springframework.stereotype.Component; - -/** - * spring redis 工具类 - * - * @author ruoyi - **/ -@SuppressWarnings(value = { "unchecked", "rawtypes" }) -@Component -public class RedisCache -{ - @Autowired - public RedisTemplate redisTemplate; - - /** - * 缓存基本的对象,Integer、String、实体类等 - * - * @param key 缓存的键值 - * @param value 缓存的值 - */ - public void setCacheObject(final String key, final T value) - { - redisTemplate.opsForValue().set(key, value); - } - - /** - * 缓存基本的对象,Integer、String、实体类等 - * - * @param key 缓存的键值 - * @param value 缓存的值 - * @param timeout 时间 - * @param timeUnit 时间颗粒度 - */ - public void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) - { - redisTemplate.opsForValue().set(key, value, timeout, timeUnit); - } - - /** - * 设置有效时间 - * - * @param key Redis键 - * @param timeout 超时时间 - * @return true=设置成功;false=设置失败 - */ - public boolean expire(final String key, final long timeout) - { - return expire(key, timeout, TimeUnit.SECONDS); - } - - /** - * 设置有效时间 - * - * @param key Redis键 - * @param timeout 超时时间 - * @param unit 时间单位 - * @return true=设置成功;false=设置失败 - */ - public boolean expire(final String key, final long timeout, final TimeUnit unit) - { - return redisTemplate.expire(key, timeout, unit); - } - - /** - * 获得缓存的基本对象。 - * - * @param key 缓存键值 - * @return 缓存键值对应的数据 - */ - public T getCacheObject(final String key) - { - ValueOperations operation = redisTemplate.opsForValue(); - return operation.get(key); - } - - /** - * 删除单个对象 - * - * @param key - */ - public boolean deleteObject(final String key) - { - return redisTemplate.delete(key); - } - - /** - * 删除集合对象 - * - * @param collection 多个对象 - * @return - */ - public long deleteObject(final Collection collection) - { - return redisTemplate.delete(collection); - } - - /** - * 缓存List数据 - * - * @param key 缓存的键值 - * @param dataList 待缓存的List数据 - * @return 缓存的对象 - */ - public long setCacheList(final String key, final List dataList) - { - Long count = redisTemplate.opsForList().rightPushAll(key, dataList); - return count == null ? 0 : count; - } - - /** - * 获得缓存的list对象 - * - * @param key 缓存的键值 - * @return 缓存键值对应的数据 - */ - public List getCacheList(final String key) - { - return redisTemplate.opsForList().range(key, 0, -1); - } - - /** - * 缓存Set - * - * @param key 缓存键值 - * @param dataSet 缓存的数据 - * @return 缓存数据的对象 - */ - public BoundSetOperations setCacheSet(final String key, final Set dataSet) - { - BoundSetOperations setOperation = redisTemplate.boundSetOps(key); - Iterator it = dataSet.iterator(); - while (it.hasNext()) - { - setOperation.add(it.next()); - } - return setOperation; - } - - /** - * 获得缓存的set - * - * @param key - * @return - */ - public Set getCacheSet(final String key) - { - return redisTemplate.opsForSet().members(key); - } - - /** - * 缓存Map - * - * @param key - * @param dataMap - */ - public void setCacheMap(final String key, final Map dataMap) - { - if (dataMap != null) { - redisTemplate.opsForHash().putAll(key, dataMap); - } - } - - /** - * 获得缓存的Map - * - * @param key - * @return - */ - public Map getCacheMap(final String key) - { - return redisTemplate.opsForHash().entries(key); - } - - /** - * 往Hash中存入数据 - * - * @param key Redis键 - * @param hKey Hash键 - * @param value 值 - */ - public void setCacheMapValue(final String key, final String hKey, final T value) - { - redisTemplate.opsForHash().put(key, hKey, value); - } - - /** - * 获取Hash中的数据 - * - * @param key Redis键 - * @param hKey Hash键 - * @return Hash中的对象 - */ - public T getCacheMapValue(final String key, final String hKey) - { - HashOperations opsForHash = redisTemplate.opsForHash(); - return opsForHash.get(key, hKey); - } - - /** - * 删除Hash中的数据 - * - * @param key - * @param hkey - */ - public void delCacheMapValue(final String key, final String hkey) - { - HashOperations hashOperations = redisTemplate.opsForHash(); - hashOperations.delete(key, hkey); - } - - /** - * 获取多个Hash中的数据 - * - * @param key Redis键 - * @param hKeys Hash键集合 - * @return Hash对象集合 - */ - public List getMultiCacheMapValue(final String key, final Collection hKeys) - { - return redisTemplate.opsForHash().multiGet(key, hKeys); - } - - /** - * 获得缓存的基本对象列表 - * - * @param pattern 字符串前缀 - * @return 对象列表 - */ - public Collection keys(final String pattern) - { - return redisTemplate.keys(pattern); - } - - /** - * 是否存在key - * - * @param key 缓存key - * @return true:存在key ;false:key不存在或者已过期 - */ - public boolean containsKey(String key) { - return redisTemplate.hasKey(key); - } - -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java deleted file mode 100644 index 84124aac..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.ruoyi.common.core.text; - -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import com.ruoyi.common.utils.StringUtils; - -/** - * 字符集工具类 - * - * @author ruoyi - */ -public class CharsetKit -{ - /** ISO-8859-1 */ - public static final String ISO_8859_1 = "ISO-8859-1"; - /** UTF-8 */ - public static final String UTF_8 = "UTF-8"; - /** GBK */ - public static final String GBK = "GBK"; - - /** ISO-8859-1 */ - public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1); - /** UTF-8 */ - public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8); - /** GBK */ - public static final Charset CHARSET_GBK = Charset.forName(GBK); - - /** - * 转换为Charset对象 - * - * @param charset 字符集,为空则返回默认字符集 - * @return Charset - */ - public static Charset charset(String charset) - { - return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset); - } - - /** - * 转换字符串的字符集编码 - * - * @param source 字符串 - * @param srcCharset 源字符集,默认ISO-8859-1 - * @param destCharset 目标字符集,默认UTF-8 - * @return 转换后的字符集 - */ - public static String convert(String source, String srcCharset, String destCharset) - { - return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset)); - } - - /** - * 转换字符串的字符集编码 - * - * @param source 字符串 - * @param srcCharset 源字符集,默认ISO-8859-1 - * @param destCharset 目标字符集,默认UTF-8 - * @return 转换后的字符集 - */ - public static String convert(String source, Charset srcCharset, Charset destCharset) - { - if (null == srcCharset) - { - srcCharset = StandardCharsets.ISO_8859_1; - } - - if (null == destCharset) - { - destCharset = StandardCharsets.UTF_8; - } - - if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset)) - { - return source; - } - return new String(source.getBytes(srcCharset), destCharset); - } - - /** - * @return 系统字符集编码 - */ - public static String systemCharset() - { - return Charset.defaultCharset().name(); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/text/Convert.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/text/Convert.java deleted file mode 100644 index 1fb74619..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/text/Convert.java +++ /dev/null @@ -1,1005 +0,0 @@ -package com.ruoyi.common.core.text; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.text.NumberFormat; -import java.util.Set; -import com.ruoyi.common.utils.StringUtils; -import org.apache.commons.lang3.ArrayUtils; - -/** - * 类型转换器 - * - * @author ruoyi - */ -public class Convert -{ - /** - * 转换为字符串
- * 如果给定的值为null,或者转换失败,返回默认值
- * 转换失败不会报错 - * - * @param value 被转换的值 - * @param defaultValue 转换错误时的默认值 - * @return 结果 - */ - public static String toStr(Object value, String defaultValue) - { - if (null == value) - { - return defaultValue; - } - if (value instanceof String) - { - return (String) value; - } - return value.toString(); - } - - /** - * 转换为字符串
- * 如果给定的值为null,或者转换失败,返回默认值null
- * 转换失败不会报错 - * - * @param value 被转换的值 - * @return 结果 - */ - public static String toStr(Object value) - { - return toStr(value, null); - } - - /** - * 转换为字符
- * 如果给定的值为null,或者转换失败,返回默认值
- * 转换失败不会报错 - * - * @param value 被转换的值 - * @param defaultValue 转换错误时的默认值 - * @return 结果 - */ - public static Character toChar(Object value, Character defaultValue) - { - if (null == value) - { - return defaultValue; - } - if (value instanceof Character) - { - return (Character) value; - } - - final String valueStr = toStr(value, null); - return StringUtils.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0); - } - - /** - * 转换为字符
- * 如果给定的值为null,或者转换失败,返回默认值null
- * 转换失败不会报错 - * - * @param value 被转换的值 - * @return 结果 - */ - public static Character toChar(Object value) - { - return toChar(value, null); - } - - /** - * 转换为byte
- * 如果给定的值为null,或者转换失败,返回默认值
- * 转换失败不会报错 - * - * @param value 被转换的值 - * @param defaultValue 转换错误时的默认值 - * @return 结果 - */ - public static Byte toByte(Object value, Byte defaultValue) - { - if (value == null) - { - return defaultValue; - } - if (value instanceof Byte) - { - return (Byte) value; - } - if (value instanceof Number) - { - return ((Number) value).byteValue(); - } - final String valueStr = toStr(value, null); - if (StringUtils.isEmpty(valueStr)) - { - return defaultValue; - } - try - { - return Byte.parseByte(valueStr); - } - catch (Exception e) - { - return defaultValue; - } - } - - /** - * 转换为byte
- * 如果给定的值为null,或者转换失败,返回默认值null
- * 转换失败不会报错 - * - * @param value 被转换的值 - * @return 结果 - */ - public static Byte toByte(Object value) - { - return toByte(value, null); - } - - /** - * 转换为Short
- * 如果给定的值为null,或者转换失败,返回默认值
- * 转换失败不会报错 - * - * @param value 被转换的值 - * @param defaultValue 转换错误时的默认值 - * @return 结果 - */ - public static Short toShort(Object value, Short defaultValue) - { - if (value == null) - { - return defaultValue; - } - if (value instanceof Short) - { - return (Short) value; - } - if (value instanceof Number) - { - return ((Number) value).shortValue(); - } - final String valueStr = toStr(value, null); - if (StringUtils.isEmpty(valueStr)) - { - return defaultValue; - } - try - { - return Short.parseShort(valueStr.trim()); - } - catch (Exception e) - { - return defaultValue; - } - } - - /** - * 转换为Short
- * 如果给定的值为null,或者转换失败,返回默认值null
- * 转换失败不会报错 - * - * @param value 被转换的值 - * @return 结果 - */ - public static Short toShort(Object value) - { - return toShort(value, null); - } - - /** - * 转换为Number
- * 如果给定的值为空,或者转换失败,返回默认值
- * 转换失败不会报错 - * - * @param value 被转换的值 - * @param defaultValue 转换错误时的默认值 - * @return 结果 - */ - public static Number toNumber(Object value, Number defaultValue) - { - if (value == null) - { - return defaultValue; - } - if (value instanceof Number) - { - return (Number) value; - } - final String valueStr = toStr(value, null); - if (StringUtils.isEmpty(valueStr)) - { - return defaultValue; - } - try - { - return NumberFormat.getInstance().parse(valueStr); - } - catch (Exception e) - { - return defaultValue; - } - } - - /** - * 转换为Number
- * 如果给定的值为空,或者转换失败,返回默认值null
- * 转换失败不会报错 - * - * @param value 被转换的值 - * @return 结果 - */ - public static Number toNumber(Object value) - { - return toNumber(value, null); - } - - /** - * 转换为int
- * 如果给定的值为空,或者转换失败,返回默认值
- * 转换失败不会报错 - * - * @param value 被转换的值 - * @param defaultValue 转换错误时的默认值 - * @return 结果 - */ - public static Integer toInt(Object value, Integer defaultValue) - { - if (value == null) - { - return defaultValue; - } - if (value instanceof Integer) - { - return (Integer) value; - } - if (value instanceof Number) - { - return ((Number) value).intValue(); - } - final String valueStr = toStr(value, null); - if (StringUtils.isEmpty(valueStr)) - { - return defaultValue; - } - try - { - return Integer.parseInt(valueStr.trim()); - } - catch (Exception e) - { - return defaultValue; - } - } - - /** - * 转换为int
- * 如果给定的值为null,或者转换失败,返回默认值null
- * 转换失败不会报错 - * - * @param value 被转换的值 - * @return 结果 - */ - public static Integer toInt(Object value) - { - return toInt(value, null); - } - - /** - * 转换为Integer数组
- * - * @param str 被转换的值 - * @return 结果 - */ - public static Integer[] toIntArray(String str) - { - return toIntArray(",", str); - } - - /** - * 转换为Long数组
- * - * @param str 被转换的值 - * @return 结果 - */ - public static Long[] toLongArray(String str) - { - return toLongArray(",", str); - } - - /** - * 转换为Integer数组
- * - * @param split 分隔符 - * @param split 被转换的值 - * @return 结果 - */ - public static Integer[] toIntArray(String split, String str) - { - if (StringUtils.isEmpty(str)) - { - return new Integer[] {}; - } - String[] arr = str.split(split); - final Integer[] ints = new Integer[arr.length]; - for (int i = 0; i < arr.length; i++) - { - final Integer v = toInt(arr[i], 0); - ints[i] = v; - } - return ints; - } - - /** - * 转换为Long数组
- * - * @param split 分隔符 - * @param str 被转换的值 - * @return 结果 - */ - public static Long[] toLongArray(String split, String str) - { - if (StringUtils.isEmpty(str)) - { - return new Long[] {}; - } - String[] arr = str.split(split); - final Long[] longs = new Long[arr.length]; - for (int i = 0; i < arr.length; i++) - { - final Long v = toLong(arr[i], null); - longs[i] = v; - } - return longs; - } - - /** - * 转换为String数组
- * - * @param str 被转换的值 - * @return 结果 - */ - public static String[] toStrArray(String str) - { - return toStrArray(",", str); - } - - /** - * 转换为String数组
- * - * @param split 分隔符 - * @param split 被转换的值 - * @return 结果 - */ - public static String[] toStrArray(String split, String str) - { - return str.split(split); - } - - /** - * 转换为long
- * 如果给定的值为空,或者转换失败,返回默认值
- * 转换失败不会报错 - * - * @param value 被转换的值 - * @param defaultValue 转换错误时的默认值 - * @return 结果 - */ - public static Long toLong(Object value, Long defaultValue) - { - if (value == null) - { - return defaultValue; - } - if (value instanceof Long) - { - return (Long) value; - } - if (value instanceof Number) - { - return ((Number) value).longValue(); - } - final String valueStr = toStr(value, null); - if (StringUtils.isEmpty(valueStr)) - { - return defaultValue; - } - try - { - // 支持科学计数法 - return new BigDecimal(valueStr.trim()).longValue(); - } - catch (Exception e) - { - return defaultValue; - } - } - - /** - * 转换为long
- * 如果给定的值为null,或者转换失败,返回默认值null
- * 转换失败不会报错 - * - * @param value 被转换的值 - * @return 结果 - */ - public static Long toLong(Object value) - { - return toLong(value, null); - } - - /** - * 转换为double
- * 如果给定的值为空,或者转换失败,返回默认值
- * 转换失败不会报错 - * - * @param value 被转换的值 - * @param defaultValue 转换错误时的默认值 - * @return 结果 - */ - public static Double toDouble(Object value, Double defaultValue) - { - if (value == null) - { - return defaultValue; - } - if (value instanceof Double) - { - return (Double) value; - } - if (value instanceof Number) - { - return ((Number) value).doubleValue(); - } - final String valueStr = toStr(value, null); - if (StringUtils.isEmpty(valueStr)) - { - return defaultValue; - } - try - { - // 支持科学计数法 - return new BigDecimal(valueStr.trim()).doubleValue(); - } - catch (Exception e) - { - return defaultValue; - } - } - - /** - * 转换为double
- * 如果给定的值为空,或者转换失败,返回默认值null
- * 转换失败不会报错 - * - * @param value 被转换的值 - * @return 结果 - */ - public static Double toDouble(Object value) - { - return toDouble(value, null); - } - - /** - * 转换为Float
- * 如果给定的值为空,或者转换失败,返回默认值
- * 转换失败不会报错 - * - * @param value 被转换的值 - * @param defaultValue 转换错误时的默认值 - * @return 结果 - */ - public static Float toFloat(Object value, Float defaultValue) - { - if (value == null) - { - return defaultValue; - } - if (value instanceof Float) - { - return (Float) value; - } - if (value instanceof Number) - { - return ((Number) value).floatValue(); - } - final String valueStr = toStr(value, null); - if (StringUtils.isEmpty(valueStr)) - { - return defaultValue; - } - try - { - return Float.parseFloat(valueStr.trim()); - } - catch (Exception e) - { - return defaultValue; - } - } - - /** - * 转换为Float
- * 如果给定的值为空,或者转换失败,返回默认值null
- * 转换失败不会报错 - * - * @param value 被转换的值 - * @return 结果 - */ - public static Float toFloat(Object value) - { - return toFloat(value, null); - } - - /** - * 转换为boolean
- * String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值
- * 转换失败不会报错 - * - * @param value 被转换的值 - * @param defaultValue 转换错误时的默认值 - * @return 结果 - */ - public static Boolean toBool(Object value, Boolean defaultValue) - { - if (value == null) - { - return defaultValue; - } - if (value instanceof Boolean) - { - return (Boolean) value; - } - String valueStr = toStr(value, null); - if (StringUtils.isEmpty(valueStr)) - { - return defaultValue; - } - valueStr = valueStr.trim().toLowerCase(); - switch (valueStr) - { - case "true": - return true; - case "false": - return false; - case "yes": - return true; - case "ok": - return true; - case "no": - return false; - case "1": - return true; - case "0": - return false; - default: - return defaultValue; - } - } - - /** - * 转换为boolean
- * 如果给定的值为空,或者转换失败,返回默认值null
- * 转换失败不会报错 - * - * @param value 被转换的值 - * @return 结果 - */ - public static Boolean toBool(Object value) - { - return toBool(value, null); - } - - /** - * 转换为Enum对象
- * 如果给定的值为空,或者转换失败,返回默认值
- * - * @param clazz Enum的Class - * @param value 值 - * @param defaultValue 默认值 - * @return Enum - */ - public static > E toEnum(Class clazz, Object value, E defaultValue) - { - if (value == null) - { - return defaultValue; - } - if (clazz.isAssignableFrom(value.getClass())) - { - @SuppressWarnings("unchecked") - E myE = (E) value; - return myE; - } - final String valueStr = toStr(value, null); - if (StringUtils.isEmpty(valueStr)) - { - return defaultValue; - } - try - { - return Enum.valueOf(clazz, valueStr); - } - catch (Exception e) - { - return defaultValue; - } - } - - /** - * 转换为Enum对象
- * 如果给定的值为空,或者转换失败,返回默认值null
- * - * @param clazz Enum的Class - * @param value 值 - * @return Enum - */ - public static > E toEnum(Class clazz, Object value) - { - return toEnum(clazz, value, null); - } - - /** - * 转换为BigInteger
- * 如果给定的值为空,或者转换失败,返回默认值
- * 转换失败不会报错 - * - * @param value 被转换的值 - * @param defaultValue 转换错误时的默认值 - * @return 结果 - */ - public static BigInteger toBigInteger(Object value, BigInteger defaultValue) - { - if (value == null) - { - return defaultValue; - } - if (value instanceof BigInteger) - { - return (BigInteger) value; - } - if (value instanceof Long) - { - return BigInteger.valueOf((Long) value); - } - final String valueStr = toStr(value, null); - if (StringUtils.isEmpty(valueStr)) - { - return defaultValue; - } - try - { - return new BigInteger(valueStr); - } - catch (Exception e) - { - return defaultValue; - } - } - - /** - * 转换为BigInteger
- * 如果给定的值为空,或者转换失败,返回默认值null
- * 转换失败不会报错 - * - * @param value 被转换的值 - * @return 结果 - */ - public static BigInteger toBigInteger(Object value) - { - return toBigInteger(value, null); - } - - /** - * 转换为BigDecimal
- * 如果给定的值为空,或者转换失败,返回默认值
- * 转换失败不会报错 - * - * @param value 被转换的值 - * @param defaultValue 转换错误时的默认值 - * @return 结果 - */ - public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue) - { - if (value == null) - { - return defaultValue; - } - if (value instanceof BigDecimal) - { - return (BigDecimal) value; - } - if (value instanceof Long) - { - return new BigDecimal((Long) value); - } - if (value instanceof Double) - { - return new BigDecimal((Double) value); - } - if (value instanceof Integer) - { - return new BigDecimal((Integer) value); - } - final String valueStr = toStr(value, null); - if (StringUtils.isEmpty(valueStr)) - { - return defaultValue; - } - try - { - return new BigDecimal(valueStr); - } - catch (Exception e) - { - return defaultValue; - } - } - - /** - * 转换为BigDecimal
- * 如果给定的值为空,或者转换失败,返回默认值
- * 转换失败不会报错 - * - * @param value 被转换的值 - * @return 结果 - */ - public static BigDecimal toBigDecimal(Object value) - { - return toBigDecimal(value, null); - } - - /** - * 将对象转为字符串
- * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 - * - * @param obj 对象 - * @return 字符串 - */ - public static String utf8Str(Object obj) - { - return str(obj, CharsetKit.CHARSET_UTF_8); - } - - /** - * 将对象转为字符串
- * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 - * - * @param obj 对象 - * @param charsetName 字符集 - * @return 字符串 - */ - public static String str(Object obj, String charsetName) - { - return str(obj, Charset.forName(charsetName)); - } - - /** - * 将对象转为字符串
- * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 - * - * @param obj 对象 - * @param charset 字符集 - * @return 字符串 - */ - public static String str(Object obj, Charset charset) - { - if (null == obj) - { - return null; - } - - if (obj instanceof String) - { - return (String) obj; - } - else if (obj instanceof byte[]) - { - return str((byte[]) obj, charset); - } - else if (obj instanceof Byte[]) - { - byte[] bytes = ArrayUtils.toPrimitive((Byte[]) obj); - return str(bytes, charset); - } - else if (obj instanceof ByteBuffer) - { - return str((ByteBuffer) obj, charset); - } - return obj.toString(); - } - - /** - * 将byte数组转为字符串 - * - * @param bytes byte数组 - * @param charset 字符集 - * @return 字符串 - */ - public static String str(byte[] bytes, String charset) - { - return str(bytes, StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset)); - } - - /** - * 解码字节码 - * - * @param data 字符串 - * @param charset 字符集,如果此字段为空,则解码的结果取决于平台 - * @return 解码后的字符串 - */ - public static String str(byte[] data, Charset charset) - { - if (data == null) - { - return null; - } - - if (null == charset) - { - return new String(data); - } - return new String(data, charset); - } - - /** - * 将编码的byteBuffer数据转换为字符串 - * - * @param data 数据 - * @param charset 字符集,如果为空使用当前系统字符集 - * @return 字符串 - */ - public static String str(ByteBuffer data, String charset) - { - if (data == null) - { - return null; - } - - return str(data, Charset.forName(charset)); - } - - /** - * 将编码的byteBuffer数据转换为字符串 - * - * @param data 数据 - * @param charset 字符集,如果为空使用当前系统字符集 - * @return 字符串 - */ - public static String str(ByteBuffer data, Charset charset) - { - if (null == charset) - { - charset = Charset.defaultCharset(); - } - return charset.decode(data).toString(); - } - - // ----------------------------------------------------------------------- 全角半角转换 - /** - * 半角转全角 - * - * @param input String. - * @return 全角字符串. - */ - public static String toSBC(String input) - { - return toSBC(input, null); - } - - /** - * 半角转全角 - * - * @param input String - * @param notConvertSet 不替换的字符集合 - * @return 全角字符串. - */ - public static String toSBC(String input, Set notConvertSet) - { - char c[] = input.toCharArray(); - for (int i = 0; i < c.length; i++) - { - if (null != notConvertSet && notConvertSet.contains(c[i])) - { - // 跳过不替换的字符 - continue; - } - - if (c[i] == ' ') - { - c[i] = '\u3000'; - } - else if (c[i] < '\177') - { - c[i] = (char) (c[i] + 65248); - - } - } - return new String(c); - } - - /** - * 全角转半角 - * - * @param input String. - * @return 半角字符串 - */ - public static String toDBC(String input) - { - return toDBC(input, null); - } - - /** - * 替换全角为半角 - * - * @param text 文本 - * @param notConvertSet 不替换的字符集合 - * @return 替换后的字符 - */ - public static String toDBC(String text, Set notConvertSet) - { - char c[] = text.toCharArray(); - for (int i = 0; i < c.length; i++) - { - if (null != notConvertSet && notConvertSet.contains(c[i])) - { - // 跳过不替换的字符 - continue; - } - - if (c[i] == '\u3000') - { - c[i] = ' '; - } - else if (c[i] > '\uFF00' && c[i] < '\uFF5F') - { - c[i] = (char) (c[i] - 65248); - } - } - String returnString = new String(c); - - return returnString; - } - - /** - * 数字金额大写转换 先写个完整的然后将如零拾替换成零 - * - * @param n 数字 - * @return 中文大写数字 - */ - public static String digitUppercase(double n) - { - String[] fraction = { "角", "分" }; - String[] digit = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" }; - String[][] unit = { { "元", "万", "亿" }, { "", "拾", "佰", "仟" } }; - - String head = n < 0 ? "负" : ""; - n = Math.abs(n); - - String s = ""; - for (int i = 0; i < fraction.length; i++) - { - s += (digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", ""); - } - if (s.length() < 1) - { - s = "整"; - } - int integerPart = (int) Math.floor(n); - - for (int i = 0; i < unit[0].length && integerPart > 0; i++) - { - String p = ""; - for (int j = 0; j < unit[1].length && n > 0; j++) - { - p = digit[integerPart % 10] + unit[1][j] + p; - integerPart = integerPart / 10; - } - s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s; - } - return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整"); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java deleted file mode 100644 index c78ac776..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.ruoyi.common.core.text; - -import com.ruoyi.common.utils.StringUtils; - -/** - * 字符串格式化 - * - * @author ruoyi - */ -public class StrFormatter -{ - public static final String EMPTY_JSON = "{}"; - public static final char C_BACKSLASH = '\\'; - public static final char C_DELIM_START = '{'; - public static final char C_DELIM_END = '}'; - - /** - * 格式化字符串
- * 此方法只是简单将占位符 {} 按照顺序替换为参数
- * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
- * 例:
- * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
- * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
- * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
- * - * @param strPattern 字符串模板 - * @param argArray 参数列表 - * @return 结果 - */ - public static String format(final String strPattern, final Object... argArray) - { - if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray)) - { - return strPattern; - } - final int strPatternLength = strPattern.length(); - - // 初始化定义好的长度以获得更好的性能 - StringBuilder sbuf = new StringBuilder(strPatternLength + 50); - - int handledPosition = 0; - int delimIndex;// 占位符所在位置 - for (int argIndex = 0; argIndex < argArray.length; argIndex++) - { - delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition); - if (delimIndex == -1) - { - if (handledPosition == 0) - { - return strPattern; - } - else - { // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果 - sbuf.append(strPattern, handledPosition, strPatternLength); - return sbuf.toString(); - } - } - else - { - if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH) - { - if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH) - { - // 转义符之前还有一个转义符,占位符依旧有效 - sbuf.append(strPattern, handledPosition, delimIndex - 1); - sbuf.append(Convert.utf8Str(argArray[argIndex])); - handledPosition = delimIndex + 2; - } - else - { - // 占位符被转义 - argIndex--; - sbuf.append(strPattern, handledPosition, delimIndex - 1); - sbuf.append(C_DELIM_START); - handledPosition = delimIndex + 1; - } - } - else - { - // 正常占位符 - sbuf.append(strPattern, handledPosition, delimIndex); - sbuf.append(Convert.utf8Str(argArray[argIndex])); - handledPosition = delimIndex + 2; - } - } - } - // 加入最后一个占位符后所有的字符 - sbuf.append(strPattern, handledPosition, strPattern.length()); - - return sbuf.toString(); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java deleted file mode 100644 index 10b7306f..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.ruoyi.common.enums; - -/** - * 操作状态 - * - * @author ruoyi - * - */ -public enum BusinessStatus -{ - /** - * 成功 - */ - SUCCESS, - - /** - * 失败 - */ - FAIL, -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/BusinessType.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/BusinessType.java deleted file mode 100644 index 2e17c4a5..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/BusinessType.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.ruoyi.common.enums; - -/** - * 业务操作类型 - * - * @author ruoyi - */ -public enum BusinessType -{ - /** - * 其它 - */ - OTHER, - - /** - * 新增 - */ - INSERT, - - /** - * 修改 - */ - UPDATE, - - /** - * 删除 - */ - DELETE, - - /** - * 授权 - */ - GRANT, - - /** - * 导出 - */ - EXPORT, - - /** - * 导入 - */ - IMPORT, - - /** - * 强退 - */ - FORCE, - - /** - * 生成代码 - */ - GENCODE, - - /** - * 清空数据 - */ - CLEAN, -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java deleted file mode 100644 index 0d945be5..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.ruoyi.common.enums; - -/** - * 数据源 - * - * @author ruoyi - */ -public enum DataSourceType -{ - /** - * 主库 - */ - MASTER, - - /** - * 从库 - */ - SLAVE -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java deleted file mode 100644 index be6f7392..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.ruoyi.common.enums; - -import java.util.HashMap; -import java.util.Map; -import org.springframework.lang.Nullable; - -/** - * 请求方式 - * - * @author ruoyi - */ -public enum HttpMethod -{ - GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE; - - private static final Map mappings = new HashMap<>(16); - - static - { - for (HttpMethod httpMethod : values()) - { - mappings.put(httpMethod.name(), httpMethod); - } - } - - @Nullable - public static HttpMethod resolve(@Nullable String method) - { - return (method != null ? mappings.get(method) : null); - } - - public boolean matches(String method) - { - return (this == resolve(method)); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/LimitType.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/LimitType.java deleted file mode 100644 index c609fd8a..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/LimitType.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.ruoyi.common.enums; - -/** - * 限流类型 - * - * @author ruoyi - */ - -public enum LimitType -{ - /** - * 默认策略全局限流 - */ - DEFAULT, - - /** - * 根据请求者IP进行限流 - */ - IP -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/OperatorType.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/OperatorType.java deleted file mode 100644 index bdd143c1..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/OperatorType.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.ruoyi.common.enums; - -/** - * 操作人类别 - * - * @author ruoyi - */ -public enum OperatorType -{ - /** - * 其它 - */ - OTHER, - - /** - * 后台用户 - */ - MANAGE, - - /** - * 手机端用户 - */ - MOBILE -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/SocialPlatformType.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/SocialPlatformType.java deleted file mode 100644 index 4cb6be8b..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/SocialPlatformType.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.ruoyi.common.enums; - -/** - * 第三方登录平台 - * - * @author json - */ -public enum SocialPlatformType { - Wechat, QQ -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/UserStatus.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/UserStatus.java deleted file mode 100644 index d7ff44a9..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/UserStatus.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.ruoyi.common.enums; - -/** - * 用户状态 - * - * @author ruoyi - */ -public enum UserStatus -{ - OK("0", "正常"), DISABLE("1", "停用"), DELETED("2", "删除"); - - private final String code; - private final String info; - - UserStatus(String code, String info) - { - this.code = code; - this.info = info; - } - - public String getCode() - { - return code; - } - - public String getInfo() - { - return info; - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java deleted file mode 100644 index f6ad2ab4..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.ruoyi.common.exception; - -/** - * 演示模式异常 - * - * @author ruoyi - */ -public class DemoModeException extends RuntimeException -{ - private static final long serialVersionUID = 1L; - - public DemoModeException() - { - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/GlobalException.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/GlobalException.java deleted file mode 100644 index 211441bf..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/GlobalException.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.ruoyi.common.exception; - -/** - * 全局异常 - * - * @author ruoyi - */ -public class GlobalException extends RuntimeException -{ - - private static final long serialVersionUID = 1L; - - /** - * 错误提示 - */ - private String message; - - /** - * 错误明细,内部调试错误 - * - * 和 {@link CommonResult#getDetailMessage()} 一致的设计 - */ - private String detailMessage; - - /** - * 空构造方法,避免反序列化问题 - */ - public GlobalException() - { - } - - public GlobalException(String message) - { - this.message = message; - } - - public String getDetailMessage() - { - return detailMessage; - } - - public GlobalException setDetailMessage(String detailMessage) - { - this.detailMessage = detailMessage; - return this; - } - - public String getMessage() - { - return message; - } - - public GlobalException setMessage(String message) - { - this.message = message; - return this; - } -} \ No newline at end of file diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/ServiceException.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/ServiceException.java deleted file mode 100644 index 6297f87f..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/ServiceException.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.ruoyi.common.exception; - -/** - * 业务异常 - * - * @author ruoyi - */ -public final class ServiceException extends RuntimeException -{ - private static final long serialVersionUID = 1L; - - /** - * 错误码 - */ - private Integer code; - - /** - * 错误提示 - */ - private String message; - - /** - * 错误明细,内部调试错误 - * - * 和 {@link CommonResult#getDetailMessage()} 一致的设计 - */ - private String detailMessage; - - /** - * 空构造方法,避免反序列化问题 - */ - public ServiceException() - { - } - - public ServiceException(String message) - { - this.message = message; - } - - public ServiceException(String message, Integer code) - { - this.message = message; - this.code = code; - } - - public String getDetailMessage() - { - return detailMessage; - } - - public String getMessage() - { - return message; - } - - public Integer getCode() - { - return code; - } - - public ServiceException setMessage(String message) - { - this.message = message; - return this; - } - - public ServiceException setDetailMessage(String detailMessage) - { - this.detailMessage = detailMessage; - return this; - } -} \ No newline at end of file diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/UtilException.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/UtilException.java deleted file mode 100644 index 980fa465..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/UtilException.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.ruoyi.common.exception; - -/** - * 工具类异常 - * - * @author ruoyi - */ -public class UtilException extends RuntimeException -{ - private static final long serialVersionUID = 8247610319171014183L; - - public UtilException(Throwable e) - { - super(e.getMessage(), e); - } - - public UtilException(String message) - { - super(message); - } - - public UtilException(String message, Throwable throwable) - { - super(message, throwable); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java deleted file mode 100644 index b55d72e1..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.ruoyi.common.exception.base; - -import com.ruoyi.common.utils.MessageUtils; -import com.ruoyi.common.utils.StringUtils; - -/** - * 基础异常 - * - * @author ruoyi - */ -public class BaseException extends RuntimeException -{ - private static final long serialVersionUID = 1L; - - /** - * 所属模块 - */ - private String module; - - /** - * 错误码 - */ - private String code; - - /** - * 错误码对应的参数 - */ - private Object[] args; - - /** - * 错误消息 - */ - private String defaultMessage; - - public BaseException(String module, String code, Object[] args, String defaultMessage) - { - this.module = module; - this.code = code; - this.args = args; - this.defaultMessage = defaultMessage; - } - - public BaseException(String module, String code, Object[] args) - { - this(module, code, args, null); - } - - public BaseException(String module, String defaultMessage) - { - this(module, null, null, defaultMessage); - } - - public BaseException(String code, Object[] args) - { - this(null, code, args, null); - } - - public BaseException(String defaultMessage) - { - this(null, null, null, defaultMessage); - } - - @Override - public String getMessage() - { - String message = null; - if (!StringUtils.isEmpty(code)) - { - message = MessageUtils.message(code, args); - } - if (message == null) - { - message = defaultMessage; - } - return message; - } - - public String getModule() - { - return module; - } - - public String getCode() - { - return code; - } - - public Object[] getArgs() - { - return args; - } - - public String getDefaultMessage() - { - return defaultMessage; - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/file/FileException.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/file/FileException.java deleted file mode 100644 index 871f09b5..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/file/FileException.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.ruoyi.common.exception.file; - -import com.ruoyi.common.exception.base.BaseException; - -/** - * 文件信息异常类 - * - * @author ruoyi - */ -public class FileException extends BaseException -{ - private static final long serialVersionUID = 1L; - - public FileException(String code, Object[] args) - { - super("file", code, args, null); - } - -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java deleted file mode 100644 index 70e0ec9b..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.ruoyi.common.exception.file; - -/** - * 文件名称超长限制异常类 - * - * @author ruoyi - */ -public class FileNameLengthLimitExceededException extends FileException -{ - private static final long serialVersionUID = 1L; - - public FileNameLengthLimitExceededException(int defaultFileNameLength) - { - super("upload.filename.exceed.length", new Object[] { defaultFileNameLength }); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java deleted file mode 100644 index ec6ab054..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.ruoyi.common.exception.file; - -/** - * 文件名大小限制异常类 - * - * @author ruoyi - */ -public class FileSizeLimitExceededException extends FileException -{ - private static final long serialVersionUID = 1L; - - public FileSizeLimitExceededException(long defaultMaxSize) - { - super("upload.exceed.maxSize", new Object[] { defaultMaxSize }); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java deleted file mode 100644 index f1c8e835..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.ruoyi.common.exception.file; - -import java.util.Arrays; -import org.apache.commons.fileupload.FileUploadException; - -/** - * 文件上传 误异常类 - * - * @author ruoyi - */ -public class InvalidExtensionException extends FileUploadException -{ - private static final long serialVersionUID = 1L; - - private String[] allowedExtension; - private String extension; - private String filename; - - public InvalidExtensionException(String[] allowedExtension, String extension, String filename) - { - super("filename : [" + filename + "], extension : [" + extension + "], allowed extension : [" + Arrays.toString(allowedExtension) + "]"); - this.allowedExtension = allowedExtension; - this.extension = extension; - this.filename = filename; - } - - public String[] getAllowedExtension() - { - return allowedExtension; - } - - public String getExtension() - { - return extension; - } - - public String getFilename() - { - return filename; - } - - public static class InvalidImageExtensionException extends InvalidExtensionException - { - private static final long serialVersionUID = 1L; - - public InvalidImageExtensionException(String[] allowedExtension, String extension, String filename) - { - super(allowedExtension, extension, filename); - } - } - - public static class InvalidFlashExtensionException extends InvalidExtensionException - { - private static final long serialVersionUID = 1L; - - public InvalidFlashExtensionException(String[] allowedExtension, String extension, String filename) - { - super(allowedExtension, extension, filename); - } - } - - public static class InvalidMediaExtensionException extends InvalidExtensionException - { - private static final long serialVersionUID = 1L; - - public InvalidMediaExtensionException(String[] allowedExtension, String extension, String filename) - { - super(allowedExtension, extension, filename); - } - } - - public static class InvalidVideoExtensionException extends InvalidExtensionException - { - private static final long serialVersionUID = 1L; - - public InvalidVideoExtensionException(String[] allowedExtension, String extension, String filename) - { - super(allowedExtension, extension, filename); - } - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java deleted file mode 100644 index a567b408..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.ruoyi.common.exception.job; - -/** - * 计划策略异常 - * - * @author ruoyi - */ -public class TaskException extends Exception -{ - private static final long serialVersionUID = 1L; - - private Code code; - - public TaskException(String msg, Code code) - { - this(msg, code, null); - } - - public TaskException(String msg, Code code, Exception nestedEx) - { - super(msg, nestedEx); - this.code = code; - } - - public Code getCode() - { - return code; - } - - public enum Code - { - TASK_EXISTS, NO_TASK_EXISTS, TASK_ALREADY_STARTED, UNKNOWN, CONFIG_ERROR, TASK_NODE_NOT_AVAILABLE - } -} \ No newline at end of file diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java deleted file mode 100644 index 389dbc75..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.ruoyi.common.exception.user; - -/** - * 验证码错误异常类 - * - * @author ruoyi - */ -public class CaptchaException extends UserException -{ - private static final long serialVersionUID = 1L; - - public CaptchaException() - { - super("user.jcaptcha.error", null); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java deleted file mode 100644 index 85f94861..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.ruoyi.common.exception.user; - -/** - * 验证码失效异常类 - * - * @author ruoyi - */ -public class CaptchaExpireException extends UserException -{ - private static final long serialVersionUID = 1L; - - public CaptchaExpireException() - { - super("user.jcaptcha.expire", null); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/user/UserException.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/user/UserException.java deleted file mode 100644 index c292d70e..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/user/UserException.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.ruoyi.common.exception.user; - -import com.ruoyi.common.exception.base.BaseException; - -/** - * 用户信息异常类 - * - * @author ruoyi - */ -public class UserException extends BaseException -{ - private static final long serialVersionUID = 1L; - - public UserException(String code, Object[] args) - { - super("user", code, args, null); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java deleted file mode 100644 index a7f3e5ff..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.ruoyi.common.exception.user; - -/** - * 用户密码不正确或不符合规范异常类 - * - * @author ruoyi - */ -public class UserPasswordNotMatchException extends UserException -{ - private static final long serialVersionUID = 1L; - - public UserPasswordNotMatchException() - { - super("user.password.not.match", null); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java deleted file mode 100644 index a1bcfe2a..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.ruoyi.common.filter; - -import java.io.IOException; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import org.springframework.http.MediaType; -import com.ruoyi.common.utils.StringUtils; - -/** - * Repeatable 过滤器 - * - * @author ruoyi - */ -public class RepeatableFilter implements Filter -{ - @Override - public void init(FilterConfig filterConfig) throws ServletException - { - - } - - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) - throws IOException, ServletException - { - ServletRequest requestWrapper = null; - if (request instanceof HttpServletRequest - && StringUtils.startsWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE)) - { - requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response); - } - if (null == requestWrapper) - { - chain.doFilter(request, response); - } - else - { - chain.doFilter(requestWrapper, response); - } - } - - @Override - public void destroy() - { - - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java deleted file mode 100644 index 614c24ce..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.ruoyi.common.filter; - -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import javax.servlet.ReadListener; -import javax.servlet.ServletInputStream; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; -import com.ruoyi.common.utils.http.HttpHelper; - -/** - * 构建可重复读取inputStream的request - * - * @author ruoyi - */ -public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper -{ - private final byte[] body; - - public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException - { - super(request); - request.setCharacterEncoding("UTF-8"); - response.setCharacterEncoding("UTF-8"); - - body = HttpHelper.getBodyString(request).getBytes("UTF-8"); - } - - @Override - public BufferedReader getReader() throws IOException - { - return new BufferedReader(new InputStreamReader(getInputStream())); - } - - @Override - public ServletInputStream getInputStream() throws IOException - { - final ByteArrayInputStream bais = new ByteArrayInputStream(body); - return new ServletInputStream() - { - @Override - public int read() throws IOException - { - return bais.read(); - } - - @Override - public int available() throws IOException - { - return body.length; - } - - @Override - public boolean isFinished() - { - return false; - } - - @Override - public boolean isReady() - { - return false; - } - - @Override - public void setReadListener(ReadListener readListener) - { - - } - }; - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/filter/XssFilter.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/filter/XssFilter.java deleted file mode 100644 index 99323edf..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/filter/XssFilter.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.ruoyi.common.filter; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import com.ruoyi.common.utils.StringUtils; - -/** - * 防止XSS攻击的过滤器 - * - * @author ruoyi - */ -public class XssFilter implements Filter -{ - /** - * 排除链接 - */ - public List excludes = new ArrayList<>(); - - @Override - public void init(FilterConfig filterConfig) throws ServletException - { - String tempExcludes = filterConfig.getInitParameter("excludes"); - if (StringUtils.isNotEmpty(tempExcludes)) - { - String[] url = tempExcludes.split(","); - for (int i = 0; url != null && i < url.length; i++) - { - excludes.add(url[i]); - } - } - } - - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) - throws IOException, ServletException - { - HttpServletRequest req = (HttpServletRequest) request; - HttpServletResponse resp = (HttpServletResponse) response; - if (handleExcludeURL(req, resp)) - { - chain.doFilter(request, response); - return; - } - XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request); - chain.doFilter(xssRequest, response); - } - - private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response) - { - String url = request.getServletPath(); - String method = request.getMethod(); - // GET DELETE 不过滤 - if (method == null || method.matches("GET") || method.matches("DELETE")) - { - return true; - } - return StringUtils.matches(url, excludes); - } - - @Override - public void destroy() - { - - } -} \ No newline at end of file diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java deleted file mode 100644 index b1eeb65c..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.ruoyi.common.filter; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import javax.servlet.ReadListener; -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; -import org.apache.commons.io.IOUtils; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.html.EscapeUtil; - -/** - * XSS过滤处理 - * - * @author ruoyi - */ -public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper -{ - /** - * @param request - */ - public XssHttpServletRequestWrapper(HttpServletRequest request) - { - super(request); - } - - @Override - public String[] getParameterValues(String name) - { - String[] values = super.getParameterValues(name); - if (values != null) - { - int length = values.length; - String[] escapseValues = new String[length]; - for (int i = 0; i < length; i++) - { - // 防xss攻击和过滤前后空格 - escapseValues[i] = EscapeUtil.clean(values[i]).trim(); - } - return escapseValues; - } - return super.getParameterValues(name); - } - - @Override - public ServletInputStream getInputStream() throws IOException - { - // 非json类型,直接返回 - if (!isJsonRequest()) - { - return super.getInputStream(); - } - - // 为空,直接返回 - String json = IOUtils.toString(super.getInputStream(), "utf-8"); - if (StringUtils.isEmpty(json)) - { - return super.getInputStream(); - } - - // xss过滤 - json = EscapeUtil.clean(json).trim(); - byte[] jsonBytes = json.getBytes("utf-8"); - final ByteArrayInputStream bis = new ByteArrayInputStream(jsonBytes); - return new ServletInputStream() - { - @Override - public boolean isFinished() - { - return true; - } - - @Override - public boolean isReady() - { - return true; - } - - @Override - public int available() throws IOException - { - return jsonBytes.length; - } - - @Override - public void setReadListener(ReadListener readListener) - { - } - - @Override - public int read() throws IOException - { - return bis.read(); - } - }; - } - - /** - * 是否是Json请求 - * - * @param request - */ - public boolean isJsonRequest() - { - String header = super.getHeader(HttpHeaders.CONTENT_TYPE); - return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE); - } -} \ No newline at end of file diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/Arith.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/Arith.java deleted file mode 100644 index b6326c2b..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/Arith.java +++ /dev/null @@ -1,114 +0,0 @@ -package com.ruoyi.common.utils; - -import java.math.BigDecimal; -import java.math.RoundingMode; - -/** - * 精确的浮点数运算 - * - * @author ruoyi - */ -public class Arith -{ - - /** 默认除法运算精度 */ - private static final int DEF_DIV_SCALE = 10; - - /** 这个类不能实例化 */ - private Arith() - { - } - - /** - * 提供精确的加法运算。 - * @param v1 被加数 - * @param v2 加数 - * @return 两个参数的和 - */ - public static double add(double v1, double v2) - { - BigDecimal b1 = new BigDecimal(Double.toString(v1)); - BigDecimal b2 = new BigDecimal(Double.toString(v2)); - return b1.add(b2).doubleValue(); - } - - /** - * 提供精确的减法运算。 - * @param v1 被减数 - * @param v2 减数 - * @return 两个参数的差 - */ - public static double sub(double v1, double v2) - { - BigDecimal b1 = new BigDecimal(Double.toString(v1)); - BigDecimal b2 = new BigDecimal(Double.toString(v2)); - return b1.subtract(b2).doubleValue(); - } - - /** - * 提供精确的乘法运算。 - * @param v1 被乘数 - * @param v2 乘数 - * @return 两个参数的积 - */ - public static double mul(double v1, double v2) - { - BigDecimal b1 = new BigDecimal(Double.toString(v1)); - BigDecimal b2 = new BigDecimal(Double.toString(v2)); - return b1.multiply(b2).doubleValue(); - } - - /** - * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 - * 小数点以后10位,以后的数字四舍五入。 - * @param v1 被除数 - * @param v2 除数 - * @return 两个参数的商 - */ - public static double div(double v1, double v2) - { - return div(v1, v2, DEF_DIV_SCALE); - } - - /** - * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 - * 定精度,以后的数字四舍五入。 - * @param v1 被除数 - * @param v2 除数 - * @param scale 表示表示需要精确到小数点以后几位。 - * @return 两个参数的商 - */ - public static double div(double v1, double v2, int scale) - { - if (scale < 0) - { - throw new IllegalArgumentException( - "The scale must be a positive integer or zero"); - } - BigDecimal b1 = new BigDecimal(Double.toString(v1)); - BigDecimal b2 = new BigDecimal(Double.toString(v2)); - if (b1.compareTo(BigDecimal.ZERO) == 0) - { - return BigDecimal.ZERO.doubleValue(); - } - return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue(); - } - - /** - * 提供精确的小数位四舍五入处理。 - * @param v 需要四舍五入的数字 - * @param scale 小数点后保留几位 - * @return 四舍五入后的结果 - */ - public static double round(double v, int scale) - { - if (scale < 0) - { - throw new IllegalArgumentException( - "The scale must be a positive integer or zero"); - } - BigDecimal b = new BigDecimal(Double.toString(v)); - BigDecimal one = BigDecimal.ONE; - return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue(); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/DateUtils.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/DateUtils.java deleted file mode 100644 index 536cb3cf..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/DateUtils.java +++ /dev/null @@ -1,155 +0,0 @@ -package com.ruoyi.common.utils; - -import java.lang.management.ManagementFactory; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import org.apache.commons.lang3.time.DateFormatUtils; - -/** - * 时间工具类 - * - * @author ruoyi - */ -public class DateUtils extends org.apache.commons.lang3.time.DateUtils -{ - public static String YYYY = "yyyy"; - - public static String YYYY_MM = "yyyy-MM"; - - public static String YYYY_MM_DD = "yyyy-MM-dd"; - - public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss"; - - public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; - - private static String[] parsePatterns = { - "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", - "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", - "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"}; - - /** - * 获取当前Date型日期 - * - * @return Date() 当前日期 - */ - public static Date getNowDate() - { - return new Date(); - } - - /** - * 获取当前日期, 默认格式为yyyy-MM-dd - * - * @return String - */ - public static String getDate() - { - return dateTimeNow(YYYY_MM_DD); - } - - public static final String getTime() - { - return dateTimeNow(YYYY_MM_DD_HH_MM_SS); - } - - public static final String dateTimeNow() - { - return dateTimeNow(YYYYMMDDHHMMSS); - } - - public static final String dateTimeNow(final String format) - { - return parseDateToStr(format, new Date()); - } - - public static final String dateTime(final Date date) - { - return parseDateToStr(YYYY_MM_DD, date); - } - - public static final String parseDateToStr(final String format, final Date date) - { - return new SimpleDateFormat(format).format(date); - } - - public static final Date dateTime(final String format, final String ts) - { - try - { - return new SimpleDateFormat(format).parse(ts); - } - catch (ParseException e) - { - throw new RuntimeException(e); - } - } - - /** - * 日期路径 即年/月/日 如2018/08/08 - */ - public static final String datePath() - { - Date now = new Date(); - return DateFormatUtils.format(now, "yyyy/MM/dd"); - } - - /** - * 日期路径 即年/月/日 如20180808 - */ - public static final String dateTime() - { - Date now = new Date(); - return DateFormatUtils.format(now, "yyyyMMdd"); - } - - /** - * 日期型字符串转化为日期 格式 - */ - public static Date parseDate(Object str) - { - if (str == null) - { - return null; - } - try - { - return parseDate(str.toString(), parsePatterns); - } - catch (ParseException e) - { - return null; - } - } - - /** - * 获取服务器启动时间 - */ - public static Date getServerStartDate() - { - long time = ManagementFactory.getRuntimeMXBean().getStartTime(); - return new Date(time); - } - - /** - * 计算两个时间差 - */ - public static String getDatePoor(Date endDate, Date nowDate) - { - long nd = 1000 * 24 * 60 * 60; - long nh = 1000 * 60 * 60; - long nm = 1000 * 60; - // long ns = 1000; - // 获得两个时间的毫秒时间差异 - long diff = endDate.getTime() - nowDate.getTime(); - // 计算差多少天 - long day = diff / nd; - // 计算差多少小时 - long hour = diff % nd / nh; - // 计算差多少分钟 - long min = diff % nd % nh / nm; - // 计算差多少秒//输出结果 - // long sec = diff % nd % nh % nm / ns; - return day + "天" + hour + "小时" + min + "分钟"; - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/DictUtils.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/DictUtils.java deleted file mode 100644 index fd9946d6..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/DictUtils.java +++ /dev/null @@ -1,183 +0,0 @@ -package com.ruoyi.common.utils; - -import java.util.Collection; -import java.util.List; -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.core.domain.entity.SysDictData; -import com.ruoyi.common.core.redis.RedisCache; -import com.ruoyi.common.utils.spring.SpringUtils; - -/** - * 字典工具类 - * - * @author ruoyi - */ -public class DictUtils -{ - /** - * 分隔符 - */ - public static final String SEPARATOR = ","; - - /** - * 设置字典缓存 - * - * @param key 参数键 - * @param dictDatas 字典数据列表 - */ - public static void setDictCache(String key, List dictDatas) - { - SpringUtils.getBean(RedisCache.class).setCacheObject(getCacheKey(key), dictDatas); - } - - /** - * 获取字典缓存 - * - * @param key 参数键 - * @return dictDatas 字典数据列表 - */ - public static List getDictCache(String key) - { - Object cacheObj = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key)); - if (StringUtils.isNotNull(cacheObj)) - { - List dictDatas = StringUtils.cast(cacheObj); - return dictDatas; - } - return null; - } - - /** - * 根据字典类型和字典值获取字典标签 - * - * @param dictType 字典类型 - * @param dictValue 字典值 - * @return 字典标签 - */ - public static String getDictLabel(String dictType, String dictValue) - { - return getDictLabel(dictType, dictValue, SEPARATOR); - } - - /** - * 根据字典类型和字典标签获取字典值 - * - * @param dictType 字典类型 - * @param dictLabel 字典标签 - * @return 字典值 - */ - public static String getDictValue(String dictType, String dictLabel) - { - return getDictValue(dictType, dictLabel, SEPARATOR); - } - - /** - * 根据字典类型和字典值获取字典标签 - * - * @param dictType 字典类型 - * @param dictValue 字典值 - * @param separator 分隔符 - * @return 字典标签 - */ - public static String getDictLabel(String dictType, String dictValue, String separator) - { - StringBuilder propertyString = new StringBuilder(); - List datas = getDictCache(dictType); - - if (StringUtils.containsAny(separator, dictValue) && StringUtils.isNotEmpty(datas)) - { - for (SysDictData dict : datas) - { - for (String value : dictValue.split(separator)) - { - if (value.equals(dict.getDictValue())) - { - propertyString.append(dict.getDictLabel() + separator); - break; - } - } - } - } - else - { - for (SysDictData dict : datas) - { - if (dictValue.equals(dict.getDictValue())) - { - return dict.getDictLabel(); - } - } - } - return StringUtils.stripEnd(propertyString.toString(), separator); - } - - /** - * 根据字典类型和字典标签获取字典值 - * - * @param dictType 字典类型 - * @param dictLabel 字典标签 - * @param separator 分隔符 - * @return 字典值 - */ - public static String getDictValue(String dictType, String dictLabel, String separator) - { - StringBuilder propertyString = new StringBuilder(); - List datas = getDictCache(dictType); - - if (StringUtils.containsAny(separator, dictLabel) && StringUtils.isNotEmpty(datas)) - { - for (SysDictData dict : datas) - { - for (String label : dictLabel.split(separator)) - { - if (label.equals(dict.getDictLabel())) - { - propertyString.append(dict.getDictValue() + separator); - break; - } - } - } - } - else - { - for (SysDictData dict : datas) - { - if (dictLabel.equals(dict.getDictLabel())) - { - return dict.getDictValue(); - } - } - } - return StringUtils.stripEnd(propertyString.toString(), separator); - } - - /** - * 删除指定字典缓存 - * - * @param key 字典键 - */ - public static void removeDictCache(String key) - { - SpringUtils.getBean(RedisCache.class).deleteObject(getCacheKey(key)); - } - - /** - * 清空字典缓存 - */ - public static void clearDictCache() - { - Collection keys = SpringUtils.getBean(RedisCache.class).keys(Constants.SYS_DICT_KEY + "*"); - SpringUtils.getBean(RedisCache.class).deleteObject(keys); - } - - /** - * 设置cache key - * - * @param configKey 参数键 - * @return 缓存键key - */ - public static String getCacheKey(String configKey) - { - return Constants.SYS_DICT_KEY + configKey; - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java deleted file mode 100644 index ae81a697..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.ruoyi.common.utils; - -import java.io.PrintWriter; -import java.io.StringWriter; -import org.apache.commons.lang3.exception.ExceptionUtils; - -/** - * 错误信息处理类。 - * - * @author ruoyi - */ -public class ExceptionUtil -{ - /** - * 获取exception的详细错误信息。 - */ - public static String getExceptionMessage(Throwable e) - { - StringWriter sw = new StringWriter(); - e.printStackTrace(new PrintWriter(sw, true)); - String str = sw.toString(); - return str; - } - - public static String getRootErrorMessage(Exception e) - { - Throwable root = ExceptionUtils.getRootCause(e); - root = (root == null ? e : root); - if (root == null) - { - return ""; - } - String msg = root.getMessage(); - if (msg == null) - { - return "null"; - } - return StringUtils.defaultString(msg); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/LogUtils.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/LogUtils.java deleted file mode 100644 index 0de30c6b..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/LogUtils.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.ruoyi.common.utils; - -/** - * 处理并记录日志文件 - * - * @author ruoyi - */ -public class LogUtils -{ - public static String getBlock(Object msg) - { - if (msg == null) - { - msg = ""; - } - return "[" + msg.toString() + "]"; - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java deleted file mode 100644 index 7dac75a3..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.ruoyi.common.utils; - -import org.springframework.context.MessageSource; -import org.springframework.context.i18n.LocaleContextHolder; -import com.ruoyi.common.utils.spring.SpringUtils; - -/** - * 获取i18n资源文件 - * - * @author ruoyi - */ -public class MessageUtils -{ - /** - * 根据消息键和参数 获取消息 委托给spring messageSource - * - * @param code 消息键 - * @param args 参数 - * @return 获取国际化翻译值 - */ - public static String message(String code, Object... args) - { - MessageSource messageSource = SpringUtils.getBean(MessageSource.class); - return messageSource.getMessage(code, args, LocaleContextHolder.getLocale()); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java deleted file mode 100644 index a6f3d538..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.ruoyi.common.utils; - -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import com.ruoyi.common.constant.HttpStatus; -import com.ruoyi.common.core.domain.model.LoginUser; -import com.ruoyi.common.exception.ServiceException; - -/** - * 安全服务工具类 - * - * @author ruoyi - */ -public class SecurityUtils -{ - /** - * 用户ID - **/ - public static Long getUserId() - { - try - { - return getLoginUser().getUserId(); - } - catch (Exception e) - { - throw new ServiceException("获取用户ID异常", HttpStatus.UNAUTHORIZED); - } - } - - /** - * 获取部门ID - **/ - public static Long getDeptId() - { - try - { - return getLoginUser().getDeptId(); - } - catch (Exception e) - { - throw new ServiceException("获取部门ID异常", HttpStatus.UNAUTHORIZED); - } - } - - /** - * 获取用户账户 - **/ - public static String getUsername() - { - try - { - return getLoginUser().getUsername(); - } - catch (Exception e) - { - throw new ServiceException("获取用户账户异常", HttpStatus.UNAUTHORIZED); - } - } - - /** - * 获取用户 - **/ - public static LoginUser getLoginUser() - { - try - { - return (LoginUser) getAuthentication().getPrincipal(); - } - catch (Exception e) - { - throw new ServiceException("获取用户信息异常", HttpStatus.UNAUTHORIZED); - } - } - - /** - * 获取Authentication - */ - public static Authentication getAuthentication() - { - return SecurityContextHolder.getContext().getAuthentication(); - } - - /** - * 生成BCryptPasswordEncoder密码 - * - * @param password 密码 - * @return 加密字符串 - */ - public static String encryptPassword(String password) - { - BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); - return passwordEncoder.encode(password); - } - - /** - * 判断密码是否相同 - * - * @param rawPassword 真实密码 - * @param encodedPassword 加密后字符 - * @return 结果 - */ - public static boolean matchesPassword(String rawPassword, String encodedPassword) - { - BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); - return passwordEncoder.matches(rawPassword, encodedPassword); - } - - /** - * 是否为管理员 - * - * @param userId 用户ID - * @return 结果 - */ - public static boolean isAdmin(Long userId) - { - return userId != null && 1L == userId; - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java deleted file mode 100644 index 03576c51..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java +++ /dev/null @@ -1,152 +0,0 @@ -package com.ruoyi.common.utils; - -import java.io.IOException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import org.springframework.web.context.request.RequestAttributes; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; -import com.ruoyi.common.core.text.Convert; - -/** - * 客户端工具类 - * - * @author ruoyi - */ -public class ServletUtils -{ - /** - * 获取String参数 - */ - public static String getParameter(String name) - { - return getRequest().getParameter(name); - } - - /** - * 获取String参数 - */ - public static String getParameter(String name, String defaultValue) - { - return Convert.toStr(getRequest().getParameter(name), defaultValue); - } - - /** - * 获取Integer参数 - */ - public static Integer getParameterToInt(String name) - { - return Convert.toInt(getRequest().getParameter(name)); - } - - /** - * 获取Integer参数 - */ - public static Integer getParameterToInt(String name, Integer defaultValue) - { - return Convert.toInt(getRequest().getParameter(name), defaultValue); - } - - /** - * 获取Boolean参数 - */ - public static Boolean getParameterToBool(String name) - { - return Convert.toBool(getRequest().getParameter(name)); - } - - /** - * 获取Boolean参数 - */ - public static Boolean getParameterToBool(String name, Boolean defaultValue) - { - return Convert.toBool(getRequest().getParameter(name), defaultValue); - } - - /** - * 获取request - */ - public static HttpServletRequest getRequest() - { - return getRequestAttributes().getRequest(); - } - - /** - * 获取response - */ - public static HttpServletResponse getResponse() - { - return getRequestAttributes().getResponse(); - } - - /** - * 获取session - */ - public static HttpSession getSession() - { - return getRequest().getSession(); - } - - public static ServletRequestAttributes getRequestAttributes() - { - RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); - return (ServletRequestAttributes) attributes; - } - - /** - * 将字符串渲染到客户端 - * - * @param response 渲染对象 - * @param string 待渲染的字符串 - * @return null - */ - public static String renderString(HttpServletResponse response, String string) - { - try - { - response.setStatus(200); - response.setContentType("application/json"); - response.setCharacterEncoding("utf-8"); - response.getWriter().print(string); - } - catch (IOException e) - { - e.printStackTrace(); - } - return null; - } - - /** - * 是否是Ajax异步请求 - * - * @param request - */ - public static boolean isAjaxRequest(HttpServletRequest request) - { - String accept = request.getHeader("accept"); - if (accept != null && accept.indexOf("application/json") != -1) - { - return true; - } - - String xRequestedWith = request.getHeader("X-Requested-With"); - if (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") != -1) - { - return true; - } - - String uri = request.getRequestURI(); - if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml")) - { - return true; - } - - String ajax = request.getParameter("__ajax"); - if (StringUtils.inStringIgnoreCase(ajax, "json", "xml")) - { - return true; - } - return false; - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/StringUtils.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/StringUtils.java deleted file mode 100644 index 4ca2bfcf..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/StringUtils.java +++ /dev/null @@ -1,534 +0,0 @@ -package com.ruoyi.common.utils; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import org.springframework.util.AntPathMatcher; -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.core.text.StrFormatter; - -/** - * 字符串工具类 - * - * @author ruoyi - */ -public class StringUtils extends org.apache.commons.lang3.StringUtils -{ - /** 空字符串 */ - private static final String NULLSTR = ""; - - /** 下划线 */ - private static final char SEPARATOR = '_'; - - /** - * 获取参数不为空值 - * - * @param value defaultValue 要判断的value - * @return value 返回值 - */ - public static T nvl(T value, T defaultValue) - { - return value != null ? value : defaultValue; - } - - /** - * * 判断一个Collection是否为空, 包含List,Set,Queue - * - * @param coll 要判断的Collection - * @return true:为空 false:非空 - */ - public static boolean isEmpty(Collection coll) - { - return isNull(coll) || coll.isEmpty(); - } - - /** - * * 判断一个Collection是否非空,包含List,Set,Queue - * - * @param coll 要判断的Collection - * @return true:非空 false:空 - */ - public static boolean isNotEmpty(Collection coll) - { - return !isEmpty(coll); - } - - /** - * * 判断一个对象数组是否为空 - * - * @param objects 要判断的对象数组 - ** @return true:为空 false:非空 - */ - public static boolean isEmpty(Object[] objects) - { - return isNull(objects) || (objects.length == 0); - } - - /** - * * 判断一个对象数组是否非空 - * - * @param objects 要判断的对象数组 - * @return true:非空 false:空 - */ - public static boolean isNotEmpty(Object[] objects) - { - return !isEmpty(objects); - } - - /** - * * 判断一个Map是否为空 - * - * @param map 要判断的Map - * @return true:为空 false:非空 - */ - public static boolean isEmpty(Map map) - { - return isNull(map) || map.isEmpty(); - } - - /** - * * 判断一个Map是否为空 - * - * @param map 要判断的Map - * @return true:非空 false:空 - */ - public static boolean isNotEmpty(Map map) - { - return !isEmpty(map); - } - - /** - * * 判断一个字符串是否为空串 - * - * @param str String - * @return true:为空 false:非空 - */ - public static boolean isEmpty(String str) - { - return isNull(str) || NULLSTR.equals(str.trim()); - } - - /** - * * 判断一个字符串是否为非空串 - * - * @param str String - * @return true:非空串 false:空串 - */ - public static boolean isNotEmpty(String str) - { - return !isEmpty(str); - } - - /** - * * 判断一个对象是否为空 - * - * @param object Object - * @return true:为空 false:非空 - */ - public static boolean isNull(Object object) - { - return object == null; - } - - /** - * * 判断一个对象是否非空 - * - * @param object Object - * @return true:非空 false:空 - */ - public static boolean isNotNull(Object object) - { - return !isNull(object); - } - - /** - * * 判断一个对象是否是数组类型(Java基本型别的数组) - * - * @param object 对象 - * @return true:是数组 false:不是数组 - */ - public static boolean isArray(Object object) - { - return isNotNull(object) && object.getClass().isArray(); - } - - /** - * 去空格 - */ - public static String trim(String str) - { - return (str == null ? "" : str.trim()); - } - - /** - * 截取字符串 - * - * @param str 字符串 - * @param start 开始 - * @return 结果 - */ - public static String substring(final String str, int start) - { - if (str == null) - { - return NULLSTR; - } - - if (start < 0) - { - start = str.length() + start; - } - - if (start < 0) - { - start = 0; - } - if (start > str.length()) - { - return NULLSTR; - } - - return str.substring(start); - } - - /** - * 截取字符串 - * - * @param str 字符串 - * @param start 开始 - * @param end 结束 - * @return 结果 - */ - public static String substring(final String str, int start, int end) - { - if (str == null) - { - return NULLSTR; - } - - if (end < 0) - { - end = str.length() + end; - } - if (start < 0) - { - start = str.length() + start; - } - - if (end > str.length()) - { - end = str.length(); - } - - if (start > end) - { - return NULLSTR; - } - - if (start < 0) - { - start = 0; - } - if (end < 0) - { - end = 0; - } - - return str.substring(start, end); - } - - /** - * 格式化文本, {} 表示占位符
- * 此方法只是简单将占位符 {} 按照顺序替换为参数
- * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
- * 例:
- * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
- * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
- * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
- * - * @param template 文本模板,被替换的部分用 {} 表示 - * @param params 参数值 - * @return 格式化后的文本 - */ - public static String format(String template, Object... params) - { - if (isEmpty(params) || isEmpty(template)) - { - return template; - } - return StrFormatter.format(template, params); - } - - /** - * 是否为http(s)://开头 - * - * @param link 链接 - * @return 结果 - */ - public static boolean ishttp(String link) - { - return StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS); - } - - /** - * 字符串转set - * - * @param str 字符串 - * @param sep 分隔符 - * @return set集合 - */ - public static final Set str2Set(String str, String sep) - { - return new HashSet(str2List(str, sep, true, false)); - } - - /** - * 字符串转list - * - * @param str 字符串 - * @param sep 分隔符 - * @param filterBlank 过滤纯空白 - * @param trim 去掉首尾空白 - * @return list集合 - */ - public static final List str2List(String str, String sep, boolean filterBlank, boolean trim) - { - List list = new ArrayList(); - if (StringUtils.isEmpty(str)) - { - return list; - } - - // 过滤空白字符串 - if (filterBlank && StringUtils.isBlank(str)) - { - return list; - } - String[] split = str.split(sep); - for (String string : split) - { - if (filterBlank && StringUtils.isBlank(string)) - { - continue; - } - if (trim) - { - string = string.trim(); - } - list.add(string); - } - - return list; - } - - /** - * 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写 - * - * @param cs 指定字符串 - * @param searchCharSequences 需要检查的字符串数组 - * @return 是否包含任意一个字符串 - */ - public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences) - { - if (isEmpty(cs) || isEmpty(searchCharSequences)) - { - return false; - } - for (CharSequence testStr : searchCharSequences) - { - if (containsIgnoreCase(cs, testStr)) - { - return true; - } - } - return false; - } - - /** - * 驼峰转下划线命名 - */ - public static String toUnderScoreCase(String str) - { - if (str == null) - { - return null; - } - StringBuilder sb = new StringBuilder(); - // 前置字符是否大写 - boolean preCharIsUpperCase = true; - // 当前字符是否大写 - boolean curreCharIsUpperCase = true; - // 下一字符是否大写 - boolean nexteCharIsUpperCase = true; - for (int i = 0; i < str.length(); i++) - { - char c = str.charAt(i); - if (i > 0) - { - preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1)); - } - else - { - preCharIsUpperCase = false; - } - - curreCharIsUpperCase = Character.isUpperCase(c); - - if (i < (str.length() - 1)) - { - nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1)); - } - - if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) - { - sb.append(SEPARATOR); - } - else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) - { - sb.append(SEPARATOR); - } - sb.append(Character.toLowerCase(c)); - } - - return sb.toString(); - } - - /** - * 是否包含字符串 - * - * @param str 验证字符串 - * @param strs 字符串组 - * @return 包含返回true - */ - public static boolean inStringIgnoreCase(String str, String... strs) - { - if (str != null && strs != null) - { - for (String s : strs) - { - if (str.equalsIgnoreCase(trim(s))) - { - return true; - } - } - } - return false; - } - - /** - * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld - * - * @param name 转换前的下划线大写方式命名的字符串 - * @return 转换后的驼峰式命名的字符串 - */ - public static String convertToCamelCase(String name) - { - StringBuilder result = new StringBuilder(); - // 快速检查 - if (name == null || name.isEmpty()) - { - // 没必要转换 - return ""; - } - else if (!name.contains("_")) - { - // 不含下划线,仅将首字母大写 - return name.substring(0, 1).toUpperCase() + name.substring(1); - } - // 用下划线将原始字符串分割 - String[] camels = name.split("_"); - for (String camel : camels) - { - // 跳过原始字符串中开头、结尾的下换线或双重下划线 - if (camel.isEmpty()) - { - continue; - } - // 首字母大写 - result.append(camel.substring(0, 1).toUpperCase()); - result.append(camel.substring(1).toLowerCase()); - } - return result.toString(); - } - - /** - * 驼峰式命名法 例如:user_name->userName - */ - public static String toCamelCase(String s) - { - if (s == null) - { - return null; - } - s = s.toLowerCase(); - StringBuilder sb = new StringBuilder(s.length()); - boolean upperCase = false; - for (int i = 0; i < s.length(); i++) - { - char c = s.charAt(i); - - if (c == SEPARATOR) - { - upperCase = true; - } - else if (upperCase) - { - sb.append(Character.toUpperCase(c)); - upperCase = false; - } - else - { - sb.append(c); - } - } - return sb.toString(); - } - - /** - * 查找指定字符串是否匹配指定字符串列表中的任意一个字符串 - * - * @param str 指定字符串 - * @param strs 需要检查的字符串数组 - * @return 是否匹配 - */ - public static boolean matches(String str, List strs) - { - if (isEmpty(str) || isEmpty(strs)) - { - return false; - } - for (String pattern : strs) - { - if (isMatch(pattern, str)) - { - return true; - } - } - return false; - } - - /** - * 判断url是否与规则配置: - * ? 表示单个字符; - * * 表示一层路径内的任意字符串,不可跨层级; - * ** 表示任意层路径; - * - * @param pattern 匹配规则 - * @param url 需要匹配的url - * @return - */ - public static boolean isMatch(String pattern, String url) - { - AntPathMatcher matcher = new AntPathMatcher(); - return matcher.match(pattern, url); - } - - @SuppressWarnings("unchecked") - public static T cast(Object obj) - { - return (T) obj; - } -} \ No newline at end of file diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/Threads.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/Threads.java deleted file mode 100644 index 71fe6d52..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/Threads.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.ruoyi.common.utils; - -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * 线程相关工具类. - * - * @author ruoyi - */ -public class Threads -{ - private static final Logger logger = LoggerFactory.getLogger(Threads.class); - - /** - * sleep等待,单位为毫秒 - */ - public static void sleep(long milliseconds) - { - try - { - Thread.sleep(milliseconds); - } - catch (InterruptedException e) - { - return; - } - } - - /** - * 停止线程池 - * 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务. - * 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数. - * 如果仍然超時,則強制退出. - * 另对在shutdown时线程本身被调用中断做了处理. - */ - public static void shutdownAndAwaitTermination(ExecutorService pool) - { - if (pool != null && !pool.isShutdown()) - { - pool.shutdown(); - try - { - if (!pool.awaitTermination(120, TimeUnit.SECONDS)) - { - pool.shutdownNow(); - if (!pool.awaitTermination(120, TimeUnit.SECONDS)) - { - logger.info("Pool did not terminate"); - } - } - } - catch (InterruptedException ie) - { - pool.shutdownNow(); - Thread.currentThread().interrupt(); - } - } - } - - /** - * 打印线程异常信息 - */ - public static void printException(Runnable r, Throwable t) - { - if (t == null && r instanceof Future) - { - try - { - Future future = (Future) r; - if (future.isDone()) - { - future.get(); - } - } - catch (CancellationException ce) - { - t = ce; - } - catch (ExecutionException ee) - { - t = ee.getCause(); - } - catch (InterruptedException ie) - { - Thread.currentThread().interrupt(); - } - } - if (t != null) - { - logger.error(t.getMessage(), t); - } - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/VerifyCodeUtils.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/VerifyCodeUtils.java deleted file mode 100644 index 5fdf3a9d..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/VerifyCodeUtils.java +++ /dev/null @@ -1,228 +0,0 @@ -package com.ruoyi.common.utils; - -import java.awt.Color; -import java.awt.Font; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.geom.AffineTransform; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.io.OutputStream; -import java.security.SecureRandom; -import java.util.Arrays; -import java.util.Random; -import javax.imageio.ImageIO; - -/** - * 验证码工具类 - * - * @author ruoyi - */ -public class VerifyCodeUtils -{ - // 使用到Algerian字体,系统里没有的话需要安装字体,字体只显示大写,去掉了1,0,i,o几个容易混淆的字符 - public static final String VERIFY_CODES = "123456789ABCDEFGHJKLMNPQRSTUVWXYZ"; - - private static Random random = new SecureRandom(); - - /** - * 使用系统默认字符源生成验证码 - * - * @param verifySize 验证码长度 - * @return - */ - public static String generateVerifyCode(int verifySize) - { - return generateVerifyCode(verifySize, VERIFY_CODES); - } - - /** - * 使用指定源生成验证码 - * - * @param verifySize 验证码长度 - * @param sources 验证码字符源 - * @return - */ - public static String generateVerifyCode(int verifySize, String sources) - { - if (sources == null || sources.length() == 0) - { - sources = VERIFY_CODES; - } - int codesLen = sources.length(); - Random rand = new Random(System.currentTimeMillis()); - StringBuilder verifyCode = new StringBuilder(verifySize); - for (int i = 0; i < verifySize; i++) - { - verifyCode.append(sources.charAt(rand.nextInt(codesLen - 1))); - } - return verifyCode.toString(); - } - - /** - * 输出指定验证码图片流 - * - * @param w - * @param h - * @param os - * @param code - * @throws IOException - */ - public static void outputImage(int w, int h, OutputStream os, String code) throws IOException - { - int verifySize = code.length(); - BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); - Random rand = new Random(); - Graphics2D g2 = image.createGraphics(); - g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - Color[] colors = new Color[5]; - Color[] colorSpaces = new Color[] { Color.WHITE, Color.CYAN, Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, - Color.ORANGE, Color.PINK, Color.YELLOW }; - float[] fractions = new float[colors.length]; - for (int i = 0; i < colors.length; i++) - { - colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)]; - fractions[i] = rand.nextFloat(); - } - Arrays.sort(fractions); - - g2.setColor(Color.GRAY);// 设置边框色 - g2.fillRect(0, 0, w, h); - - Color c = getRandColor(200, 250); - g2.setColor(c);// 设置背景色 - g2.fillRect(0, 2, w, h - 4); - - // 绘制干扰线 - Random random = new Random(); - g2.setColor(getRandColor(160, 200));// 设置线条的颜色 - for (int i = 0; i < 20; i++) - { - int x = random.nextInt(w - 1); - int y = random.nextInt(h - 1); - int xl = random.nextInt(6) + 1; - int yl = random.nextInt(12) + 1; - g2.drawLine(x, y, x + xl + 40, y + yl + 20); - } - - // 添加噪点 - float yawpRate = 0.05f;// 噪声率 - int area = (int) (yawpRate * w * h); - for (int i = 0; i < area; i++) - { - int x = random.nextInt(w); - int y = random.nextInt(h); - int rgb = getRandomIntColor(); - image.setRGB(x, y, rgb); - } - - shear(g2, w, h, c);// 使图片扭曲 - - g2.setColor(getRandColor(100, 160)); - int fontSize = h - 4; - Font font = new Font("Algerian", Font.ITALIC, fontSize); - g2.setFont(font); - char[] chars = code.toCharArray(); - for (int i = 0; i < verifySize; i++) - { - AffineTransform affine = new AffineTransform(); - affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), - (w / verifySize) * i + fontSize / 2, h / 2); - g2.setTransform(affine); - g2.drawChars(chars, i, 1, ((w - 10) / verifySize) * i + 5, h / 2 + fontSize / 2 - 10); - } - - g2.dispose(); - ImageIO.write(image, "jpg", os); - } - - private static Color getRandColor(int fc, int bc) - { - if (fc > 255) { - fc = 255; - } - if (bc > 255) { - bc = 255; - } - int r = fc + random.nextInt(bc - fc); - int g = fc + random.nextInt(bc - fc); - int b = fc + random.nextInt(bc - fc); - return new Color(r, g, b); - } - - private static int getRandomIntColor() - { - int[] rgb = getRandomRgb(); - int color = 0; - for (int c : rgb) - { - color = color << 8; - color = color | c; - } - return color; - } - - private static int[] getRandomRgb() - { - int[] rgb = new int[3]; - for (int i = 0; i < 3; i++) - { - rgb[i] = random.nextInt(255); - } - return rgb; - } - - private static void shear(Graphics g, int w1, int h1, Color color) - { - shearX(g, w1, h1, color); - shearY(g, w1, h1, color); - } - - private static void shearX(Graphics g, int w1, int h1, Color color) - { - - int period = random.nextInt(2); - - boolean borderGap = true; - int frames = 1; - int phase = random.nextInt(2); - - for (int i = 0; i < h1; i++) - { - double d = (double) (period >> 1) - * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames); - g.copyArea(0, i, w1, 1, (int) d, 0); - if (borderGap) - { - g.setColor(color); - g.drawLine((int) d, i, 0, i); - g.drawLine((int) d + w1, i, w1, i); - } - } - - } - - private static void shearY(Graphics g, int w1, int h1, Color color) - { - - int period = random.nextInt(40) + 10; // 50; - - boolean borderGap = true; - int frames = 20; - int phase = 7; - for (int i = 0; i < w1; i++) - { - double d = (double) (period >> 1) - * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames); - g.copyArea(i, 0, 1, h1, 0, (int) d); - if (borderGap) - { - g.setColor(color); - g.drawLine(i, (int) d, i, 0); - g.drawLine(i, (int) d + h1, i, h1); - } - - } - } -} \ No newline at end of file diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java deleted file mode 100644 index 4463662d..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.ruoyi.common.utils.bean; - -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Bean 工具类 - * - * @author ruoyi - */ -public class BeanUtils extends org.springframework.beans.BeanUtils -{ - /** Bean方法名中属性名开始的下标 */ - private static final int BEAN_METHOD_PROP_INDEX = 3; - - /** * 匹配getter方法的正则表达式 */ - private static final Pattern GET_PATTERN = Pattern.compile("get(\\p{javaUpperCase}\\w*)"); - - /** * 匹配setter方法的正则表达式 */ - private static final Pattern SET_PATTERN = Pattern.compile("set(\\p{javaUpperCase}\\w*)"); - - /** - * Bean属性复制工具方法。 - * - * @param dest 目标对象 - * @param src 源对象 - */ - public static void copyBeanProp(Object dest, Object src) - { - try - { - copyProperties(src, dest); - } - catch (Exception e) - { - e.printStackTrace(); - } - } - - /** - * 获取对象的setter方法。 - * - * @param obj 对象 - * @return 对象的setter方法列表 - */ - public static List getSetterMethods(Object obj) - { - // setter方法列表 - List setterMethods = new ArrayList(); - - // 获取所有方法 - Method[] methods = obj.getClass().getMethods(); - - // 查找setter方法 - - for (Method method : methods) - { - Matcher m = SET_PATTERN.matcher(method.getName()); - if (m.matches() && (method.getParameterTypes().length == 1)) - { - setterMethods.add(method); - } - } - // 返回setter方法列表 - return setterMethods; - } - - /** - * 获取对象的getter方法。 - * - * @param obj 对象 - * @return 对象的getter方法列表 - */ - - public static List getGetterMethods(Object obj) - { - // getter方法列表 - List getterMethods = new ArrayList(); - // 获取所有方法 - Method[] methods = obj.getClass().getMethods(); - // 查找getter方法 - for (Method method : methods) - { - Matcher m = GET_PATTERN.matcher(method.getName()); - if (m.matches() && (method.getParameterTypes().length == 0)) - { - getterMethods.add(method); - } - } - // 返回getter方法列表 - return getterMethods; - } - - /** - * 检查Bean方法名中的属性名是否相等。
- * 如getName()和setName()属性名一样,getName()和setAge()属性名不一样。 - * - * @param m1 方法名1 - * @param m2 方法名2 - * @return 属性名一样返回true,否则返回false - */ - - public static boolean isMethodPropEquals(String m1, String m2) - { - return m1.substring(BEAN_METHOD_PROP_INDEX).equals(m2.substring(BEAN_METHOD_PROP_INDEX)); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java deleted file mode 100644 index 68130b9c..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.ruoyi.common.utils.file; - -import java.io.File; -import org.apache.commons.lang3.StringUtils; - -/** - * 文件类型工具类 - * - * @author ruoyi - */ -public class FileTypeUtils -{ - /** - * 获取文件类型 - *

- * 例如: ruoyi.txt, 返回: txt - * - * @param file 文件名 - * @return 后缀(不含".") - */ - public static String getFileType(File file) - { - if (null == file) - { - return StringUtils.EMPTY; - } - return getFileType(file.getName()); - } - - /** - * 获取文件类型 - *

- * 例如: ruoyi.txt, 返回: txt - * - * @param fileName 文件名 - * @return 后缀(不含".") - */ - public static String getFileType(String fileName) - { - int separatorIndex = fileName.lastIndexOf("."); - if (separatorIndex < 0) - { - return ""; - } - return fileName.substring(separatorIndex + 1).toLowerCase(); - } - - /** - * 获取文件类型 - * - * @param photoByte 文件字节码 - * @return 后缀(不含".") - */ - public static String getFileExtendName(byte[] photoByte) - { - String strFileExtendName = "JPG"; - if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56) - && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97)) - { - strFileExtendName = "GIF"; - } - else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70)) - { - strFileExtendName = "JPG"; - } - else if ((photoByte[0] == 66) && (photoByte[1] == 77)) - { - strFileExtendName = "BMP"; - } - else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71)) - { - strFileExtendName = "PNG"; - } - return strFileExtendName; - } -} \ No newline at end of file diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java deleted file mode 100644 index eb12806e..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java +++ /dev/null @@ -1,235 +0,0 @@ -package com.ruoyi.common.utils.file; - -import java.io.File; -import java.io.IOException; -import org.apache.commons.io.FilenameUtils; -import org.springframework.web.multipart.MultipartFile; -import com.ruoyi.common.config.RuoYiConfig; -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.exception.file.FileNameLengthLimitExceededException; -import com.ruoyi.common.exception.file.FileSizeLimitExceededException; -import com.ruoyi.common.exception.file.InvalidExtensionException; -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.uuid.IdUtils; - -/** - * 文件上传工具类 - * - * @author ruoyi - */ -public class FileUploadUtils -{ - /** - * 默认大小 50M - */ - public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024; - - /** - * 默认的文件名最大长度 100 - */ - public static final int DEFAULT_FILE_NAME_LENGTH = 100; - - /** - * 默认上传的地址 - */ - private static String defaultBaseDir = RuoYiConfig.getProfile(); - - public static void setDefaultBaseDir(String defaultBaseDir) - { - FileUploadUtils.defaultBaseDir = defaultBaseDir; - } - - public static String getDefaultBaseDir() - { - return defaultBaseDir; - } - - /** - * 以默认配置进行文件上传 - * - * @param file 上传的文件 - * @return 文件名称 - * @throws Exception - */ - public static final String upload(MultipartFile file) throws IOException - { - try - { - return upload(getDefaultBaseDir(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION); - } - catch (Exception e) - { - throw new IOException(e.getMessage(), e); - } - } - - /** - * 根据文件路径上传 - * - * @param baseDir 相对应用的基目录 - * @param file 上传的文件 - * @return 文件名称 - * @throws IOException - */ - public static final String upload(String baseDir, MultipartFile file) throws IOException - { - try - { - return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION); - } - catch (Exception e) - { - throw new IOException(e.getMessage(), e); - } - } - - /** - * 文件上传 - * - * @param baseDir 相对应用的基目录 - * @param file 上传的文件 - * @param allowedExtension 上传文件类型 - * @return 返回上传成功的文件名 - * @throws FileSizeLimitExceededException 如果超出最大大小 - * @throws FileNameLengthLimitExceededException 文件名太长 - * @throws IOException 比如读写文件出错时 - * @throws InvalidExtensionException 文件校验异常 - */ - public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension) - throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException, - InvalidExtensionException - { - int fileNamelength = file.getOriginalFilename().length(); - if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) - { - throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH); - } - - assertAllowed(file, allowedExtension); - - String fileName = extractFilename(file); - - File desc = getAbsoluteFile(baseDir, fileName); - file.transferTo(desc); - String pathFileName = getPathFileName(baseDir, fileName); - return pathFileName; - } - - /** - * 编码文件名 - */ - public static final String extractFilename(MultipartFile file) - { - String fileName = file.getOriginalFilename(); - String extension = getExtension(file); - fileName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension; - return fileName; - } - - public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException - { - File desc = new File(uploadDir + File.separator + fileName); - - if (!desc.exists()) - { - if (!desc.getParentFile().exists()) - { - desc.getParentFile().mkdirs(); - } - } - return desc; - } - - public static final String getPathFileName(String uploadDir, String fileName) throws IOException - { - int dirLastIndex = RuoYiConfig.getProfile().length() + 1; - String currentDir = StringUtils.substring(uploadDir, dirLastIndex); - String pathFileName = Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName; - return pathFileName; - } - - /** - * 文件大小校验 - * - * @param file 上传的文件 - * @return - * @throws FileSizeLimitExceededException 如果超出最大大小 - * @throws InvalidExtensionException - */ - public static final void assertAllowed(MultipartFile file, String[] allowedExtension) - throws FileSizeLimitExceededException, InvalidExtensionException - { - long size = file.getSize(); - if (DEFAULT_MAX_SIZE != -1 && size > DEFAULT_MAX_SIZE) - { - throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024); - } - - String fileName = file.getOriginalFilename(); - String extension = getExtension(file); - if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension)) - { - if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION) - { - throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension, - fileName); - } - else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION) - { - throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension, - fileName); - } - else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION) - { - throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension, - fileName); - } - else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION) - { - throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension, - fileName); - } - else - { - throw new InvalidExtensionException(allowedExtension, extension, fileName); - } - } - - } - - /** - * 判断MIME类型是否是允许的MIME类型 - * - * @param extension - * @param allowedExtension - * @return - */ - public static final boolean isAllowedExtension(String extension, String[] allowedExtension) - { - for (String str : allowedExtension) - { - if (str.equalsIgnoreCase(extension)) - { - return true; - } - } - return false; - } - - /** - * 获取文件名的后缀 - * - * @param file 表单文件 - * @return 后缀名 - */ - public static final String getExtension(MultipartFile file) - { - String extension = FilenameUtils.getExtension(file.getOriginalFilename()); - if (StringUtils.isEmpty(extension)) - { - extension = MimeTypeUtils.getExtension(file.getContentType()); - } - return extension; - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java deleted file mode 100644 index 7a244598..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java +++ /dev/null @@ -1,259 +0,0 @@ -package com.ruoyi.common.utils.file; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.ArrayUtils; -import com.ruoyi.common.config.RuoYiConfig; -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.uuid.IdUtils; - -/** - * 文件处理工具类 - * - * @author ruoyi - */ -public class FileUtils -{ - public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+"; - - /** - * 输出指定文件的byte数组 - * - * @param filePath 文件路径 - * @param os 输出流 - * @return - */ - public static void writeBytes(String filePath, OutputStream os) throws IOException - { - FileInputStream fis = null; - try - { - File file = new File(filePath); - if (!file.exists()) - { - throw new FileNotFoundException(filePath); - } - fis = new FileInputStream(file); - byte[] b = new byte[1024]; - int length; - while ((length = fis.read(b)) > 0) - { - os.write(b, 0, length); - } - } - catch (IOException e) - { - throw e; - } - finally - { - IOUtils.close(os); - IOUtils.close(fis); - } - } - - /** - * 写数据到文件中 - * - * @param data 数据 - * @return 目标文件 - * @throws IOException IO异常 - */ - public static String writeImportBytes(byte[] data) throws IOException - { - return writeBytes(data, RuoYiConfig.getImportPath()); - } - - /** - * 写数据到文件中 - * - * @param data 数据 - * @param uploadDir 目标文件 - * @return 目标文件 - * @throws IOException IO异常 - */ - public static String writeBytes(byte[] data, String uploadDir) throws IOException - { - FileOutputStream fos = null; - String pathName = ""; - try - { - String extension = getFileExtendName(data); - pathName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension; - File file = FileUploadUtils.getAbsoluteFile(uploadDir, pathName); - fos = new FileOutputStream(file); - fos.write(data); - } - finally - { - IOUtils.close(fos); - } - return FileUploadUtils.getPathFileName(uploadDir, pathName); - } - - /** - * 删除文件 - * - * @param filePath 文件 - * @return - */ - public static boolean deleteFile(String filePath) - { - boolean flag = false; - File file = new File(filePath); - // 路径为文件且不为空则进行删除 - if (file.isFile() && file.exists()) - { - file.delete(); - flag = true; - } - return flag; - } - - /** - * 文件名称验证 - * - * @param filename 文件名称 - * @return true 正常 false 非法 - */ - public static boolean isValidFilename(String filename) - { - return filename.matches(FILENAME_PATTERN); - } - - /** - * 检查文件是否可下载 - * - * @param resource 需要下载的文件 - * @return true 正常 false 非法 - */ - public static boolean checkAllowDownload(String resource) - { - // 禁止目录上跳级别 - if (StringUtils.contains(resource, "..")) - { - return false; - } - - // 检查允许下载的文件规则 - if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource))) - { - return true; - } - - // 不在允许下载的文件规则 - return false; - } - - /** - * 下载文件名重新编码 - * - * @param request 请求对象 - * @param fileName 文件名 - * @return 编码后的文件名 - */ - public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException - { - final String agent = request.getHeader("USER-AGENT"); - String filename = fileName; - if (agent.contains("MSIE")) - { - // IE浏览器 - filename = URLEncoder.encode(filename, "utf-8"); - filename = filename.replace("+", " "); - } - else if (agent.contains("Firefox")) - { - // 火狐浏览器 - filename = new String(fileName.getBytes(), "ISO8859-1"); - } - else if (agent.contains("Chrome")) - { - // google浏览器 - filename = URLEncoder.encode(filename, "utf-8"); - } - else - { - // 其它浏览器 - filename = URLEncoder.encode(filename, "utf-8"); - } - return filename; - } - - /** - * 下载文件名重新编码 - * - * @param response 响应对象 - * @param realFileName 真实文件名 - * @return - */ - public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException - { - String percentEncodedFileName = percentEncode(realFileName); - - StringBuilder contentDispositionValue = new StringBuilder(); - contentDispositionValue.append("attachment; filename=") - .append(percentEncodedFileName) - .append(";") - .append("filename*=") - .append("utf-8''") - .append(percentEncodedFileName); - - response.addHeader("Access-Control-Allow-Origin", "*"); - response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename"); - response.setHeader("Content-disposition", contentDispositionValue.toString()); - response.setHeader("download-filename", percentEncodedFileName); - } - - /** - * 百分号编码工具方法 - * - * @param s 需要百分号编码的字符串 - * @return 百分号编码后的字符串 - */ - public static String percentEncode(String s) throws UnsupportedEncodingException - { - String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString()); - return encode.replaceAll("\\+", "%20"); - } - - /** - * 获取图像后缀 - * - * @param photoByte 图像数据 - * @return 后缀名 - */ - public static String getFileExtendName(byte[] photoByte) - { - String strFileExtendName = "jpg"; - if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56) - && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97)) - { - strFileExtendName = "gif"; - } - else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70)) - { - strFileExtendName = "jpg"; - } - else if ((photoByte[0] == 66) && (photoByte[1] == 77)) - { - strFileExtendName = "bmp"; - } - else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71)) - { - strFileExtendName = "png"; - } - return strFileExtendName; - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java deleted file mode 100644 index 0b7b5aaa..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.ruoyi.common.utils.file; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.FileInputStream; -import java.io.InputStream; -import java.net.URL; -import java.net.URLConnection; -import java.util.Arrays; -import org.apache.poi.util.IOUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import com.ruoyi.common.config.RuoYiConfig; -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.utils.StringUtils; - -/** - * 图片处理工具类 - * - * @author ruoyi - */ -public class ImageUtils -{ - private static final Logger log = LoggerFactory.getLogger(ImageUtils.class); - - public static byte[] getImage(String imagePath) - { - InputStream is = getFile(imagePath); - try - { - return IOUtils.toByteArray(is); - } - catch (Exception e) - { - log.error("图片加载异常 {}", e); - return null; - } - finally - { - IOUtils.closeQuietly(is); - } - } - - public static InputStream getFile(String imagePath) - { - try - { - byte[] result = readFile(imagePath); - result = Arrays.copyOf(result, result.length); - return new ByteArrayInputStream(result); - } - catch (Exception e) - { - log.error("获取图片异常 {}", e); - } - return null; - } - - /** - * 读取文件为字节数据 - * - * @param key 地址 - * @return 字节数据 - */ - public static byte[] readFile(String url) - { - InputStream in = null; - ByteArrayOutputStream baos = null; - try - { - if (url.startsWith("http")) - { - // 网络地址 - URL urlObj = new URL(url); - URLConnection urlConnection = urlObj.openConnection(); - urlConnection.setConnectTimeout(30 * 1000); - urlConnection.setReadTimeout(60 * 1000); - urlConnection.setDoInput(true); - in = urlConnection.getInputStream(); - } - else - { - // 本机地址 - String localPath = RuoYiConfig.getProfile(); - String downloadPath = localPath + StringUtils.substringAfter(url, Constants.RESOURCE_PREFIX); - in = new FileInputStream(downloadPath); - } - return IOUtils.toByteArray(in); - } - catch (Exception e) - { - log.error("获取文件路径异常 {}", e); - return null; - } - finally - { - IOUtils.closeQuietly(in); - IOUtils.closeQuietly(baos); - } - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java deleted file mode 100644 index f968f1a1..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.ruoyi.common.utils.file; - -/** - * 媒体类型工具类 - * - * @author ruoyi - */ -public class MimeTypeUtils -{ - public static final String IMAGE_PNG = "image/png"; - - public static final String IMAGE_JPG = "image/jpg"; - - public static final String IMAGE_JPEG = "image/jpeg"; - - public static final String IMAGE_BMP = "image/bmp"; - - public static final String IMAGE_GIF = "image/gif"; - - public static final String[] IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" }; - - public static final String[] FLASH_EXTENSION = { "swf", "flv" }; - - public static final String[] MEDIA_EXTENSION = { "swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg", - "asf", "rm", "rmvb" }; - - public static final String[] VIDEO_EXTENSION = { "mp4", "avi", "rmvb" }; - - public static final String[] DEFAULT_ALLOWED_EXTENSION = { - // 图片 - "bmp", "gif", "jpg", "jpeg", "png", - // word excel powerpoint - "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt", - // 压缩文件 - "rar", "zip", "gz", "bz2", - // 视频格式 - "mp4", "avi", "rmvb", - // pdf - "pdf" }; - - public static String getExtension(String prefix) - { - switch (prefix) - { - case IMAGE_PNG: - return "png"; - case IMAGE_JPG: - return "jpg"; - case IMAGE_JPEG: - return "jpeg"; - case IMAGE_BMP: - return "bmp"; - case IMAGE_GIF: - return "gif"; - default: - return ""; - } - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java deleted file mode 100644 index f52e83e5..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java +++ /dev/null @@ -1,167 +0,0 @@ -package com.ruoyi.common.utils.html; - -import com.ruoyi.common.utils.StringUtils; - -/** - * 转义和反转义工具类 - * - * @author ruoyi - */ -public class EscapeUtil -{ - public static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)"; - - private static final char[][] TEXT = new char[64][]; - - static - { - for (int i = 0; i < 64; i++) - { - TEXT[i] = new char[] { (char) i }; - } - - // special HTML characters - TEXT['\''] = "'".toCharArray(); // 单引号 - TEXT['"'] = """.toCharArray(); // 双引号 - TEXT['&'] = "&".toCharArray(); // &符 - TEXT['<'] = "<".toCharArray(); // 小于号 - TEXT['>'] = ">".toCharArray(); // 大于号 - } - - /** - * 转义文本中的HTML字符为安全的字符 - * - * @param text 被转义的文本 - * @return 转义后的文本 - */ - public static String escape(String text) - { - return encode(text); - } - - /** - * 还原被转义的HTML特殊字符 - * - * @param content 包含转义符的HTML内容 - * @return 转换后的字符串 - */ - public static String unescape(String content) - { - return decode(content); - } - - /** - * 清除所有HTML标签,但是不删除标签内的内容 - * - * @param content 文本 - * @return 清除标签后的文本 - */ - public static String clean(String content) - { - return new HTMLFilter().filter(content); - } - - /** - * Escape编码 - * - * @param text 被编码的文本 - * @return 编码后的字符 - */ - private static String encode(String text) - { - if (StringUtils.isEmpty(text)) - { - return StringUtils.EMPTY; - } - - final StringBuilder tmp = new StringBuilder(text.length() * 6); - char c; - for (int i = 0; i < text.length(); i++) - { - c = text.charAt(i); - if (c < 256) - { - tmp.append("%"); - if (c < 16) - { - tmp.append("0"); - } - tmp.append(Integer.toString(c, 16)); - } - else - { - tmp.append("%u"); - if (c <= 0xfff) - { - // issue#I49JU8@Gitee - tmp.append("0"); - } - tmp.append(Integer.toString(c, 16)); - } - } - return tmp.toString(); - } - - /** - * Escape解码 - * - * @param content 被转义的内容 - * @return 解码后的字符串 - */ - public static String decode(String content) - { - if (StringUtils.isEmpty(content)) - { - return content; - } - - StringBuilder tmp = new StringBuilder(content.length()); - int lastPos = 0, pos = 0; - char ch; - while (lastPos < content.length()) - { - pos = content.indexOf("%", lastPos); - if (pos == lastPos) - { - if (content.charAt(pos + 1) == 'u') - { - ch = (char) Integer.parseInt(content.substring(pos + 2, pos + 6), 16); - tmp.append(ch); - lastPos = pos + 6; - } - else - { - ch = (char) Integer.parseInt(content.substring(pos + 1, pos + 3), 16); - tmp.append(ch); - lastPos = pos + 3; - } - } - else - { - if (pos == -1) - { - tmp.append(content.substring(lastPos)); - lastPos = content.length(); - } - else - { - tmp.append(content.substring(lastPos, pos)); - lastPos = pos; - } - } - } - return tmp.toString(); - } - - public static void main(String[] args) - { - String html = ""; - String escape = EscapeUtil.escape(html); - // String html = "ipt>alert(\"XSS\")ipt>"; - // String html = "<123"; - // String html = "123>"; - System.out.println("clean: " + EscapeUtil.clean(html)); - System.out.println("escape: " + escape); - System.out.println("unescape: " + EscapeUtil.unescape(escape)); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java deleted file mode 100644 index db069bc8..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java +++ /dev/null @@ -1,570 +0,0 @@ -package com.ruoyi.common.utils.html; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * HTML过滤器,用于去除XSS漏洞隐患。 - * - * @author ruoyi - */ -public final class HTMLFilter -{ - /** - * regex flag union representing /si modifiers in php - **/ - private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL; - private static final Pattern P_COMMENTS = Pattern.compile("", Pattern.DOTALL); - private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI); - private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL); - private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI); - private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI); - private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI); - private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI); - private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI); - private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?"); - private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?"); - private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?"); - private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))"); - private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL); - private static final Pattern P_END_ARROW = Pattern.compile("^>"); - private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)"); - private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)"); - private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)"); - private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)"); - private static final Pattern P_AMP = Pattern.compile("&"); - private static final Pattern P_QUOTE = Pattern.compile("\""); - private static final Pattern P_LEFT_ARROW = Pattern.compile("<"); - private static final Pattern P_RIGHT_ARROW = Pattern.compile(">"); - private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>"); - - // @xxx could grow large... maybe use sesat's ReferenceMap - private static final ConcurrentMap P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<>(); - private static final ConcurrentMap P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<>(); - - /** - * set of allowed html elements, along with allowed attributes for each element - **/ - private final Map> vAllowed; - /** - * counts of open tags for each (allowable) html element - **/ - private final Map vTagCounts = new HashMap<>(); - - /** - * html elements which must always be self-closing (e.g. "") - **/ - private final String[] vSelfClosingTags; - /** - * html elements which must always have separate opening and closing tags (e.g. "") - **/ - private final String[] vNeedClosingTags; - /** - * set of disallowed html elements - **/ - private final String[] vDisallowed; - /** - * attributes which should be checked for valid protocols - **/ - private final String[] vProtocolAtts; - /** - * allowed protocols - **/ - private final String[] vAllowedProtocols; - /** - * tags which should be removed if they contain no content (e.g. "" or "") - **/ - private final String[] vRemoveBlanks; - /** - * entities allowed within html markup - **/ - private final String[] vAllowedEntities; - /** - * flag determining whether comments are allowed in input String. - */ - private final boolean stripComment; - private final boolean encodeQuotes; - /** - * flag determining whether to try to make tags when presented with "unbalanced" angle brackets (e.g. "" - * becomes " text "). If set to false, unbalanced angle brackets will be html escaped. - */ - private final boolean alwaysMakeTags; - - /** - * Default constructor. - */ - public HTMLFilter() - { - vAllowed = new HashMap<>(); - - final ArrayList a_atts = new ArrayList<>(); - a_atts.add("href"); - a_atts.add("target"); - vAllowed.put("a", a_atts); - - final ArrayList img_atts = new ArrayList<>(); - img_atts.add("src"); - img_atts.add("width"); - img_atts.add("height"); - img_atts.add("alt"); - vAllowed.put("img", img_atts); - - final ArrayList no_atts = new ArrayList<>(); - vAllowed.put("b", no_atts); - vAllowed.put("strong", no_atts); - vAllowed.put("i", no_atts); - vAllowed.put("em", no_atts); - - vSelfClosingTags = new String[] { "img" }; - vNeedClosingTags = new String[] { "a", "b", "strong", "i", "em" }; - vDisallowed = new String[] {}; - vAllowedProtocols = new String[] { "http", "mailto", "https" }; // no ftp. - vProtocolAtts = new String[] { "src", "href" }; - vRemoveBlanks = new String[] { "a", "b", "strong", "i", "em" }; - vAllowedEntities = new String[] { "amp", "gt", "lt", "quot" }; - stripComment = true; - encodeQuotes = true; - alwaysMakeTags = false; - } - - /** - * Map-parameter configurable constructor. - * - * @param conf map containing configuration. keys match field names. - */ - @SuppressWarnings("unchecked") - public HTMLFilter(final Map conf) - { - - assert conf.containsKey("vAllowed") : "configuration requires vAllowed"; - assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags"; - assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags"; - assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed"; - assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols"; - assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts"; - assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks"; - assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities"; - - vAllowed = Collections.unmodifiableMap((HashMap>) conf.get("vAllowed")); - vSelfClosingTags = (String[]) conf.get("vSelfClosingTags"); - vNeedClosingTags = (String[]) conf.get("vNeedClosingTags"); - vDisallowed = (String[]) conf.get("vDisallowed"); - vAllowedProtocols = (String[]) conf.get("vAllowedProtocols"); - vProtocolAtts = (String[]) conf.get("vProtocolAtts"); - vRemoveBlanks = (String[]) conf.get("vRemoveBlanks"); - vAllowedEntities = (String[]) conf.get("vAllowedEntities"); - stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true; - encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true; - alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true; - } - - private void reset() - { - vTagCounts.clear(); - } - - // --------------------------------------------------------------- - // my versions of some PHP library functions - public static String chr(final int decimal) - { - return String.valueOf((char) decimal); - } - - public static String htmlSpecialChars(final String s) - { - String result = s; - result = regexReplace(P_AMP, "&", result); - result = regexReplace(P_QUOTE, """, result); - result = regexReplace(P_LEFT_ARROW, "<", result); - result = regexReplace(P_RIGHT_ARROW, ">", result); - return result; - } - - // --------------------------------------------------------------- - - /** - * given a user submitted input String, filter out any invalid or restricted html. - * - * @param input text (i.e. submitted by a user) than may contain html - * @return "clean" version of input, with only valid, whitelisted html elements allowed - */ - public String filter(final String input) - { - reset(); - String s = input; - - s = escapeComments(s); - - s = balanceHTML(s); - - s = checkTags(s); - - s = processRemoveBlanks(s); - - // s = validateEntities(s); - - return s; - } - - public boolean isAlwaysMakeTags() - { - return alwaysMakeTags; - } - - public boolean isStripComments() - { - return stripComment; - } - - private String escapeComments(final String s) - { - final Matcher m = P_COMMENTS.matcher(s); - final StringBuffer buf = new StringBuffer(); - if (m.find()) - { - final String match = m.group(1); // (.*?) - m.appendReplacement(buf, Matcher.quoteReplacement("")); - } - m.appendTail(buf); - - return buf.toString(); - } - - private String balanceHTML(String s) - { - if (alwaysMakeTags) - { - // - // try and form html - // - s = regexReplace(P_END_ARROW, "", s); - // 不追加结束标签 - s = regexReplace(P_BODY_TO_END, "<$1>", s); - s = regexReplace(P_XML_CONTENT, "$1<$2", s); - - } - else - { - // - // escape stray brackets - // - s = regexReplace(P_STRAY_LEFT_ARROW, "<$1", s); - s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2><", s); - - // - // the last regexp causes '<>' entities to appear - // (we need to do a lookahead assertion so that the last bracket can - // be used in the next pass of the regexp) - // - s = regexReplace(P_BOTH_ARROWS, "", s); - } - - return s; - } - - private String checkTags(String s) - { - Matcher m = P_TAGS.matcher(s); - - final StringBuffer buf = new StringBuffer(); - while (m.find()) - { - String replaceStr = m.group(1); - replaceStr = processTag(replaceStr); - m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr)); - } - m.appendTail(buf); - - // these get tallied in processTag - // (remember to reset before subsequent calls to filter method) - final StringBuilder sBuilder = new StringBuilder(buf.toString()); - for (String key : vTagCounts.keySet()) - { - for (int ii = 0; ii < vTagCounts.get(key); ii++) - { - sBuilder.append(""); - } - } - s = sBuilder.toString(); - - return s; - } - - private String processRemoveBlanks(final String s) - { - String result = s; - for (String tag : vRemoveBlanks) - { - if (!P_REMOVE_PAIR_BLANKS.containsKey(tag)) - { - P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?>")); - } - result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result); - if (!P_REMOVE_SELF_BLANKS.containsKey(tag)) - { - P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>")); - } - result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result); - } - - return result; - } - - private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) - { - Matcher m = regex_pattern.matcher(s); - return m.replaceAll(replacement); - } - - private String processTag(final String s) - { - // ending tags - Matcher m = P_END_TAG.matcher(s); - if (m.find()) - { - final String name = m.group(1).toLowerCase(); - if (allowed(name)) - { - if (!inArray(name, vSelfClosingTags)) - { - if (vTagCounts.containsKey(name)) - { - vTagCounts.put(name, vTagCounts.get(name) - 1); - return ""; - } - } - } - } - - // starting tags - m = P_START_TAG.matcher(s); - if (m.find()) - { - final String name = m.group(1).toLowerCase(); - final String body = m.group(2); - String ending = m.group(3); - - // debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" ); - if (allowed(name)) - { - final StringBuilder params = new StringBuilder(); - - final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body); - final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body); - final List paramNames = new ArrayList<>(); - final List paramValues = new ArrayList<>(); - while (m2.find()) - { - paramNames.add(m2.group(1)); // ([a-z0-9]+) - paramValues.add(m2.group(3)); // (.*?) - } - while (m3.find()) - { - paramNames.add(m3.group(1)); // ([a-z0-9]+) - paramValues.add(m3.group(3)); // ([^\"\\s']+) - } - - String paramName, paramValue; - for (int ii = 0; ii < paramNames.size(); ii++) - { - paramName = paramNames.get(ii).toLowerCase(); - paramValue = paramValues.get(ii); - - // debug( "paramName='" + paramName + "'" ); - // debug( "paramValue='" + paramValue + "'" ); - // debug( "allowed? " + vAllowed.get( name ).contains( paramName ) ); - - if (allowedAttribute(name, paramName)) - { - if (inArray(paramName, vProtocolAtts)) - { - paramValue = processParamProtocol(paramValue); - } - params.append(' ').append(paramName).append("=\\\"").append(paramValue).append("\""); - } - } - - if (inArray(name, vSelfClosingTags)) - { - ending = " /"; - } - - if (inArray(name, vNeedClosingTags)) - { - ending = ""; - } - - if (ending == null || ending.length() < 1) - { - if (vTagCounts.containsKey(name)) - { - vTagCounts.put(name, vTagCounts.get(name) + 1); - } - else - { - vTagCounts.put(name, 1); - } - } - else - { - ending = " /"; - } - return "<" + name + params + ending + ">"; - } - else - { - return ""; - } - } - - // comments - m = P_COMMENT.matcher(s); - if (!stripComment && m.find()) - { - return "<" + m.group() + ">"; - } - - return ""; - } - - private String processParamProtocol(String s) - { - s = decodeEntities(s); - final Matcher m = P_PROTOCOL.matcher(s); - if (m.find()) - { - final String protocol = m.group(1); - if (!inArray(protocol, vAllowedProtocols)) - { - // bad protocol, turn into local anchor link instead - s = "#" + s.substring(protocol.length() + 1); - if (s.startsWith("#//")) - { - s = "#" + s.substring(3); - } - } - } - - return s; - } - - private String decodeEntities(String s) - { - StringBuffer buf = new StringBuffer(); - - Matcher m = P_ENTITY.matcher(s); - while (m.find()) - { - final String match = m.group(1); - final int decimal = Integer.decode(match).intValue(); - m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); - } - m.appendTail(buf); - s = buf.toString(); - - buf = new StringBuffer(); - m = P_ENTITY_UNICODE.matcher(s); - while (m.find()) - { - final String match = m.group(1); - final int decimal = Integer.valueOf(match, 16).intValue(); - m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); - } - m.appendTail(buf); - s = buf.toString(); - - buf = new StringBuffer(); - m = P_ENCODE.matcher(s); - while (m.find()) - { - final String match = m.group(1); - final int decimal = Integer.valueOf(match, 16).intValue(); - m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); - } - m.appendTail(buf); - s = buf.toString(); - - s = validateEntities(s); - return s; - } - - private String validateEntities(final String s) - { - StringBuffer buf = new StringBuffer(); - - // validate entities throughout the string - Matcher m = P_VALID_ENTITIES.matcher(s); - while (m.find()) - { - final String one = m.group(1); // ([^&;]*) - final String two = m.group(2); // (?=(;|&|$)) - m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two))); - } - m.appendTail(buf); - - return encodeQuotes(buf.toString()); - } - - private String encodeQuotes(final String s) - { - if (encodeQuotes) - { - StringBuffer buf = new StringBuffer(); - Matcher m = P_VALID_QUOTES.matcher(s); - while (m.find()) - { - final String one = m.group(1); // (>|^) - final String two = m.group(2); // ([^<]+?) - final String three = m.group(3); // (<|$) - // 不替换双引号为",防止json格式无效 regexReplace(P_QUOTE, """, two) - m.appendReplacement(buf, Matcher.quoteReplacement(one + two + three)); - } - m.appendTail(buf); - return buf.toString(); - } - else - { - return s; - } - } - - private String checkEntity(final String preamble, final String term) - { - - return ";".equals(term) && isValidEntity(preamble) ? '&' + preamble : "&" + preamble; - } - - private boolean isValidEntity(final String entity) - { - return inArray(entity, vAllowedEntities); - } - - private static boolean inArray(final String s, final String[] array) - { - for (String item : array) - { - if (item != null && item.equals(s)) - { - return true; - } - } - return false; - } - - private boolean allowed(final String name) - { - return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed); - } - - private boolean allowedAttribute(final String name, final String paramName) - { - return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName)); - } -} \ No newline at end of file diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java deleted file mode 100644 index dac60ad0..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.ruoyi.common.utils.http; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.Charset; -import javax.servlet.ServletRequest; -import org.apache.commons.lang3.exception.ExceptionUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * 通用http工具封装 - * - * @author ruoyi - */ -public class HttpHelper -{ - private static final Logger LOGGER = LoggerFactory.getLogger(HttpHelper.class); - - public static String getBodyString(ServletRequest request) - { - StringBuilder sb = new StringBuilder(); - BufferedReader reader = null; - try (InputStream inputStream = request.getInputStream()) - { - reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8"))); - String line = ""; - while ((line = reader.readLine()) != null) - { - sb.append(line); - } - } - catch (IOException e) - { - LOGGER.warn("getBodyString出现问题!"); - } - finally - { - if (reader != null) - { - try - { - reader.close(); - } - catch (IOException e) - { - LOGGER.error(ExceptionUtils.getMessage(e)); - } - } - } - return sb.toString(); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java deleted file mode 100644 index e319d370..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java +++ /dev/null @@ -1,274 +0,0 @@ -package com.ruoyi.common.utils.http; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.PrintWriter; -import java.net.ConnectException; -import java.net.SocketTimeoutException; -import java.net.URL; -import java.net.URLConnection; -import java.security.cert.X509Certificate; -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSession; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.utils.StringUtils; - -/** - * 通用http发送方法 - * - * @author ruoyi - */ -public class HttpUtils -{ - private static final Logger log = LoggerFactory.getLogger(HttpUtils.class); - - /** - * 向指定 URL 发送GET方法的请求 - * - * @param url 发送请求的 URL - * @return 所代表远程资源的响应结果 - */ - public static String sendGet(String url) - { - return sendGet(url, StringUtils.EMPTY); - } - - /** - * 向指定 URL 发送GET方法的请求 - * - * @param url 发送请求的 URL - * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 - * @return 所代表远程资源的响应结果 - */ - public static String sendGet(String url, String param) - { - return sendGet(url, param, Constants.UTF8); - } - - /** - * 向指定 URL 发送GET方法的请求 - * - * @param url 发送请求的 URL - * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 - * @param contentType 编码类型 - * @return 所代表远程资源的响应结果 - */ - public static String sendGet(String url, String param, String contentType) - { - StringBuilder result = new StringBuilder(); - BufferedReader in = null; - try - { - String urlNameString = StringUtils.isNotBlank(param) ? url + "?" + param : url; - log.info("sendGet - {}", urlNameString); - URL realUrl = new URL(urlNameString); - URLConnection connection = realUrl.openConnection(); - connection.setRequestProperty("accept", "*/*"); - connection.setRequestProperty("connection", "Keep-Alive"); - connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); - connection.connect(); - in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType)); - String line; - while ((line = in.readLine()) != null) - { - result.append(line); - } - log.info("recv - {}", result); - } - catch (ConnectException e) - { - log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e); - } - catch (SocketTimeoutException e) - { - log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e); - } - catch (IOException e) - { - log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e); - } - catch (Exception e) - { - log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e); - } - finally - { - try - { - if (in != null) - { - in.close(); - } - } - catch (Exception ex) - { - log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); - } - } - return result.toString(); - } - - /** - * 向指定 URL 发送POST方法的请求 - * - * @param url 发送请求的 URL - * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 - * @return 所代表远程资源的响应结果 - */ - public static String sendPost(String url, String param) - { - PrintWriter out = null; - BufferedReader in = null; - StringBuilder result = new StringBuilder(); - try - { - String urlNameString = url; - log.info("sendPost - {}", urlNameString); - URL realUrl = new URL(urlNameString); - URLConnection conn = realUrl.openConnection(); - conn.setRequestProperty("accept", "*/*"); - conn.setRequestProperty("connection", "Keep-Alive"); - conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); - conn.setRequestProperty("Accept-Charset", "utf-8"); - conn.setRequestProperty("contentType", "utf-8"); - conn.setDoOutput(true); - conn.setDoInput(true); - out = new PrintWriter(conn.getOutputStream()); - out.print(param); - out.flush(); - in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8")); - String line; - while ((line = in.readLine()) != null) - { - result.append(line); - } - log.info("recv - {}", result); - } - catch (ConnectException e) - { - log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e); - } - catch (SocketTimeoutException e) - { - log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e); - } - catch (IOException e) - { - log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e); - } - catch (Exception e) - { - log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e); - } - finally - { - try - { - if (out != null) - { - out.close(); - } - if (in != null) - { - in.close(); - } - } - catch (IOException ex) - { - log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); - } - } - return result.toString(); - } - - public static String sendSSLPost(String url, String param) - { - StringBuilder result = new StringBuilder(); - String urlNameString = url + "?" + param; - try - { - log.info("sendSSLPost - {}", urlNameString); - SSLContext sc = SSLContext.getInstance("SSL"); - sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom()); - URL console = new URL(urlNameString); - HttpsURLConnection conn = (HttpsURLConnection) console.openConnection(); - conn.setRequestProperty("accept", "*/*"); - conn.setRequestProperty("connection", "Keep-Alive"); - conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); - conn.setRequestProperty("Accept-Charset", "utf-8"); - conn.setRequestProperty("contentType", "utf-8"); - conn.setDoOutput(true); - conn.setDoInput(true); - - conn.setSSLSocketFactory(sc.getSocketFactory()); - conn.setHostnameVerifier(new TrustAnyHostnameVerifier()); - conn.connect(); - InputStream is = conn.getInputStream(); - BufferedReader br = new BufferedReader(new InputStreamReader(is)); - String ret = ""; - while ((ret = br.readLine()) != null) - { - if (ret != null && !"".equals(ret.trim())) - { - result.append(new String(ret.getBytes("ISO-8859-1"), "utf-8")); - } - } - log.info("recv - {}", result); - conn.disconnect(); - br.close(); - } - catch (ConnectException e) - { - log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e); - } - catch (SocketTimeoutException e) - { - log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e); - } - catch (IOException e) - { - log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e); - } - catch (Exception e) - { - log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e); - } - return result.toString(); - } - - private static class TrustAnyTrustManager implements X509TrustManager - { - @Override - public void checkClientTrusted(X509Certificate[] chain, String authType) - { - } - - @Override - public void checkServerTrusted(X509Certificate[] chain, String authType) - { - } - - @Override - public X509Certificate[] getAcceptedIssuers() - { - return new X509Certificate[] {}; - } - } - - private static class TrustAnyHostnameVerifier implements HostnameVerifier - { - @Override - public boolean verify(String hostname, SSLSession session) - { - return true; - } - } -} \ No newline at end of file diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java deleted file mode 100644 index 01c24fc7..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.ruoyi.common.utils.ip; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import com.alibaba.fastjson.JSONObject; -import com.ruoyi.common.config.RuoYiConfig; -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.http.HttpUtils; - -/** - * 获取地址类 - * - * @author ruoyi - */ -public class AddressUtils -{ - private static final Logger log = LoggerFactory.getLogger(AddressUtils.class); - - // IP地址查询 - public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp"; - - // 未知地址 - public static final String UNKNOWN = "XX XX"; - - public static String getRealAddressByIP(String ip) - { - String address = UNKNOWN; - // 内网不查询 - if (IpUtils.internalIp(ip)) - { - return "内网IP"; - } - if (RuoYiConfig.isAddressEnabled()) - { - try - { - String rspStr = HttpUtils.sendGet(IP_URL, "ip=" + ip + "&json=true", Constants.GBK); - if (StringUtils.isEmpty(rspStr)) - { - log.error("获取地理位置异常 {}", ip); - return UNKNOWN; - } - JSONObject obj = JSONObject.parseObject(rspStr); - String region = obj.getString("pro"); - String city = obj.getString("city"); - return String.format("%s %s", region, city); - } - catch (Exception e) - { - log.error("获取地理位置异常 {}", ip); - } - } - return address; - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java deleted file mode 100644 index 1b3f42ba..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java +++ /dev/null @@ -1,195 +0,0 @@ -package com.ruoyi.common.utils.ip; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import javax.servlet.http.HttpServletRequest; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.html.EscapeUtil; - -/** - * 获取IP方法 - * - * @author ruoyi - */ -public class IpUtils -{ - public static String getIpAddr(HttpServletRequest request) - { - if (request == null) - { - return "unknown"; - } - String ip = request.getHeader("x-forwarded-for"); - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) - { - ip = request.getHeader("Proxy-Client-IP"); - } - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) - { - ip = request.getHeader("X-Forwarded-For"); - } - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) - { - ip = request.getHeader("WL-Proxy-Client-IP"); - } - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) - { - ip = request.getHeader("X-Real-IP"); - } - - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) - { - ip = request.getRemoteAddr(); - } - return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : EscapeUtil.clean(ip); - } - - public static boolean internalIp(String ip) - { - byte[] addr = textToNumericFormatV4(ip); - return internalIp(addr) || "127.0.0.1".equals(ip); - } - - private static boolean internalIp(byte[] addr) - { - if (StringUtils.isNull(addr) || addr.length < 2) - { - return true; - } - final byte b0 = addr[0]; - final byte b1 = addr[1]; - // 10.x.x.x/8 - final byte SECTION_1 = 0x0A; - // 172.16.x.x/12 - final byte SECTION_2 = (byte) 0xAC; - final byte SECTION_3 = (byte) 0x10; - final byte SECTION_4 = (byte) 0x1F; - // 192.168.x.x/16 - final byte SECTION_5 = (byte) 0xC0; - final byte SECTION_6 = (byte) 0xA8; - switch (b0) - { - case SECTION_1: - return true; - case SECTION_2: - if (b1 >= SECTION_3 && b1 <= SECTION_4) - { - return true; - } - case SECTION_5: - switch (b1) - { - case SECTION_6: - return true; - } - default: - return false; - } - } - - /** - * 将IPv4地址转换成字节 - * - * @param text IPv4地址 - * @return byte 字节 - */ - public static byte[] textToNumericFormatV4(String text) - { - if (text.length() == 0) - { - return null; - } - - byte[] bytes = new byte[4]; - String[] elements = text.split("\\.", -1); - try - { - long l; - int i; - switch (elements.length) - { - case 1: - l = Long.parseLong(elements[0]); - if ((l < 0L) || (l > 4294967295L)) { - return null; - } - bytes[0] = (byte) (int) (l >> 24 & 0xFF); - bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF); - bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); - bytes[3] = (byte) (int) (l & 0xFF); - break; - case 2: - l = Integer.parseInt(elements[0]); - if ((l < 0L) || (l > 255L)) { - return null; - } - bytes[0] = (byte) (int) (l & 0xFF); - l = Integer.parseInt(elements[1]); - if ((l < 0L) || (l > 16777215L)) { - return null; - } - bytes[1] = (byte) (int) (l >> 16 & 0xFF); - bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); - bytes[3] = (byte) (int) (l & 0xFF); - break; - case 3: - for (i = 0; i < 2; ++i) - { - l = Integer.parseInt(elements[i]); - if ((l < 0L) || (l > 255L)) { - return null; - } - bytes[i] = (byte) (int) (l & 0xFF); - } - l = Integer.parseInt(elements[2]); - if ((l < 0L) || (l > 65535L)) { - return null; - } - bytes[2] = (byte) (int) (l >> 8 & 0xFF); - bytes[3] = (byte) (int) (l & 0xFF); - break; - case 4: - for (i = 0; i < 4; ++i) - { - l = Integer.parseInt(elements[i]); - if ((l < 0L) || (l > 255L)) { - return null; - } - bytes[i] = (byte) (int) (l & 0xFF); - } - break; - default: - return null; - } - } - catch (NumberFormatException e) - { - return null; - } - return bytes; - } - - public static String getHostIp() - { - try - { - return InetAddress.getLocalHost().getHostAddress(); - } - catch (UnknownHostException e) - { - } - return "127.0.0.1"; - } - - public static String getHostName() - { - try - { - return InetAddress.getLocalHost().getHostName(); - } - catch (UnknownHostException e) - { - } - return "未知"; - } -} \ No newline at end of file diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java deleted file mode 100644 index 5ea74c11..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.ruoyi.common.utils.poi; - -/** - * Excel数据格式处理适配器 - * - * @author ruoyi - */ -public interface ExcelHandlerAdapter -{ - /** - * 格式化 - * - * @param value 单元格数据值 - * @param args excel注解args参数组 - * - * @return 处理后的值 - */ - Object format(Object value, String[] args); -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java deleted file mode 100644 index 4557ca0b..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java +++ /dev/null @@ -1,1391 +0,0 @@ -package com.ruoyi.common.utils.poi; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.math.BigDecimal; -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.stream.Collectors; -import javax.servlet.http.HttpServletResponse; -import org.apache.poi.hssf.usermodel.HSSFClientAnchor; -import org.apache.poi.hssf.usermodel.HSSFPicture; -import org.apache.poi.hssf.usermodel.HSSFPictureData; -import org.apache.poi.hssf.usermodel.HSSFShape; -import org.apache.poi.hssf.usermodel.HSSFSheet; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.ooxml.POIXMLDocumentPart; -import org.apache.poi.ss.usermodel.BorderStyle; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.CellStyle; -import org.apache.poi.ss.usermodel.CellType; -import org.apache.poi.ss.usermodel.ClientAnchor; -import org.apache.poi.ss.usermodel.DataValidation; -import org.apache.poi.ss.usermodel.DataValidationConstraint; -import org.apache.poi.ss.usermodel.DataValidationHelper; -import org.apache.poi.ss.usermodel.DateUtil; -import org.apache.poi.ss.usermodel.Drawing; -import org.apache.poi.ss.usermodel.FillPatternType; -import org.apache.poi.ss.usermodel.Font; -import org.apache.poi.ss.usermodel.HorizontalAlignment; -import org.apache.poi.ss.usermodel.IndexedColors; -import org.apache.poi.ss.usermodel.PictureData; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.VerticalAlignment; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.ss.usermodel.WorkbookFactory; -import org.apache.poi.ss.util.CellRangeAddress; -import org.apache.poi.ss.util.CellRangeAddressList; -import org.apache.poi.util.IOUtils; -import org.apache.poi.xssf.streaming.SXSSFWorkbook; -import org.apache.poi.xssf.usermodel.XSSFClientAnchor; -import org.apache.poi.xssf.usermodel.XSSFDataValidation; -import org.apache.poi.xssf.usermodel.XSSFDrawing; -import org.apache.poi.xssf.usermodel.XSSFPicture; -import org.apache.poi.xssf.usermodel.XSSFShape; -import org.apache.poi.xssf.usermodel.XSSFSheet; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import com.ruoyi.common.annotation.Excel; -import com.ruoyi.common.annotation.Excel.ColumnType; -import com.ruoyi.common.annotation.Excel.Type; -import com.ruoyi.common.annotation.Excels; -import com.ruoyi.common.config.RuoYiConfig; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.text.Convert; -import com.ruoyi.common.exception.UtilException; -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.common.utils.DictUtils; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.file.FileTypeUtils; -import com.ruoyi.common.utils.file.FileUtils; -import com.ruoyi.common.utils.file.ImageUtils; -import com.ruoyi.common.utils.reflect.ReflectUtils; - -/** - * Excel相关处理 - * - * @author ruoyi - */ -public class ExcelUtil -{ - private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class); - - /** - * Excel sheet最大行数,默认65536 - */ - public static final int sheetSize = 65536; - - /** - * 工作表名称 - */ - private String sheetName; - - /** - * 导出类型(EXPORT:导出数据;IMPORT:导入模板) - */ - private Type type; - - /** - * 工作薄对象 - */ - private Workbook wb; - - /** - * 工作表对象 - */ - private Sheet sheet; - - /** - * 样式列表 - */ - private Map styles; - - /** - * 导入导出数据列表 - */ - private List list; - - /** - * 注解列表 - */ - private List fields; - - /** - * 当前行号 - */ - private int rownum; - - /** - * 标题 - */ - private String title; - - /** - * 最大高度 - */ - private short maxHeight; - - /** - * 统计列表 - */ - private Map statistics = new HashMap(); - - /** - * 数字格式 - */ - private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00"); - - /** - * 实体对象 - */ - public Class clazz; - - public ExcelUtil(Class clazz) - { - this.clazz = clazz; - } - - public void init(List list, String sheetName, String title, Type type) - { - if (list == null) - { - list = new ArrayList(); - } - this.list = list; - this.sheetName = sheetName; - this.type = type; - this.title = title; - createExcelField(); - createWorkbook(); - createTitle(); - } - - /** - * 创建excel第一行标题 - */ - public void createTitle() - { - if (StringUtils.isNotEmpty(title)) - { - Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0); - titleRow.setHeightInPoints(30); - Cell titleCell = titleRow.createCell(0); - titleCell.setCellStyle(styles.get("title")); - titleCell.setCellValue(title); - sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(), - this.fields.size() - 1)); - } - } - - /** - * 对excel表单默认第一个索引名转换成list - * - * @param is 输入流 - * @return 转换后集合 - */ - public List importExcel(InputStream is) throws Exception - { - return importExcel(is, 0); - } - - /** - * 对excel表单默认第一个索引名转换成list - * - * @param is 输入流 - * @param titleNum 标题占用行数 - * @return 转换后集合 - */ - public List importExcel(InputStream is, int titleNum) throws Exception - { - return importExcel(StringUtils.EMPTY, is, titleNum); - } - - /** - * 对excel表单指定表格索引名转换成list - * - * @param sheetName 表格索引名 - * @param titleNum 标题占用行数 - * @param is 输入流 - * @return 转换后集合 - */ - public List importExcel(String sheetName, InputStream is, int titleNum) throws Exception - { - this.type = Type.IMPORT; - this.wb = WorkbookFactory.create(is); - List list = new ArrayList(); - // 如果指定sheet名,则取指定sheet中的内容 否则默认指向第1个sheet - Sheet sheet = StringUtils.isNotEmpty(sheetName) ? wb.getSheet(sheetName) : wb.getSheetAt(0); - if (sheet == null) - { - throw new IOException("文件sheet不存在"); - } - boolean isXSSFWorkbook = !(wb instanceof HSSFWorkbook); - Map pictures; - if (isXSSFWorkbook) - { - pictures = getSheetPictures07((XSSFSheet) sheet, (XSSFWorkbook) wb); - } - else - { - pictures = getSheetPictures03((HSSFSheet) sheet, (HSSFWorkbook) wb); - } - // 获取最后一个非空行的行下标,比如总行数为n,则返回的为n-1 - int rows = sheet.getLastRowNum(); - - if (rows > 0) - { - // 定义一个map用于存放excel列的序号和field. - Map cellMap = new HashMap(); - // 获取表头 - Row heard = sheet.getRow(titleNum); - for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++) - { - Cell cell = heard.getCell(i); - if (StringUtils.isNotNull(cell)) - { - String value = this.getCellValue(heard, i).toString(); - cellMap.put(value, i); - } - else - { - cellMap.put(null, i); - } - } - // 有数据时才处理 得到类的所有field. - List fields = this.getFields(); - Map fieldsMap = new HashMap(); - for (Object[] objects : fields) - { - Excel attr = (Excel) objects[1]; - Integer column = cellMap.get(attr.name()); - if (column != null) - { - fieldsMap.put(column, objects); - } - } - for (int i = titleNum + 1; i <= rows; i++) - { - // 从第2行开始取数据,默认第一行是表头. - Row row = sheet.getRow(i); - // 判断当前行是否是空行 - if (isRowEmpty(row)) - { - continue; - } - T entity = null; - for (Map.Entry entry : fieldsMap.entrySet()) - { - Object val = this.getCellValue(row, entry.getKey()); - - // 如果不存在实例则新建. - entity = (entity == null ? clazz.newInstance() : entity); - // 从map中得到对应列的field. - Field field = (Field) entry.getValue()[0]; - Excel attr = (Excel) entry.getValue()[1]; - // 取得类型,并根据对象类型设置值. - Class fieldType = field.getType(); - if (String.class == fieldType) - { - String s = Convert.toStr(val); - if (StringUtils.endsWith(s, ".0")) - { - val = StringUtils.substringBefore(s, ".0"); - } - else - { - String dateFormat = field.getAnnotation(Excel.class).dateFormat(); - if (StringUtils.isNotEmpty(dateFormat)) - { - val = DateUtils.parseDateToStr(dateFormat, (Date) val); - } - else - { - val = Convert.toStr(val); - } - } - } - else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val))) - { - val = Convert.toInt(val); - } - else if (Long.TYPE == fieldType || Long.class == fieldType) - { - val = Convert.toLong(val); - } - else if (Double.TYPE == fieldType || Double.class == fieldType) - { - val = Convert.toDouble(val); - } - else if (Float.TYPE == fieldType || Float.class == fieldType) - { - val = Convert.toFloat(val); - } - else if (BigDecimal.class == fieldType) - { - val = Convert.toBigDecimal(val); - } - else if (Date.class == fieldType) - { - if (val instanceof String) - { - val = DateUtils.parseDate(val); - } - else if (val instanceof Double) - { - val = DateUtil.getJavaDate((Double) val); - } - } - else if (Boolean.TYPE == fieldType || Boolean.class == fieldType) - { - val = Convert.toBool(val, false); - } - if (StringUtils.isNotNull(fieldType)) - { - String propertyName = field.getName(); - if (StringUtils.isNotEmpty(attr.targetAttr())) - { - propertyName = field.getName() + "." + attr.targetAttr(); - } - else if (StringUtils.isNotEmpty(attr.readConverterExp())) - { - val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator()); - } - else if (StringUtils.isNotEmpty(attr.dictType())) - { - val = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator()); - } - else if (!attr.handler().equals(ExcelHandlerAdapter.class)) - { - val = dataFormatHandlerAdapter(val, attr); - } - else if (ColumnType.IMAGE == attr.cellType() && StringUtils.isNotEmpty(pictures)) - { - PictureData image = pictures.get(row.getRowNum() + "_" + entry.getKey()); - if (image == null) - { - val = ""; - } - else - { - byte[] data = image.getData(); - val = FileUtils.writeImportBytes(data); - } - } - ReflectUtils.invokeSetter(entity, propertyName, val); - } - } - list.add(entity); - } - } - return list; - } - - /** - * 对list数据源将其里面的数据导入到excel表单 - * - * @param list 导出数据集合 - * @param sheetName 工作表的名称 - * @return 结果 - */ - public AjaxResult exportExcel(List list, String sheetName) - { - return exportExcel(list, sheetName, StringUtils.EMPTY); - } - - /** - * 对list数据源将其里面的数据导入到excel表单 - * - * @param list 导出数据集合 - * @param sheetName 工作表的名称 - * @param title 标题 - * @return 结果 - */ - public AjaxResult exportExcel(List list, String sheetName, String title) - { - this.init(list, sheetName, title, Type.EXPORT); - return exportExcel(); - } - - /** - * 对list数据源将其里面的数据导入到excel表单 - * - * @param response 返回数据 - * @param list 导出数据集合 - * @param sheetName 工作表的名称 - * @return 结果 - * @throws IOException - */ - public void exportExcel(HttpServletResponse response, List list, String sheetName) - { - exportExcel(response, list, sheetName, StringUtils.EMPTY); - } - - /** - * 对list数据源将其里面的数据导入到excel表单 - * - * @param response 返回数据 - * @param list 导出数据集合 - * @param sheetName 工作表的名称 - * @param title 标题 - * @return 结果 - * @throws IOException - */ - public void exportExcel(HttpServletResponse response, List list, String sheetName, String title) - { - response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); - response.setCharacterEncoding("utf-8"); - this.init(list, sheetName, title, Type.EXPORT); - exportExcel(response); - } - - /** - * 对list数据源将其里面的数据导入到excel表单 - * - * @param sheetName 工作表的名称 - * @return 结果 - */ - public AjaxResult importTemplateExcel(String sheetName) - { - return importTemplateExcel(sheetName, StringUtils.EMPTY); - } - - /** - * 对list数据源将其里面的数据导入到excel表单 - * - * @param sheetName 工作表的名称 - * @param title 标题 - * @return 结果 - */ - public AjaxResult importTemplateExcel(String sheetName, String title) - { - this.init(null, sheetName, title, Type.IMPORT); - return exportExcel(); - } - - /** - * 对list数据源将其里面的数据导入到excel表单 - * - * @param sheetName 工作表的名称 - * @return 结果 - */ - public void importTemplateExcel(HttpServletResponse response, String sheetName) - { - importTemplateExcel(response, sheetName, StringUtils.EMPTY); - } - - /** - * 对list数据源将其里面的数据导入到excel表单 - * - * @param sheetName 工作表的名称 - * @param title 标题 - * @return 结果 - */ - public void importTemplateExcel(HttpServletResponse response, String sheetName, String title) - { - response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); - response.setCharacterEncoding("utf-8"); - this.init(null, sheetName, title, Type.IMPORT); - exportExcel(response); - } - - /** - * 对list数据源将其里面的数据导入到excel表单 - * - * @return 结果 - */ - public void exportExcel(HttpServletResponse response) - { - try - { - writeSheet(); - wb.write(response.getOutputStream()); - } - catch (Exception e) - { - log.error("导出Excel异常{}", e.getMessage()); - } - finally - { - IOUtils.closeQuietly(wb); - } - } - - /** - * 对list数据源将其里面的数据导入到excel表单 - * - * @return 结果 - */ - public AjaxResult exportExcel() - { - OutputStream out = null; - try - { - writeSheet(); - String filename = encodingFilename(sheetName); - out = new FileOutputStream(getAbsoluteFile(filename)); - wb.write(out); - return AjaxResult.success(filename); - } - catch (Exception e) - { - log.error("导出Excel异常{}", e.getMessage()); - throw new UtilException("导出Excel失败,请联系网站管理员!"); - } - finally - { - IOUtils.closeQuietly(wb); - IOUtils.closeQuietly(out); - } - } - - /** - * 创建写入数据到Sheet - */ - public void writeSheet() - { - // 取出一共有多少个sheet. - int sheetNo = Math.max(1, (int) Math.ceil(list.size() * 1.0 / sheetSize)); - for (int index = 0; index < sheetNo; index++) - { - createSheet(sheetNo, index); - - // 产生一行 - Row row = sheet.createRow(rownum); - int column = 0; - // 写入各个字段的列头名称 - for (Object[] os : fields) - { - Excel excel = (Excel) os[1]; - this.createCell(excel, row, column++); - } - if (Type.EXPORT.equals(type)) - { - fillExcelData(index, row); - addStatisticsRow(); - } - } - } - - /** - * 填充excel数据 - * - * @param index 序号 - * @param row 单元格行 - */ - public void fillExcelData(int index, Row row) - { - int startNo = index * sheetSize; - int endNo = Math.min(startNo + sheetSize, list.size()); - for (int i = startNo; i < endNo; i++) - { - row = sheet.createRow(i + 1 + rownum - startNo); - // 得到导出对象. - T vo = (T) list.get(i); - int column = 0; - for (Object[] os : fields) - { - Field field = (Field) os[0]; - Excel excel = (Excel) os[1]; - this.addCell(excel, row, vo, field, column++); - } - } - } - - /** - * 创建表格样式 - * - * @param wb 工作薄对象 - * @return 样式列表 - */ - private Map createStyles(Workbook wb) - { - // 写入各条记录,每条记录对应excel表中的一行 - Map styles = new HashMap(); - CellStyle style = wb.createCellStyle(); - style.setAlignment(HorizontalAlignment.CENTER); - style.setVerticalAlignment(VerticalAlignment.CENTER); - Font titleFont = wb.createFont(); - titleFont.setFontName("Arial"); - titleFont.setFontHeightInPoints((short) 16); - titleFont.setBold(true); - style.setFont(titleFont); - styles.put("title", style); - - style = wb.createCellStyle(); - style.setAlignment(HorizontalAlignment.CENTER); - style.setVerticalAlignment(VerticalAlignment.CENTER); - style.setBorderRight(BorderStyle.THIN); - style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); - style.setBorderLeft(BorderStyle.THIN); - style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); - style.setBorderTop(BorderStyle.THIN); - style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); - style.setBorderBottom(BorderStyle.THIN); - style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); - Font dataFont = wb.createFont(); - dataFont.setFontName("Arial"); - dataFont.setFontHeightInPoints((short) 10); - style.setFont(dataFont); - styles.put("data", style); - - style = wb.createCellStyle(); - style.cloneStyleFrom(styles.get("data")); - style.setAlignment(HorizontalAlignment.CENTER); - style.setVerticalAlignment(VerticalAlignment.CENTER); - style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex()); - style.setFillPattern(FillPatternType.SOLID_FOREGROUND); - Font headerFont = wb.createFont(); - headerFont.setFontName("Arial"); - headerFont.setFontHeightInPoints((short) 10); - headerFont.setBold(true); - headerFont.setColor(IndexedColors.WHITE.getIndex()); - style.setFont(headerFont); - styles.put("header", style); - - style = wb.createCellStyle(); - style.setAlignment(HorizontalAlignment.CENTER); - style.setVerticalAlignment(VerticalAlignment.CENTER); - Font totalFont = wb.createFont(); - totalFont.setFontName("Arial"); - totalFont.setFontHeightInPoints((short) 10); - style.setFont(totalFont); - styles.put("total", style); - - style = wb.createCellStyle(); - style.cloneStyleFrom(styles.get("data")); - style.setAlignment(HorizontalAlignment.LEFT); - styles.put("data1", style); - - style = wb.createCellStyle(); - style.cloneStyleFrom(styles.get("data")); - style.setAlignment(HorizontalAlignment.CENTER); - styles.put("data2", style); - - style = wb.createCellStyle(); - style.cloneStyleFrom(styles.get("data")); - style.setAlignment(HorizontalAlignment.RIGHT); - styles.put("data3", style); - - return styles; - } - - /** - * 创建单元格 - */ - public Cell createCell(Excel attr, Row row, int column) - { - // 创建列 - Cell cell = row.createCell(column); - // 写入列信息 - cell.setCellValue(attr.name()); - setDataValidation(attr, row, column); - cell.setCellStyle(styles.get("header")); - return cell; - } - - /** - * 设置单元格信息 - * - * @param value 单元格值 - * @param attr 注解相关 - * @param cell 单元格信息 - */ - public void setCellVo(Object value, Excel attr, Cell cell) - { - if (ColumnType.STRING == attr.cellType()) - { - cell.setCellValue(StringUtils.isNull(value) ? attr.defaultValue() : value + attr.suffix()); - } - else if (ColumnType.NUMERIC == attr.cellType()) - { - if (StringUtils.isNotNull(value)) - { - cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value)); - } - } - else if (ColumnType.IMAGE == attr.cellType()) - { - ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1), cell.getRow().getRowNum() + 1); - String imagePath = Convert.toStr(value); - if (StringUtils.isNotEmpty(imagePath)) - { - byte[] data = ImageUtils.getImage(imagePath); - getDrawingPatriarch(cell.getSheet()).createPicture(anchor, - cell.getSheet().getWorkbook().addPicture(data, getImageType(data))); - } - } - } - - /** - * 获取画布 - */ - public static Drawing getDrawingPatriarch(Sheet sheet) - { - if (sheet.getDrawingPatriarch() == null) - { - sheet.createDrawingPatriarch(); - } - return sheet.getDrawingPatriarch(); - } - - /** - * 获取图片类型,设置图片插入类型 - */ - public int getImageType(byte[] value) - { - String type = FileTypeUtils.getFileExtendName(value); - if ("JPG".equalsIgnoreCase(type)) - { - return Workbook.PICTURE_TYPE_JPEG; - } - else if ("PNG".equalsIgnoreCase(type)) - { - return Workbook.PICTURE_TYPE_PNG; - } - return Workbook.PICTURE_TYPE_JPEG; - } - - /** - * 创建表格样式 - */ - public void setDataValidation(Excel attr, Row row, int column) - { - if (attr.name().indexOf("注:") >= 0) - { - sheet.setColumnWidth(column, 6000); - } - else - { - // 设置列宽 - sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256)); - } - // 如果设置了提示信息则鼠标放上去提示. - if (StringUtils.isNotEmpty(attr.prompt())) - { - // 这里默认设了2-101列提示. - setXSSFPrompt(sheet, "", attr.prompt(), 1, 100, column, column); - } - // 如果设置了combo属性则本列只能选择不能输入 - if (attr.combo().length > 0) - { - // 这里默认设了2-101列只能选择不能输入. - setXSSFValidation(sheet, attr.combo(), 1, 100, column, column); - } - } - - /** - * 添加单元格 - */ - public Cell addCell(Excel attr, Row row, T vo, Field field, int column) - { - Cell cell = null; - try - { - // 设置行高 - row.setHeight(maxHeight); - // 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列. - if (attr.isExport()) - { - // 创建cell - cell = row.createCell(column); - int align = attr.align().value(); - cell.setCellStyle(styles.get("data" + (align >= 1 && align <= 3 ? align : ""))); - - // 用于读取对象中的属性 - Object value = getTargetValue(vo, field, attr); - String dateFormat = attr.dateFormat(); - String readConverterExp = attr.readConverterExp(); - String separator = attr.separator(); - String dictType = attr.dictType(); - if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value)) - { - cell.setCellValue(DateUtils.parseDateToStr(dateFormat, (Date) value)); - } - else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value)) - { - cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator)); - } - else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value)) - { - cell.setCellValue(convertDictByExp(Convert.toStr(value), dictType, separator)); - } - else if (value instanceof BigDecimal && -1 != attr.scale()) - { - cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).toString()); - } - else if (!attr.handler().equals(ExcelHandlerAdapter.class)) - { - cell.setCellValue(dataFormatHandlerAdapter(value, attr)); - } - else - { - // 设置列类型 - setCellVo(value, attr, cell); - } - addStatisticsData(column, Convert.toStr(value), attr); - } - } - catch (Exception e) - { - log.error("导出Excel失败{}", e); - } - return cell; - } - - /** - * 设置 POI XSSFSheet 单元格提示 - * - * @param sheet 表单 - * @param promptTitle 提示标题 - * @param promptContent 提示内容 - * @param firstRow 开始行 - * @param endRow 结束行 - * @param firstCol 开始列 - * @param endCol 结束列 - */ - public void setXSSFPrompt(Sheet sheet, String promptTitle, String promptContent, int firstRow, int endRow, - int firstCol, int endCol) - { - DataValidationHelper helper = sheet.getDataValidationHelper(); - DataValidationConstraint constraint = helper.createCustomConstraint("DD1"); - CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); - DataValidation dataValidation = helper.createValidation(constraint, regions); - dataValidation.createPromptBox(promptTitle, promptContent); - dataValidation.setShowPromptBox(true); - sheet.addValidationData(dataValidation); - } - - /** - * 设置某些列的值只能输入预制的数据,显示下拉框. - * - * @param sheet 要设置的sheet. - * @param textlist 下拉框显示的内容 - * @param firstRow 开始行 - * @param endRow 结束行 - * @param firstCol 开始列 - * @param endCol 结束列 - * @return 设置好的sheet. - */ - public void setXSSFValidation(Sheet sheet, String[] textlist, int firstRow, int endRow, int firstCol, int endCol) - { - DataValidationHelper helper = sheet.getDataValidationHelper(); - // 加载下拉列表内容 - DataValidationConstraint constraint = helper.createExplicitListConstraint(textlist); - // 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列 - CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); - // 数据有效性对象 - DataValidation dataValidation = helper.createValidation(constraint, regions); - // 处理Excel兼容性问题 - if (dataValidation instanceof XSSFDataValidation) - { - dataValidation.setSuppressDropDownArrow(true); - dataValidation.setShowErrorBox(true); - } - else - { - dataValidation.setSuppressDropDownArrow(false); - } - - sheet.addValidationData(dataValidation); - } - - /** - * 解析导出值 0=男,1=女,2=未知 - * - * @param propertyValue 参数值 - * @param converterExp 翻译注解 - * @param separator 分隔符 - * @return 解析后值 - */ - public static String convertByExp(String propertyValue, String converterExp, String separator) - { - StringBuilder propertyString = new StringBuilder(); - String[] convertSource = converterExp.split(","); - for (String item : convertSource) - { - String[] itemArray = item.split("="); - if (StringUtils.containsAny(separator, propertyValue)) - { - for (String value : propertyValue.split(separator)) - { - if (itemArray[0].equals(value)) - { - propertyString.append(itemArray[1] + separator); - break; - } - } - } - else - { - if (itemArray[0].equals(propertyValue)) - { - return itemArray[1]; - } - } - } - return StringUtils.stripEnd(propertyString.toString(), separator); - } - - /** - * 反向解析值 男=0,女=1,未知=2 - * - * @param propertyValue 参数值 - * @param converterExp 翻译注解 - * @param separator 分隔符 - * @return 解析后值 - */ - public static String reverseByExp(String propertyValue, String converterExp, String separator) - { - StringBuilder propertyString = new StringBuilder(); - String[] convertSource = converterExp.split(","); - for (String item : convertSource) - { - String[] itemArray = item.split("="); - if (StringUtils.containsAny(separator, propertyValue)) - { - for (String value : propertyValue.split(separator)) - { - if (itemArray[1].equals(value)) - { - propertyString.append(itemArray[0] + separator); - break; - } - } - } - else - { - if (itemArray[1].equals(propertyValue)) - { - return itemArray[0]; - } - } - } - return StringUtils.stripEnd(propertyString.toString(), separator); - } - - /** - * 解析字典值 - * - * @param dictValue 字典值 - * @param dictType 字典类型 - * @param separator 分隔符 - * @return 字典标签 - */ - public static String convertDictByExp(String dictValue, String dictType, String separator) - { - return DictUtils.getDictLabel(dictType, dictValue, separator); - } - - /** - * 反向解析值字典值 - * - * @param dictLabel 字典标签 - * @param dictType 字典类型 - * @param separator 分隔符 - * @return 字典值 - */ - public static String reverseDictByExp(String dictLabel, String dictType, String separator) - { - return DictUtils.getDictValue(dictType, dictLabel, separator); - } - - /** - * 数据处理器 - * - * @param value 数据值 - * @param excel 数据注解 - * @return - */ - public String dataFormatHandlerAdapter(Object value, Excel excel) - { - try - { - Object instance = excel.handler().newInstance(); - Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class }); - value = formatMethod.invoke(instance, value, excel.args()); - } - catch (Exception e) - { - log.error("不能格式化数据 " + excel.handler(), e.getMessage()); - } - return Convert.toStr(value); - } - - /** - * 合计统计信息 - */ - private void addStatisticsData(Integer index, String text, Excel entity) - { - if (entity != null && entity.isStatistics()) - { - Double temp = 0D; - if (!statistics.containsKey(index)) - { - statistics.put(index, temp); - } - try - { - temp = Double.valueOf(text); - } - catch (NumberFormatException e) - { - } - statistics.put(index, statistics.get(index) + temp); - } - } - - /** - * 创建统计行 - */ - public void addStatisticsRow() - { - if (statistics.size() > 0) - { - Row row = sheet.createRow(sheet.getLastRowNum() + 1); - Set keys = statistics.keySet(); - Cell cell = row.createCell(0); - cell.setCellStyle(styles.get("total")); - cell.setCellValue("合计"); - - for (Integer key : keys) - { - cell = row.createCell(key); - cell.setCellStyle(styles.get("total")); - cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key))); - } - statistics.clear(); - } - } - - /** - * 编码文件名 - */ - public String encodingFilename(String filename) - { - filename = UUID.randomUUID().toString() + "_" + filename + ".xlsx"; - return filename; - } - - /** - * 获取下载路径 - * - * @param filename 文件名称 - */ - public String getAbsoluteFile(String filename) - { - String downloadPath = RuoYiConfig.getDownloadPath() + filename; - File desc = new File(downloadPath); - if (!desc.getParentFile().exists()) - { - desc.getParentFile().mkdirs(); - } - return downloadPath; - } - - /** - * 获取bean中的属性值 - * - * @param vo 实体对象 - * @param field 字段 - * @param excel 注解 - * @return 最终的属性值 - * @throws Exception - */ - private Object getTargetValue(T vo, Field field, Excel excel) throws Exception - { - Object o = field.get(vo); - if (StringUtils.isNotEmpty(excel.targetAttr())) - { - String target = excel.targetAttr(); - if (target.indexOf(".") > -1) - { - String[] targets = target.split("[.]"); - for (String name : targets) - { - o = getValue(o, name); - } - } - else - { - o = getValue(o, target); - } - } - return o; - } - - /** - * 以类的属性的get方法方法形式获取值 - * - * @param o - * @param name - * @return value - * @throws Exception - */ - private Object getValue(Object o, String name) throws Exception - { - if (StringUtils.isNotNull(o) && StringUtils.isNotEmpty(name)) - { - Class clazz = o.getClass(); - Field field = clazz.getDeclaredField(name); - field.setAccessible(true); - o = field.get(o); - } - return o; - } - - /** - * 得到所有定义字段 - */ - private void createExcelField() - { - this.fields = getFields(); - this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList()); - this.maxHeight = getRowHeight(); - } - - /** - * 获取字段注解信息 - */ - public List getFields() - { - List fields = new ArrayList(); - List tempFields = new ArrayList<>(); - tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields())); - tempFields.addAll(Arrays.asList(clazz.getDeclaredFields())); - for (Field field : tempFields) - { - // 单注解 - if (field.isAnnotationPresent(Excel.class)) - { - Excel attr = field.getAnnotation(Excel.class); - if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) - { - field.setAccessible(true); - fields.add(new Object[] { field, attr }); - } - } - - // 多注解 - if (field.isAnnotationPresent(Excels.class)) - { - Excels attrs = field.getAnnotation(Excels.class); - Excel[] excels = attrs.value(); - for (Excel attr : excels) - { - if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) - { - field.setAccessible(true); - fields.add(new Object[] { field, attr }); - } - } - } - } - return fields; - } - - /** - * 根据注解获取最大行高 - */ - public short getRowHeight() - { - double maxHeight = 0; - for (Object[] os : this.fields) - { - Excel excel = (Excel) os[1]; - maxHeight = maxHeight > excel.height() ? maxHeight : excel.height(); - } - return (short) (maxHeight * 20); - } - - /** - * 创建一个工作簿 - */ - public void createWorkbook() - { - this.wb = new SXSSFWorkbook(500); - this.sheet = wb.createSheet(); - wb.setSheetName(0, sheetName); - this.styles = createStyles(wb); - } - - /** - * 创建工作表 - * - * @param sheetNo sheet数量 - * @param index 序号 - */ - public void createSheet(int sheetNo, int index) - { - // 设置工作表的名称. - if (sheetNo > 1 && index > 0) - { - this.sheet = wb.createSheet(); - this.createTitle(); - wb.setSheetName(index, sheetName + index); - } - } - - /** - * 获取单元格值 - * - * @param row 获取的行 - * @param column 获取单元格列号 - * @return 单元格值 - */ - public Object getCellValue(Row row, int column) - { - if (row == null) - { - return row; - } - Object val = ""; - try - { - Cell cell = row.getCell(column); - if (StringUtils.isNotNull(cell)) - { - if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA) - { - val = cell.getNumericCellValue(); - if (DateUtil.isCellDateFormatted(cell)) - { - val = DateUtil.getJavaDate((Double) val); // POI Excel 日期格式转换 - } - else - { - if ((Double) val % 1 != 0) - { - val = new BigDecimal(val.toString()); - } - else - { - val = new DecimalFormat("0").format(val); - } - } - } - else if (cell.getCellType() == CellType.STRING) - { - val = cell.getStringCellValue(); - } - else if (cell.getCellType() == CellType.BOOLEAN) - { - val = cell.getBooleanCellValue(); - } - else if (cell.getCellType() == CellType.ERROR) - { - val = cell.getErrorCellValue(); - } - - } - } - catch (Exception e) - { - return val; - } - return val; - } - - /** - * 判断是否是空行 - * - * @param row 判断的行 - * @return - */ - private boolean isRowEmpty(Row row) - { - if (row == null) - { - return true; - } - for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) - { - Cell cell = row.getCell(i); - if (cell != null && cell.getCellType() != CellType.BLANK) - { - return false; - } - } - return true; - } - - /** - * 获取Excel2003图片 - * - * @param sheet 当前sheet对象 - * @param workbook 工作簿对象 - * @return Map key:图片单元格索引(1_1)String,value:图片流PictureData - */ - public static Map getSheetPictures03(HSSFSheet sheet, HSSFWorkbook workbook) - { - Map sheetIndexPicMap = new HashMap(); - List pictures = workbook.getAllPictures(); - if (!pictures.isEmpty()) - { - for (HSSFShape shape : sheet.getDrawingPatriarch().getChildren()) - { - HSSFClientAnchor anchor = (HSSFClientAnchor) shape.getAnchor(); - if (shape instanceof HSSFPicture) - { - HSSFPicture pic = (HSSFPicture) shape; - int pictureIndex = pic.getPictureIndex() - 1; - HSSFPictureData picData = pictures.get(pictureIndex); - String picIndex = String.valueOf(anchor.getRow1()) + "_" + String.valueOf(anchor.getCol1()); - sheetIndexPicMap.put(picIndex, picData); - } - } - return sheetIndexPicMap; - } - else - { - return sheetIndexPicMap; - } - } - - /** - * 获取Excel2007图片 - * - * @param sheet 当前sheet对象 - * @param workbook 工作簿对象 - * @return Map key:图片单元格索引(1_1)String,value:图片流PictureData - */ - public static Map getSheetPictures07(XSSFSheet sheet, XSSFWorkbook workbook) - { - Map sheetIndexPicMap = new HashMap(); - for (POIXMLDocumentPart dr : sheet.getRelations()) - { - if (dr instanceof XSSFDrawing) - { - XSSFDrawing drawing = (XSSFDrawing) dr; - List shapes = drawing.getShapes(); - for (XSSFShape shape : shapes) - { - if (shape instanceof XSSFPicture) - { - XSSFPicture pic = (XSSFPicture) shape; - XSSFClientAnchor anchor = pic.getPreferredSize(); - CTMarker ctMarker = anchor.getFrom(); - String picIndex = ctMarker.getRow() + "_" + ctMarker.getCol(); - sheetIndexPicMap.put(picIndex, pic.getPictureData()); - } - } - } - } - return sheetIndexPicMap; - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java deleted file mode 100644 index b19953e0..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java +++ /dev/null @@ -1,410 +0,0 @@ -package com.ruoyi.common.utils.reflect; - -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.Date; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.Validate; -import org.apache.poi.ss.usermodel.DateUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import com.ruoyi.common.core.text.Convert; -import com.ruoyi.common.utils.DateUtils; - -/** - * 反射工具类. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数. - * - * @author ruoyi - */ -@SuppressWarnings("rawtypes") -public class ReflectUtils -{ - private static final String SETTER_PREFIX = "set"; - - private static final String GETTER_PREFIX = "get"; - - private static final String CGLIB_CLASS_SEPARATOR = "$$"; - - private static Logger logger = LoggerFactory.getLogger(ReflectUtils.class); - - /** - * 调用Getter方法. - * 支持多级,如:对象名.对象名.方法 - */ - @SuppressWarnings("unchecked") - public static E invokeGetter(Object obj, String propertyName) - { - Object object = obj; - for (String name : StringUtils.split(propertyName, ".")) - { - String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name); - object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {}); - } - return (E) object; - } - - /** - * 调用Setter方法, 仅匹配方法名。 - * 支持多级,如:对象名.对象名.方法 - */ - public static void invokeSetter(Object obj, String propertyName, E value) - { - Object object = obj; - String[] names = StringUtils.split(propertyName, "."); - for (int i = 0; i < names.length; i++) - { - if (i < names.length - 1) - { - String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]); - object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {}); - } - else - { - String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]); - invokeMethodByName(object, setterMethodName, new Object[] { value }); - } - } - } - - /** - * 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数. - */ - @SuppressWarnings("unchecked") - public static E getFieldValue(final Object obj, final String fieldName) - { - Field field = getAccessibleField(obj, fieldName); - if (field == null) - { - logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); - return null; - } - E result = null; - try - { - result = (E) field.get(obj); - } - catch (IllegalAccessException e) - { - logger.error("不可能抛出的异常{}", e.getMessage()); - } - return result; - } - - /** - * 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数. - */ - public static void setFieldValue(final Object obj, final String fieldName, final E value) - { - Field field = getAccessibleField(obj, fieldName); - if (field == null) - { - // throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); - logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); - return; - } - try - { - field.set(obj, value); - } - catch (IllegalAccessException e) - { - logger.error("不可能抛出的异常: {}", e.getMessage()); - } - } - - /** - * 直接调用对象方法, 无视private/protected修饰符. - * 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用. - * 同时匹配方法名+参数类型, - */ - @SuppressWarnings("unchecked") - public static E invokeMethod(final Object obj, final String methodName, final Class[] parameterTypes, - final Object[] args) - { - if (obj == null || methodName == null) - { - return null; - } - Method method = getAccessibleMethod(obj, methodName, parameterTypes); - if (method == null) - { - logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 "); - return null; - } - try - { - return (E) method.invoke(obj, args); - } - catch (Exception e) - { - String msg = "method: " + method + ", obj: " + obj + ", args: " + args + ""; - throw convertReflectionExceptionToUnchecked(msg, e); - } - } - - /** - * 直接调用对象方法, 无视private/protected修饰符, - * 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用. - * 只匹配函数名,如果有多个同名函数调用第一个。 - */ - @SuppressWarnings("unchecked") - public static E invokeMethodByName(final Object obj, final String methodName, final Object[] args) - { - Method method = getAccessibleMethodByName(obj, methodName, args.length); - if (method == null) - { - // 如果为空不报错,直接返回空。 - logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 "); - return null; - } - try - { - // 类型转换(将参数数据类型转换为目标方法参数类型) - Class[] cs = method.getParameterTypes(); - for (int i = 0; i < cs.length; i++) - { - if (args[i] != null && !args[i].getClass().equals(cs[i])) - { - if (cs[i] == String.class) - { - args[i] = Convert.toStr(args[i]); - if (StringUtils.endsWith((String) args[i], ".0")) - { - args[i] = StringUtils.substringBefore((String) args[i], ".0"); - } - } - else if (cs[i] == Integer.class) - { - args[i] = Convert.toInt(args[i]); - } - else if (cs[i] == Long.class) - { - args[i] = Convert.toLong(args[i]); - } - else if (cs[i] == Double.class) - { - args[i] = Convert.toDouble(args[i]); - } - else if (cs[i] == Float.class) - { - args[i] = Convert.toFloat(args[i]); - } - else if (cs[i] == Date.class) - { - if (args[i] instanceof String) - { - args[i] = DateUtils.parseDate(args[i]); - } - else - { - args[i] = DateUtil.getJavaDate((Double) args[i]); - } - } - else if (cs[i] == boolean.class || cs[i] == Boolean.class) - { - args[i] = Convert.toBool(args[i]); - } - } - } - return (E) method.invoke(obj, args); - } - catch (Exception e) - { - String msg = "method: " + method + ", obj: " + obj + ", args: " + args + ""; - throw convertReflectionExceptionToUnchecked(msg, e); - } - } - - /** - * 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问. - * 如向上转型到Object仍无法找到, 返回null. - */ - public static Field getAccessibleField(final Object obj, final String fieldName) - { - // 为空不报错。直接返回 null - if (obj == null) - { - return null; - } - Validate.notBlank(fieldName, "fieldName can't be blank"); - for (Class superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) - { - try - { - Field field = superClass.getDeclaredField(fieldName); - makeAccessible(field); - return field; - } - catch (NoSuchFieldException e) - { - continue; - } - } - return null; - } - - /** - * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. - * 如向上转型到Object仍无法找到, 返回null. - * 匹配函数名+参数类型。 - * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args) - */ - public static Method getAccessibleMethod(final Object obj, final String methodName, - final Class... parameterTypes) - { - // 为空不报错。直接返回 null - if (obj == null) - { - return null; - } - Validate.notBlank(methodName, "methodName can't be blank"); - for (Class searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) - { - try - { - Method method = searchType.getDeclaredMethod(methodName, parameterTypes); - makeAccessible(method); - return method; - } - catch (NoSuchMethodException e) - { - continue; - } - } - return null; - } - - /** - * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. - * 如向上转型到Object仍无法找到, 返回null. - * 只匹配函数名。 - * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args) - */ - public static Method getAccessibleMethodByName(final Object obj, final String methodName, int argsNum) - { - // 为空不报错。直接返回 null - if (obj == null) - { - return null; - } - Validate.notBlank(methodName, "methodName can't be blank"); - for (Class searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) - { - Method[] methods = searchType.getDeclaredMethods(); - for (Method method : methods) - { - if (method.getName().equals(methodName) && method.getParameterTypes().length == argsNum) - { - makeAccessible(method); - return method; - } - } - } - return null; - } - - /** - * 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 - */ - public static void makeAccessible(Method method) - { - if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) - && !method.isAccessible()) - { - method.setAccessible(true); - } - } - - /** - * 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 - */ - public static void makeAccessible(Field field) - { - if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) - || Modifier.isFinal(field.getModifiers())) && !field.isAccessible()) - { - field.setAccessible(true); - } - } - - /** - * 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处 - * 如无法找到, 返回Object.class. - */ - @SuppressWarnings("unchecked") - public static Class getClassGenricType(final Class clazz) - { - return getClassGenricType(clazz, 0); - } - - /** - * 通过反射, 获得Class定义中声明的父类的泛型参数的类型. - * 如无法找到, 返回Object.class. - */ - public static Class getClassGenricType(final Class clazz, final int index) - { - Type genType = clazz.getGenericSuperclass(); - - if (!(genType instanceof ParameterizedType)) - { - logger.debug(clazz.getSimpleName() + "'s superclass not ParameterizedType"); - return Object.class; - } - - Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); - - if (index >= params.length || index < 0) - { - logger.debug("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: " - + params.length); - return Object.class; - } - if (!(params[index] instanceof Class)) - { - logger.debug(clazz.getSimpleName() + " not set the actual class on superclass generic parameter"); - return Object.class; - } - - return (Class) params[index]; - } - - public static Class getUserClass(Object instance) - { - if (instance == null) - { - throw new RuntimeException("Instance must not be null"); - } - Class clazz = instance.getClass(); - if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) - { - Class superClass = clazz.getSuperclass(); - if (superClass != null && !Object.class.equals(superClass)) - { - return superClass; - } - } - return clazz; - - } - - /** - * 将反射时的checked exception转换为unchecked exception. - */ - public static RuntimeException convertReflectionExceptionToUnchecked(String msg, Exception e) - { - if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException - || e instanceof NoSuchMethodException) - { - return new IllegalArgumentException(msg, e); - } - else if (e instanceof InvocationTargetException) - { - return new RuntimeException(msg, ((InvocationTargetException) e).getTargetException()); - } - return new RuntimeException(msg, e); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/sign/Base64.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/sign/Base64.java deleted file mode 100644 index ca1cd924..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/sign/Base64.java +++ /dev/null @@ -1,291 +0,0 @@ -package com.ruoyi.common.utils.sign; - -/** - * Base64工具类 - * - * @author ruoyi - */ -public final class Base64 -{ - static private final int BASELENGTH = 128; - static private final int LOOKUPLENGTH = 64; - static private final int TWENTYFOURBITGROUP = 24; - static private final int EIGHTBIT = 8; - static private final int SIXTEENBIT = 16; - static private final int FOURBYTE = 4; - static private final int SIGN = -128; - static private final char PAD = '='; - static final private byte[] base64Alphabet = new byte[BASELENGTH]; - static final private char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH]; - - static - { - for (int i = 0; i < BASELENGTH; ++i) - { - base64Alphabet[i] = -1; - } - for (int i = 'Z'; i >= 'A'; i--) - { - base64Alphabet[i] = (byte) (i - 'A'); - } - for (int i = 'z'; i >= 'a'; i--) - { - base64Alphabet[i] = (byte) (i - 'a' + 26); - } - - for (int i = '9'; i >= '0'; i--) - { - base64Alphabet[i] = (byte) (i - '0' + 52); - } - - base64Alphabet['+'] = 62; - base64Alphabet['/'] = 63; - - for (int i = 0; i <= 25; i++) - { - lookUpBase64Alphabet[i] = (char) ('A' + i); - } - - for (int i = 26, j = 0; i <= 51; i++, j++) - { - lookUpBase64Alphabet[i] = (char) ('a' + j); - } - - for (int i = 52, j = 0; i <= 61; i++, j++) - { - lookUpBase64Alphabet[i] = (char) ('0' + j); - } - lookUpBase64Alphabet[62] = (char) '+'; - lookUpBase64Alphabet[63] = (char) '/'; - } - - private static boolean isWhiteSpace(char octect) - { - return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9); - } - - private static boolean isPad(char octect) - { - return (octect == PAD); - } - - private static boolean isData(char octect) - { - return (octect < BASELENGTH && base64Alphabet[octect] != -1); - } - - /** - * Encodes hex octects into Base64 - * - * @param binaryData Array containing binaryData - * @return Encoded Base64 array - */ - public static String encode(byte[] binaryData) - { - if (binaryData == null) - { - return null; - } - - int lengthDataBits = binaryData.length * EIGHTBIT; - if (lengthDataBits == 0) - { - return ""; - } - - int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP; - int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP; - int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets; - char encodedData[] = null; - - encodedData = new char[numberQuartet * 4]; - - byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0; - - int encodedIndex = 0; - int dataIndex = 0; - - for (int i = 0; i < numberTriplets; i++) - { - b1 = binaryData[dataIndex++]; - b2 = binaryData[dataIndex++]; - b3 = binaryData[dataIndex++]; - - l = (byte) (b2 & 0x0f); - k = (byte) (b1 & 0x03); - - byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); - byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0); - byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc); - - encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; - encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)]; - encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3]; - encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f]; - } - - // form integral number of 6-bit groups - if (fewerThan24bits == EIGHTBIT) - { - b1 = binaryData[dataIndex]; - k = (byte) (b1 & 0x03); - byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); - encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; - encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4]; - encodedData[encodedIndex++] = PAD; - encodedData[encodedIndex++] = PAD; - } - else if (fewerThan24bits == SIXTEENBIT) - { - b1 = binaryData[dataIndex]; - b2 = binaryData[dataIndex + 1]; - l = (byte) (b2 & 0x0f); - k = (byte) (b1 & 0x03); - - byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); - byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0); - - encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; - encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)]; - encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2]; - encodedData[encodedIndex++] = PAD; - } - return new String(encodedData); - } - - /** - * Decodes Base64 data into octects - * - * @param encoded string containing Base64 data - * @return Array containind decoded data. - */ - public static byte[] decode(String encoded) - { - if (encoded == null) - { - return null; - } - - char[] base64Data = encoded.toCharArray(); - // remove white spaces - int len = removeWhiteSpace(base64Data); - - if (len % FOURBYTE != 0) - { - return null;// should be divisible by four - } - - int numberQuadruple = (len / FOURBYTE); - - if (numberQuadruple == 0) - { - return new byte[0]; - } - - byte decodedData[] = null; - byte b1 = 0, b2 = 0, b3 = 0, b4 = 0; - char d1 = 0, d2 = 0, d3 = 0, d4 = 0; - - int i = 0; - int encodedIndex = 0; - int dataIndex = 0; - decodedData = new byte[(numberQuadruple) * 3]; - - for (; i < numberQuadruple - 1; i++) - { - - if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++])) - || !isData((d3 = base64Data[dataIndex++])) || !isData((d4 = base64Data[dataIndex++]))) - { - return null; - } // if found "no data" just return null - - b1 = base64Alphabet[d1]; - b2 = base64Alphabet[d2]; - b3 = base64Alphabet[d3]; - b4 = base64Alphabet[d4]; - - decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); - decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); - decodedData[encodedIndex++] = (byte) (b3 << 6 | b4); - } - - if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))) - { - return null;// if found "no data" just return null - } - - b1 = base64Alphabet[d1]; - b2 = base64Alphabet[d2]; - - d3 = base64Data[dataIndex++]; - d4 = base64Data[dataIndex++]; - if (!isData((d3)) || !isData((d4))) - {// Check if they are PAD characters - if (isPad(d3) && isPad(d4)) - { - if ((b2 & 0xf) != 0)// last 4 bits should be zero - { - return null; - } - byte[] tmp = new byte[i * 3 + 1]; - System.arraycopy(decodedData, 0, tmp, 0, i * 3); - tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); - return tmp; - } - else if (!isPad(d3) && isPad(d4)) - { - b3 = base64Alphabet[d3]; - if ((b3 & 0x3) != 0)// last 2 bits should be zero - { - return null; - } - byte[] tmp = new byte[i * 3 + 2]; - System.arraycopy(decodedData, 0, tmp, 0, i * 3); - tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); - tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); - return tmp; - } - else - { - return null; - } - } - else - { // No PAD e.g 3cQl - b3 = base64Alphabet[d3]; - b4 = base64Alphabet[d4]; - decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); - decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); - decodedData[encodedIndex++] = (byte) (b3 << 6 | b4); - - } - return decodedData; - } - - /** - * remove WhiteSpace from MIME containing encoded Base64 data. - * - * @param data the byte array of base64 data (with WS) - * @return the new length - */ - private static int removeWhiteSpace(char[] data) - { - if (data == null) - { - return 0; - } - - // count characters that's not whitespace - int newSize = 0; - int len = data.length; - for (int i = 0; i < len; i++) - { - if (!isWhiteSpace(data[i])) - { - data[newSize++] = data[i]; - } - } - return newSize; - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java deleted file mode 100644 index de77ee82..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.ruoyi.common.utils.sign; - -import java.security.MessageDigest; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Md5加密方法 - * - * @author ruoyi - */ -public class Md5Utils -{ - private static final Logger log = LoggerFactory.getLogger(Md5Utils.class); - - private static byte[] md5(String s) - { - MessageDigest algorithm; - try - { - algorithm = MessageDigest.getInstance("MD5"); - algorithm.reset(); - algorithm.update(s.getBytes("UTF-8")); - byte[] messageDigest = algorithm.digest(); - return messageDigest; - } - catch (Exception e) - { - log.error("MD5 Error...", e); - } - return null; - } - - private static final String toHex(byte hash[]) - { - if (hash == null) - { - return null; - } - StringBuffer buf = new StringBuffer(hash.length * 2); - int i; - - for (i = 0; i < hash.length; i++) - { - if ((hash[i] & 0xff) < 0x10) - { - buf.append("0"); - } - buf.append(Long.toString(hash[i] & 0xff, 16)); - } - return buf.toString(); - } - - public static String hash(String s) - { - try - { - return new String(toHex(md5(s)).getBytes("UTF-8"), "UTF-8"); - } - catch (Exception e) - { - log.error("not supported charset...{}", e); - return s; - } - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java deleted file mode 100644 index 9993b98f..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java +++ /dev/null @@ -1,146 +0,0 @@ -package com.ruoyi.common.utils.spring; - -import org.springframework.aop.framework.AopContext; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.NoSuchBeanDefinitionException; -import org.springframework.beans.factory.config.BeanFactoryPostProcessor; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.stereotype.Component; -import com.ruoyi.common.utils.StringUtils; - -/** - * spring工具类 方便在非spring管理环境中获取bean - * - * @author ruoyi - */ -@Component -public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware -{ - /** Spring应用上下文环境 */ - private static ConfigurableListableBeanFactory beanFactory; - - private static ApplicationContext applicationContext; - - @Override - public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException - { - SpringUtils.beanFactory = beanFactory; - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException - { - SpringUtils.applicationContext = applicationContext; - } - - /** - * 获取对象 - * - * @param name - * @return Object 一个以所给名字注册的bean的实例 - * @throws org.springframework.beans.BeansException - * - */ - @SuppressWarnings("unchecked") - public static T getBean(String name) throws BeansException - { - return (T) beanFactory.getBean(name); - } - - /** - * 获取类型为requiredType的对象 - * - * @param clz - * @return - * @throws org.springframework.beans.BeansException - * - */ - public static T getBean(Class clz) throws BeansException - { - T result = (T) beanFactory.getBean(clz); - return result; - } - - /** - * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true - * - * @param name - * @return boolean - */ - public static boolean containsBean(String name) - { - return beanFactory.containsBean(name); - } - - /** - * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException) - * - * @param name - * @return boolean - * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException - * - */ - public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException - { - return beanFactory.isSingleton(name); - } - - /** - * @param name - * @return Class 注册对象的类型 - * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException - * - */ - public static Class getType(String name) throws NoSuchBeanDefinitionException - { - return beanFactory.getType(name); - } - - /** - * 如果给定的bean名字在bean定义中有别名,则返回这些别名 - * - * @param name - * @return - * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException - * - */ - public static String[] getAliases(String name) throws NoSuchBeanDefinitionException - { - return beanFactory.getAliases(name); - } - - /** - * 获取aop代理对象 - * - * @param invoker - * @return - */ - @SuppressWarnings("unchecked") - public static T getAopProxy(T invoker) - { - return (T) AopContext.currentProxy(); - } - - /** - * 获取当前的环境配置,无配置返回null - * - * @return 当前的环境配置 - */ - public static String[] getActiveProfiles() - { - return applicationContext.getEnvironment().getActiveProfiles(); - } - - /** - * 获取当前的环境配置,当有多个环境配置时,只获取第一个 - * - * @return 当前的环境配置 - */ - public static String getActiveProfile() - { - final String[] activeProfiles = getActiveProfiles(); - return StringUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null; - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java deleted file mode 100644 index a1989463..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.ruoyi.common.utils.sql; - -import com.ruoyi.common.exception.UtilException; -import com.ruoyi.common.utils.StringUtils; - -/** - * sql操作工具类 - * - * @author ruoyi - */ -public class SqlUtil -{ - /** - * 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序) - */ - public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+"; - - /** - * 检查字符,防止注入绕过 - */ - public static String escapeOrderBySql(String value) - { - if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value)) - { - throw new UtilException("参数不符合规范,不能进行查询"); - } - return value; - } - - /** - * 验证 order by 语法是否符合规范 - */ - public static boolean isValidOrderBySql(String value) - { - return value.matches(SQL_PATTERN); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java deleted file mode 100644 index 2c844271..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.ruoyi.common.utils.uuid; - -/** - * ID生成器工具类 - * - * @author ruoyi - */ -public class IdUtils -{ - /** - * 获取随机UUID - * - * @return 随机UUID - */ - public static String randomUUID() - { - return UUID.randomUUID().toString(); - } - - /** - * 简化的UUID,去掉了横线 - * - * @return 简化的UUID,去掉了横线 - */ - public static String simpleUUID() - { - return UUID.randomUUID().toString(true); - } - - /** - * 获取随机UUID,使用性能更好的ThreadLocalRandom生成UUID - * - * @return 随机UUID - */ - public static String fastUUID() - { - return UUID.fastUUID().toString(); - } - - /** - * 简化的UUID,去掉了横线,使用性能更好的ThreadLocalRandom生成UUID - * - * @return 简化的UUID,去掉了横线 - */ - public static String fastSimpleUUID() - { - return UUID.fastUUID().toString(true); - } -} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java deleted file mode 100644 index dfda46cf..00000000 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java +++ /dev/null @@ -1,484 +0,0 @@ -package com.ruoyi.common.utils.uuid; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.util.Random; -import java.util.concurrent.ThreadLocalRandom; -import com.ruoyi.common.exception.UtilException; - -/** - * 提供通用唯一识别码(universally unique identifier)(UUID)实现 - * - * @author ruoyi - */ -public final class UUID implements java.io.Serializable, Comparable -{ - private static final long serialVersionUID = -1185015143654744140L; - - /** - * SecureRandom 的单例 - * - */ - private static class Holder - { - static final SecureRandom numberGenerator = getSecureRandom(); - } - - /** 此UUID的最高64有效位 */ - private final long mostSigBits; - - /** 此UUID的最低64有效位 */ - private final long leastSigBits; - - /** - * 私有构造 - * - * @param data 数据 - */ - private UUID(byte[] data) - { - long msb = 0; - long lsb = 0; - assert data.length == 16 : "data must be 16 bytes in length"; - for (int i = 0; i < 8; i++) - { - msb = (msb << 8) | (data[i] & 0xff); - } - for (int i = 8; i < 16; i++) - { - lsb = (lsb << 8) | (data[i] & 0xff); - } - this.mostSigBits = msb; - this.leastSigBits = lsb; - } - - /** - * 使用指定的数据构造新的 UUID。 - * - * @param mostSigBits 用于 {@code UUID} 的最高有效 64 位 - * @param leastSigBits 用于 {@code UUID} 的最低有效 64 位 - */ - public UUID(long mostSigBits, long leastSigBits) - { - this.mostSigBits = mostSigBits; - this.leastSigBits = leastSigBits; - } - - /** - * 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的本地线程伪随机数生成器生成该 UUID。 - * - * @return 随机生成的 {@code UUID} - */ - public static UUID fastUUID() - { - return randomUUID(false); - } - - /** - * 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。 - * - * @return 随机生成的 {@code UUID} - */ - public static UUID randomUUID() - { - return randomUUID(true); - } - - /** - * 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。 - * - * @param isSecure 是否使用{@link SecureRandom}如果是可以获得更安全的随机码,否则可以得到更好的性能 - * @return 随机生成的 {@code UUID} - */ - public static UUID randomUUID(boolean isSecure) - { - final Random ng = isSecure ? Holder.numberGenerator : getRandom(); - - byte[] randomBytes = new byte[16]; - ng.nextBytes(randomBytes); - randomBytes[6] &= 0x0f; /* clear version */ - randomBytes[6] |= 0x40; /* set to version 4 */ - randomBytes[8] &= 0x3f; /* clear variant */ - randomBytes[8] |= 0x80; /* set to IETF variant */ - return new UUID(randomBytes); - } - - /** - * 根据指定的字节数组获取类型 3(基于名称的)UUID 的静态工厂。 - * - * @param name 用于构造 UUID 的字节数组。 - * - * @return 根据指定数组生成的 {@code UUID} - */ - public static UUID nameUUIDFromBytes(byte[] name) - { - MessageDigest md; - try - { - md = MessageDigest.getInstance("MD5"); - } - catch (NoSuchAlgorithmException nsae) - { - throw new InternalError("MD5 not supported"); - } - byte[] md5Bytes = md.digest(name); - md5Bytes[6] &= 0x0f; /* clear version */ - md5Bytes[6] |= 0x30; /* set to version 3 */ - md5Bytes[8] &= 0x3f; /* clear variant */ - md5Bytes[8] |= 0x80; /* set to IETF variant */ - return new UUID(md5Bytes); - } - - /** - * 根据 {@link #toString()} 方法中描述的字符串标准表示形式创建{@code UUID}。 - * - * @param name 指定 {@code UUID} 字符串 - * @return 具有指定值的 {@code UUID} - * @throws IllegalArgumentException 如果 name 与 {@link #toString} 中描述的字符串表示形式不符抛出此异常 - * - */ - public static UUID fromString(String name) - { - String[] components = name.split("-"); - if (components.length != 5) - { - throw new IllegalArgumentException("Invalid UUID string: " + name); - } - for (int i = 0; i < 5; i++) - { - components[i] = "0x" + components[i]; - } - - long mostSigBits = Long.decode(components[0]).longValue(); - mostSigBits <<= 16; - mostSigBits |= Long.decode(components[1]).longValue(); - mostSigBits <<= 16; - mostSigBits |= Long.decode(components[2]).longValue(); - - long leastSigBits = Long.decode(components[3]).longValue(); - leastSigBits <<= 48; - leastSigBits |= Long.decode(components[4]).longValue(); - - return new UUID(mostSigBits, leastSigBits); - } - - /** - * 返回此 UUID 的 128 位值中的最低有效 64 位。 - * - * @return 此 UUID 的 128 位值中的最低有效 64 位。 - */ - public long getLeastSignificantBits() - { - return leastSigBits; - } - - /** - * 返回此 UUID 的 128 位值中的最高有效 64 位。 - * - * @return 此 UUID 的 128 位值中最高有效 64 位。 - */ - public long getMostSignificantBits() - { - return mostSigBits; - } - - /** - * 与此 {@code UUID} 相关联的版本号. 版本号描述此 {@code UUID} 是如何生成的。 - *

- * 版本号具有以下含意: - *

    - *
  • 1 基于时间的 UUID - *
  • 2 DCE 安全 UUID - *
  • 3 基于名称的 UUID - *
  • 4 随机生成的 UUID - *
- * - * @return 此 {@code UUID} 的版本号 - */ - public int version() - { - // Version is bits masked by 0x000000000000F000 in MS long - return (int) ((mostSigBits >> 12) & 0x0f); - } - - /** - * 与此 {@code UUID} 相关联的变体号。变体号描述 {@code UUID} 的布局。 - *

- * 变体号具有以下含意: - *

    - *
  • 0 为 NCS 向后兼容保留 - *
  • 2 IETF RFC 4122(Leach-Salz), 用于此类 - *
  • 6 保留,微软向后兼容 - *
  • 7 保留供以后定义使用 - *
- * - * @return 此 {@code UUID} 相关联的变体号 - */ - public int variant() - { - // This field is composed of a varying number of bits. - // 0 - - Reserved for NCS backward compatibility - // 1 0 - The IETF aka Leach-Salz variant (used by this class) - // 1 1 0 Reserved, Microsoft backward compatibility - // 1 1 1 Reserved for future definition. - return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63)); - } - - /** - * 与此 UUID 相关联的时间戳值。 - * - *

- * 60 位的时间戳值根据此 {@code UUID} 的 time_low、time_mid 和 time_hi 字段构造。
- * 所得到的时间戳以 100 毫微秒为单位,从 UTC(通用协调时间) 1582 年 10 月 15 日零时开始。 - * - *

- * 时间戳值仅在在基于时间的 UUID(其 version 类型为 1)中才有意义。
- * 如果此 {@code UUID} 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。 - * - * @throws UnsupportedOperationException 如果此 {@code UUID} 不是 version 为 1 的 UUID。 - */ - public long timestamp() throws UnsupportedOperationException - { - checkTimeBase(); - return (mostSigBits & 0x0FFFL) << 48// - | ((mostSigBits >> 16) & 0x0FFFFL) << 32// - | mostSigBits >>> 32; - } - - /** - * 与此 UUID 相关联的时钟序列值。 - * - *

- * 14 位的时钟序列值根据此 UUID 的 clock_seq 字段构造。clock_seq 字段用于保证在基于时间的 UUID 中的时间唯一性。 - *

- * {@code clockSequence} 值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。 如果此 UUID 不是基于时间的 UUID,则此方法抛出 - * UnsupportedOperationException。 - * - * @return 此 {@code UUID} 的时钟序列 - * - * @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1 - */ - public int clockSequence() throws UnsupportedOperationException - { - checkTimeBase(); - return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48); - } - - /** - * 与此 UUID 相关的节点值。 - * - *

- * 48 位的节点值根据此 UUID 的 node 字段构造。此字段旨在用于保存机器的 IEEE 802 地址,该地址用于生成此 UUID 以保证空间唯一性。 - *

- * 节点值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。
- * 如果此 UUID 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。 - * - * @return 此 {@code UUID} 的节点值 - * - * @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1 - */ - public long node() throws UnsupportedOperationException - { - checkTimeBase(); - return leastSigBits & 0x0000FFFFFFFFFFFFL; - } - - /** - * 返回此{@code UUID} 的字符串表现形式。 - * - *

- * UUID 的字符串表示形式由此 BNF 描述: - * - *

-     * {@code
-     * UUID                   = ----
-     * time_low               = 4*
-     * time_mid               = 2*
-     * time_high_and_version  = 2*
-     * variant_and_sequence   = 2*
-     * node                   = 6*
-     * hexOctet               = 
-     * hexDigit               = [0-9a-fA-F]
-     * }
-     * 
- * - * - * - * @return 此{@code UUID} 的字符串表现形式 - * @see #toString(boolean) - */ - @Override - public String toString() - { - return toString(false); - } - - /** - * 返回此{@code UUID} 的字符串表现形式。 - * - *

- * UUID 的字符串表示形式由此 BNF 描述: - * - *

-     * {@code
-     * UUID                   = ----
-     * time_low               = 4*
-     * time_mid               = 2*
-     * time_high_and_version  = 2*
-     * variant_and_sequence   = 2*
-     * node                   = 6*
-     * hexOctet               = 
-     * hexDigit               = [0-9a-fA-F]
-     * }
-     * 
- * - * - * - * @param isSimple 是否简单模式,简单模式为不带'-'的UUID字符串 - * @return 此{@code UUID} 的字符串表现形式 - */ - public String toString(boolean isSimple) - { - final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36); - // time_low - builder.append(digits(mostSigBits >> 32, 8)); - if (!isSimple) - { - builder.append('-'); - } - // time_mid - builder.append(digits(mostSigBits >> 16, 4)); - if (!isSimple) - { - builder.append('-'); - } - // time_high_and_version - builder.append(digits(mostSigBits, 4)); - if (!isSimple) - { - builder.append('-'); - } - // variant_and_sequence - builder.append(digits(leastSigBits >> 48, 4)); - if (!isSimple) - { - builder.append('-'); - } - // node - builder.append(digits(leastSigBits, 12)); - - return builder.toString(); - } - - /** - * 返回此 UUID 的哈希码。 - * - * @return UUID 的哈希码值。 - */ - @Override - public int hashCode() - { - long hilo = mostSigBits ^ leastSigBits; - return ((int) (hilo >> 32)) ^ (int) hilo; - } - - /** - * 将此对象与指定对象比较。 - *

- * 当且仅当参数不为 {@code null}、而是一个 UUID 对象、具有与此 UUID 相同的 varriant、包含相同的值(每一位均相同)时,结果才为 {@code true}。 - * - * @param obj 要与之比较的对象 - * - * @return 如果对象相同,则返回 {@code true};否则返回 {@code false} - */ - @Override - public boolean equals(Object obj) - { - if ((null == obj) || (obj.getClass() != UUID.class)) - { - return false; - } - UUID id = (UUID) obj; - return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits); - } - - // Comparison Operations - - /** - * 将此 UUID 与指定的 UUID 比较。 - * - *

- * 如果两个 UUID 不同,且第一个 UUID 的最高有效字段大于第二个 UUID 的对应字段,则第一个 UUID 大于第二个 UUID。 - * - * @param val 与此 UUID 比较的 UUID - * - * @return 在此 UUID 小于、等于或大于 val 时,分别返回 -1、0 或 1。 - * - */ - @Override - public int compareTo(UUID val) - { - // The ordering is intentionally set up so that the UUIDs - // can simply be numerically compared as two numbers - return (this.mostSigBits < val.mostSigBits ? -1 : // - (this.mostSigBits > val.mostSigBits ? 1 : // - (this.leastSigBits < val.leastSigBits ? -1 : // - (this.leastSigBits > val.leastSigBits ? 1 : // - 0)))); - } - - // ------------------------------------------------------------------------------------------------------------------- - // Private method start - /** - * 返回指定数字对应的hex值 - * - * @param val 值 - * @param digits 位 - * @return 值 - */ - private static String digits(long val, int digits) - { - long hi = 1L << (digits * 4); - return Long.toHexString(hi | (val & (hi - 1))).substring(1); - } - - /** - * 检查是否为time-based版本UUID - */ - private void checkTimeBase() - { - if (version() != 1) - { - throw new UnsupportedOperationException("Not a time-based UUID"); - } - } - - /** - * 获取{@link SecureRandom},类提供加密的强随机数生成器 (RNG) - * - * @return {@link SecureRandom} - */ - public static SecureRandom getSecureRandom() - { - try - { - return SecureRandom.getInstance("SHA1PRNG"); - } - catch (NoSuchAlgorithmException e) - { - throw new UtilException(e); - } - } - - /** - * 获取随机数生成器对象
- * ThreadLocalRandom是JDK 7之后提供并发产生随机数,能够解决多个线程发生的竞争争夺。 - * - * @return {@link ThreadLocalRandom} - */ - public static ThreadLocalRandom getRandom() - { - return ThreadLocalRandom.current(); - } -} diff --git a/springboot/wumei-framework/pom.xml b/springboot/wumei-framework/pom.xml deleted file mode 100644 index cb502414..00000000 --- a/springboot/wumei-framework/pom.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - wumei - com.wumei - 3.8.0 - - 4.0.0 - - wumei-framework - - - framework框架核心 - - - - - - - org.springframework.boot - spring-boot-starter-web - - - - - org.springframework.boot - spring-boot-starter-aop - - - - - com.alibaba - druid-spring-boot-starter - - - - - com.github.penggle - kaptcha - - - javax.servlet-api - javax.servlet - - - - - - - com.github.oshi - oshi-core - - - - - com.wumei - wumei-system - - - - - \ No newline at end of file diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java deleted file mode 100644 index 48f8d728..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java +++ /dev/null @@ -1,149 +0,0 @@ -package com.ruoyi.framework.aspectj; - -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Before; -import org.springframework.stereotype.Component; -import com.ruoyi.common.annotation.DataScope; -import com.ruoyi.common.core.domain.BaseEntity; -import com.ruoyi.common.core.domain.entity.SysRole; -import com.ruoyi.common.core.domain.entity.SysUser; -import com.ruoyi.common.core.domain.model.LoginUser; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.SecurityUtils; - -/** - * 数据过滤处理 - * - * @author ruoyi - */ -@Aspect -@Component -public class DataScopeAspect -{ - /** - * 全部数据权限 - */ - public static final String DATA_SCOPE_ALL = "1"; - - /** - * 自定数据权限 - */ - public static final String DATA_SCOPE_CUSTOM = "2"; - - /** - * 部门数据权限 - */ - public static final String DATA_SCOPE_DEPT = "3"; - - /** - * 部门及以下数据权限 - */ - public static final String DATA_SCOPE_DEPT_AND_CHILD = "4"; - - /** - * 仅本人数据权限 - */ - public static final String DATA_SCOPE_SELF = "5"; - - /** - * 数据权限过滤关键字 - */ - public static final String DATA_SCOPE = "dataScope"; - - @Before("@annotation(controllerDataScope)") - public void doBefore(JoinPoint point, DataScope controllerDataScope) throws Throwable - { - clearDataScope(point); - handleDataScope(point, controllerDataScope); - } - - protected void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope) - { - // 获取当前的用户 - LoginUser loginUser = SecurityUtils.getLoginUser(); - if (StringUtils.isNotNull(loginUser)) - { - SysUser currentUser = loginUser.getUser(); - // 如果是超级管理员,则不过滤数据 - if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin()) - { - dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), - controllerDataScope.userAlias()); - } - } - } - - /** - * 数据范围过滤 - * - * @param joinPoint 切点 - * @param user 用户 - * @param userAlias 别名 - */ - public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias) - { - StringBuilder sqlString = new StringBuilder(); - - for (SysRole role : user.getRoles()) - { - String dataScope = role.getDataScope(); - if (DATA_SCOPE_ALL.equals(dataScope)) - { - sqlString = new StringBuilder(); - break; - } - else if (DATA_SCOPE_CUSTOM.equals(dataScope)) - { - sqlString.append(StringUtils.format( - " OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias, - role.getRoleId())); - } - else if (DATA_SCOPE_DEPT.equals(dataScope)) - { - sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId())); - } - else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) - { - sqlString.append(StringUtils.format( - " OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )", - deptAlias, user.getDeptId(), user.getDeptId())); - } - else if (DATA_SCOPE_SELF.equals(dataScope)) - { - if (StringUtils.isNotBlank(userAlias)) - { - sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId())); - } - else - { - // 数据权限为仅本人且没有userAlias别名不查询任何数据 - sqlString.append(" OR 1=0 "); - } - } - } - - if (StringUtils.isNotBlank(sqlString.toString())) - { - Object params = joinPoint.getArgs()[0]; - if (StringUtils.isNotNull(params) && params instanceof BaseEntity) - { - BaseEntity baseEntity = (BaseEntity) params; - baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")"); - } - } - } - - /** - * 拼接权限sql前先清空params.dataScope参数防止注入 - */ - private void clearDataScope(final JoinPoint joinPoint) - { - Object params = joinPoint.getArgs()[0]; - if (StringUtils.isNotNull(params) && params instanceof BaseEntity) - { - BaseEntity baseEntity = (BaseEntity) params; - baseEntity.getParams().put(DATA_SCOPE, ""); - } - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java deleted file mode 100644 index 8c2c9f43..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.ruoyi.framework.aspectj; - -import java.util.Objects; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Pointcut; -import org.aspectj.lang.reflect.MethodSignature; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.core.annotation.Order; -import org.springframework.stereotype.Component; -import com.ruoyi.common.annotation.DataSource; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.framework.datasource.DynamicDataSourceContextHolder; - -/** - * 多数据源处理 - * - * @author ruoyi - */ -@Aspect -@Order(1) -@Component -public class DataSourceAspect -{ - protected Logger logger = LoggerFactory.getLogger(getClass()); - - @Pointcut("@annotation(com.ruoyi.common.annotation.DataSource)" - + "|| @within(com.ruoyi.common.annotation.DataSource)") - public void dsPointCut() - { - - } - - @Around("dsPointCut()") - public Object around(ProceedingJoinPoint point) throws Throwable - { - DataSource dataSource = getDataSource(point); - - if (StringUtils.isNotNull(dataSource)) - { - DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name()); - } - - try - { - return point.proceed(); - } - finally - { - // 销毁数据源 在执行方法之后 - DynamicDataSourceContextHolder.clearDataSourceType(); - } - } - - /** - * 获取需要切换的数据源 - */ - public DataSource getDataSource(ProceedingJoinPoint point) - { - MethodSignature signature = (MethodSignature) point.getSignature(); - DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class); - if (Objects.nonNull(dataSource)) - { - return dataSource; - } - - return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class); - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java deleted file mode 100644 index 9bf5b8c5..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java +++ /dev/null @@ -1,218 +0,0 @@ -package com.ruoyi.framework.aspectj; - -import java.util.Collection; -import java.util.Map; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.annotation.AfterReturning; -import org.aspectj.lang.annotation.AfterThrowing; -import org.aspectj.lang.annotation.Aspect; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; -import org.springframework.validation.BindingResult; -import org.springframework.web.multipart.MultipartFile; -import org.springframework.web.servlet.HandlerMapping; -import com.alibaba.fastjson.JSON; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.domain.model.LoginUser; -import com.ruoyi.common.enums.BusinessStatus; -import com.ruoyi.common.enums.HttpMethod; -import com.ruoyi.common.utils.ServletUtils; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.ip.IpUtils; -import com.ruoyi.common.utils.SecurityUtils; -import com.ruoyi.framework.manager.AsyncManager; -import com.ruoyi.framework.manager.factory.AsyncFactory; -import com.ruoyi.system.domain.SysOperLog; - -/** - * 操作日志记录处理 - * - * @author ruoyi - */ -@Aspect -@Component -public class LogAspect -{ - private static final Logger log = LoggerFactory.getLogger(LogAspect.class); - - /** - * 处理完请求后执行 - * - * @param joinPoint 切点 - */ - @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult") - public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult) - { - handleLog(joinPoint, controllerLog, null, jsonResult); - } - - /** - * 拦截异常操作 - * - * @param joinPoint 切点 - * @param e 异常 - */ - @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e") - public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) - { - handleLog(joinPoint, controllerLog, e, null); - } - - protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult) - { - try - { - - // 获取当前的用户 - LoginUser loginUser = SecurityUtils.getLoginUser(); - - // *========数据库日志=========*// - SysOperLog operLog = new SysOperLog(); - operLog.setStatus(BusinessStatus.SUCCESS.ordinal()); - // 请求的地址 - String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); - operLog.setOperIp(ip); - operLog.setOperUrl(ServletUtils.getRequest().getRequestURI()); - if (loginUser != null) - { - operLog.setOperName(loginUser.getUsername()); - } - - if (e != null) - { - operLog.setStatus(BusinessStatus.FAIL.ordinal()); - operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000)); - } - // 设置方法名称 - String className = joinPoint.getTarget().getClass().getName(); - String methodName = joinPoint.getSignature().getName(); - operLog.setMethod(className + "." + methodName + "()"); - // 设置请求方式 - operLog.setRequestMethod(ServletUtils.getRequest().getMethod()); - // 处理设置注解上的参数 - getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult); - // 保存数据库 - AsyncManager.me().execute(AsyncFactory.recordOper(operLog)); - } - catch (Exception exp) - { - // 记录本地异常日志 - log.error("==前置通知异常=="); - log.error("异常信息:{}", exp.getMessage()); - exp.printStackTrace(); - } - } - - /** - * 获取注解中对方法的描述信息 用于Controller层注解 - * - * @param log 日志 - * @param operLog 操作日志 - * @throws Exception - */ - public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog, Object jsonResult) throws Exception - { - // 设置action动作 - operLog.setBusinessType(log.businessType().ordinal()); - // 设置标题 - operLog.setTitle(log.title()); - // 设置操作人类别 - operLog.setOperatorType(log.operatorType().ordinal()); - // 是否需要保存request,参数和值 - if (log.isSaveRequestData()) - { - // 获取参数的信息,传入到数据库中。 - setRequestValue(joinPoint, operLog); - } - // 是否需要保存response,参数和值 - if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult)) - { - operLog.setJsonResult(StringUtils.substring(JSON.toJSONString(jsonResult), 0, 2000)); - } - } - - /** - * 获取请求的参数,放到log中 - * - * @param operLog 操作日志 - * @throws Exception 异常 - */ - private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog) throws Exception - { - String requestMethod = operLog.getRequestMethod(); - if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) - { - String params = argsArrayToString(joinPoint.getArgs()); - operLog.setOperParam(StringUtils.substring(params, 0, 2000)); - } - else - { - Map paramsMap = (Map) ServletUtils.getRequest().getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); - operLog.setOperParam(StringUtils.substring(paramsMap.toString(), 0, 2000)); - } - } - - /** - * 参数拼装 - */ - private String argsArrayToString(Object[] paramsArray) - { - String params = ""; - if (paramsArray != null && paramsArray.length > 0) - { - for (Object o : paramsArray) - { - if (StringUtils.isNotNull(o) && !isFilterObject(o)) - { - try - { - Object jsonObj = JSON.toJSON(o); - params += jsonObj.toString() + " "; - } - catch (Exception e) - { - } - } - } - } - return params.trim(); - } - - /** - * 判断是否需要过滤的对象。 - * - * @param o 对象信息。 - * @return 如果是需要过滤的对象,则返回true;否则返回false。 - */ - @SuppressWarnings("rawtypes") - public boolean isFilterObject(final Object o) - { - Class clazz = o.getClass(); - if (clazz.isArray()) - { - return clazz.getComponentType().isAssignableFrom(MultipartFile.class); - } - else if (Collection.class.isAssignableFrom(clazz)) - { - Collection collection = (Collection) o; - for (Object value : collection) - { - return value instanceof MultipartFile; - } - } - else if (Map.class.isAssignableFrom(clazz)) - { - Map map = (Map) o; - for (Object value : map.entrySet()) - { - Map.Entry entry = (Map.Entry) value; - return entry.getValue() instanceof MultipartFile; - } - } - return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse - || o instanceof BindingResult; - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java deleted file mode 100644 index 0d1b62f1..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.ruoyi.framework.aspectj; - -import java.lang.reflect.Method; -import java.util.Collections; -import java.util.List; -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Before; -import org.aspectj.lang.reflect.MethodSignature; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.core.script.RedisScript; -import org.springframework.stereotype.Component; -import com.ruoyi.common.annotation.RateLimiter; -import com.ruoyi.common.enums.LimitType; -import com.ruoyi.common.exception.ServiceException; -import com.ruoyi.common.utils.ServletUtils; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.ip.IpUtils; - -/** - * 限流处理 - * - * @author ruoyi - */ -@Aspect -@Component -public class RateLimiterAspect -{ - private static final Logger log = LoggerFactory.getLogger(RateLimiterAspect.class); - - private RedisTemplate redisTemplate; - - private RedisScript limitScript; - - @Autowired - public void setRedisTemplate1(RedisTemplate redisTemplate) - { - this.redisTemplate = redisTemplate; - } - - @Autowired - public void setLimitScript(RedisScript limitScript) - { - this.limitScript = limitScript; - } - - @Before("@annotation(rateLimiter)") - public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable - { - String key = rateLimiter.key(); - int time = rateLimiter.time(); - int count = rateLimiter.count(); - - String combineKey = getCombineKey(rateLimiter, point); - List keys = Collections.singletonList(combineKey); - try - { - Long number = redisTemplate.execute(limitScript, keys, count, time); - if (StringUtils.isNull(number) || number.intValue() > count) - { - throw new ServiceException("访问过于频繁,请稍候再试"); - } - log.info("限制请求'{}',当前请求'{}',缓存key'{}'", count, number.intValue(), key); - } - catch (ServiceException e) - { - throw e; - } - catch (Exception e) - { - throw new RuntimeException("服务器限流异常,请稍候再试"); - } - } - - public String getCombineKey(RateLimiter rateLimiter, JoinPoint point) - { - StringBuffer stringBuffer = new StringBuffer(rateLimiter.key()); - if (rateLimiter.limitType() == LimitType.IP) - { - stringBuffer.append(IpUtils.getIpAddr(ServletUtils.getRequest())).append("-"); - } - MethodSignature signature = (MethodSignature) point.getSignature(); - Method method = signature.getMethod(); - Class targetClass = method.getDeclaringClass(); - stringBuffer.append(targetClass.getName()).append("-").append(method.getName()); - return stringBuffer.toString(); - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java deleted file mode 100644 index 1d4dc1f7..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.ruoyi.framework.config; - -import java.util.TimeZone; -import org.mybatis.spring.annotation.MapperScan; -import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.EnableAspectJAutoProxy; - -/** - * 程序注解配置 - * - * @author ruoyi - */ -@Configuration -// 表示通过aop框架暴露该代理对象,AopContext能够访问 -@EnableAspectJAutoProxy(exposeProxy = true) -// 指定要扫描的Mapper类的包的路径 -@MapperScan("com.ruoyi.**.mapper") -public class ApplicationConfig -{ - /** - * 时区配置 - */ - @Bean - public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() - { - return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(TimeZone.getDefault()); - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java deleted file mode 100644 index 43e78aeb..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.ruoyi.framework.config; - -import java.util.Properties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import com.google.code.kaptcha.impl.DefaultKaptcha; -import com.google.code.kaptcha.util.Config; -import static com.google.code.kaptcha.Constants.*; - -/** - * 验证码配置 - * - * @author ruoyi - */ -@Configuration -public class CaptchaConfig -{ - @Bean(name = "captchaProducer") - public DefaultKaptcha getKaptchaBean() - { - DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); - Properties properties = new Properties(); - // 是否有边框 默认为true 我们可以自己设置yes,no - properties.setProperty(KAPTCHA_BORDER, "yes"); - // 验证码文本字符颜色 默认为Color.BLACK - properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black"); - // 验证码图片宽度 默认为200 - properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160"); - // 验证码图片高度 默认为50 - properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60"); - // 验证码文本字符大小 默认为40 - properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38"); - // KAPTCHA_SESSION_KEY - properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode"); - // 验证码文本字符长度 默认为5 - properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4"); - // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize) - properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier"); - // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy - properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy"); - Config config = new Config(properties); - defaultKaptcha.setConfig(config); - return defaultKaptcha; - } - - @Bean(name = "captchaProducerMath") - public DefaultKaptcha getKaptchaBeanMath() - { - DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); - Properties properties = new Properties(); - // 是否有边框 默认为true 我们可以自己设置yes,no - properties.setProperty(KAPTCHA_BORDER, "yes"); - // 边框颜色 默认为Color.BLACK - properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90"); - // 验证码文本字符颜色 默认为Color.BLACK - properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue"); - // 验证码图片宽度 默认为200 - properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160"); - // 验证码图片高度 默认为50 - properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60"); - // 验证码文本字符大小 默认为40 - properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35"); - // KAPTCHA_SESSION_KEY - properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath"); - // 验证码文本生成器 - properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.ruoyi.framework.config.KaptchaTextCreator"); - // 验证码文本字符间距 默认为2 - properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3"); - // 验证码文本字符长度 默认为5 - properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6"); - // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize) - properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier"); - // 验证码噪点颜色 默认为Color.BLACK - properties.setProperty(KAPTCHA_NOISE_COLOR, "white"); - // 干扰实现类 - properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise"); - // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy - properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy"); - Config config = new Config(properties); - defaultKaptcha.setConfig(config); - return defaultKaptcha; - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java deleted file mode 100644 index f6abac13..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.ruoyi.framework.config; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.sql.DataSource; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; -import com.alibaba.druid.pool.DruidDataSource; -import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; -import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties; -import com.alibaba.druid.util.Utils; -import com.ruoyi.common.enums.DataSourceType; -import com.ruoyi.common.utils.spring.SpringUtils; -import com.ruoyi.framework.config.properties.DruidProperties; -import com.ruoyi.framework.datasource.DynamicDataSource; - -/** - * druid 配置多数据源 - * - * @author ruoyi - */ -@Configuration -public class DruidConfig -{ - @Bean - @ConfigurationProperties("spring.datasource.druid.master") - public DataSource masterDataSource(DruidProperties druidProperties) - { - DruidDataSource dataSource = DruidDataSourceBuilder.create().build(); - return druidProperties.dataSource(dataSource); - } - - @Bean - @ConfigurationProperties("spring.datasource.druid.slave") - @ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true") - public DataSource slaveDataSource(DruidProperties druidProperties) - { - DruidDataSource dataSource = DruidDataSourceBuilder.create().build(); - return druidProperties.dataSource(dataSource); - } - - @Bean(name = "dynamicDataSource") - @Primary - public DynamicDataSource dataSource(DataSource masterDataSource) - { - Map targetDataSources = new HashMap<>(); - targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource); - setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource"); - return new DynamicDataSource(masterDataSource, targetDataSources); - } - - /** - * 设置数据源 - * - * @param targetDataSources 备选数据源集合 - * @param sourceName 数据源名称 - * @param beanName bean名称 - */ - public void setDataSource(Map targetDataSources, String sourceName, String beanName) - { - try - { - DataSource dataSource = SpringUtils.getBean(beanName); - targetDataSources.put(sourceName, dataSource); - } - catch (Exception e) - { - } - } - - /** - * 去除监控页面底部的广告 - */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Bean - @ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true") - public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties) - { - // 获取web监控页面的参数 - DruidStatProperties.StatViewServlet config = properties.getStatViewServlet(); - // 提取common.js的配置路径 - String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*"; - String commonJsPattern = pattern.replaceAll("\\*", "js/common.js"); - final String filePath = "support/http/resources/js/common.js"; - // 创建filter进行过滤 - Filter filter = new Filter() - { - @Override - public void init(javax.servlet.FilterConfig filterConfig) throws ServletException - { - } - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) - throws IOException, ServletException - { - chain.doFilter(request, response); - // 重置缓冲区,响应头不会被重置 - response.resetBuffer(); - // 获取common.js - String text = Utils.readFromResource(filePath); - // 正则替换banner, 除去底部的广告信息 - text = text.replaceAll("
", ""); - text = text.replaceAll("powered.*?shrek.wang", ""); - response.getWriter().write(text); - } - @Override - public void destroy() - { - } - }; - FilterRegistrationBean registrationBean = new FilterRegistrationBean(); - registrationBean.setFilter(filter); - registrationBean.addUrlPatterns(commonJsPattern); - return registrationBean; - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java deleted file mode 100644 index 59812ea5..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.ruoyi.framework.config; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.serializer.SerializerFeature; -import com.fasterxml.jackson.databind.JavaType; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.type.TypeFactory; -import org.springframework.data.redis.serializer.RedisSerializer; -import org.springframework.data.redis.serializer.SerializationException; -import com.alibaba.fastjson.parser.ParserConfig; -import org.springframework.util.Assert; -import java.nio.charset.Charset; - -/** - * Redis使用FastJson序列化 - * - * @author ruoyi - */ -public class FastJson2JsonRedisSerializer implements RedisSerializer -{ - @SuppressWarnings("unused") - private ObjectMapper objectMapper = new ObjectMapper(); - - public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); - - private Class clazz; - - static - { - ParserConfig.getGlobalInstance().setAutoTypeSupport(true); - } - - public FastJson2JsonRedisSerializer(Class clazz) - { - super(); - this.clazz = clazz; - } - - @Override - public byte[] serialize(T t) throws SerializationException - { - if (t == null) - { - return new byte[0]; - } - return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); - } - - @Override - public T deserialize(byte[] bytes) throws SerializationException - { - if (bytes == null || bytes.length <= 0) - { - return null; - } - String str = new String(bytes, DEFAULT_CHARSET); - - return JSON.parseObject(str, clazz); - } - - public void setObjectMapper(ObjectMapper objectMapper) - { - Assert.notNull(objectMapper, "'objectMapper' must not be null"); - this.objectMapper = objectMapper; - } - - protected JavaType getJavaType(Class clazz) - { - return TypeFactory.defaultInstance().constructType(clazz); - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java deleted file mode 100644 index bb14c04d..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.ruoyi.framework.config; - -import java.util.HashMap; -import java.util.Map; -import javax.servlet.DispatcherType; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import com.ruoyi.common.filter.RepeatableFilter; -import com.ruoyi.common.filter.XssFilter; -import com.ruoyi.common.utils.StringUtils; - -/** - * Filter配置 - * - * @author ruoyi - */ -@Configuration -public class FilterConfig -{ - @Value("${xss.excludes}") - private String excludes; - - @Value("${xss.urlPatterns}") - private String urlPatterns; - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Bean - @ConditionalOnProperty(value = "xss.enabled", havingValue = "true") - public FilterRegistrationBean xssFilterRegistration() - { - FilterRegistrationBean registration = new FilterRegistrationBean(); - registration.setDispatcherTypes(DispatcherType.REQUEST); - registration.setFilter(new XssFilter()); - registration.addUrlPatterns(StringUtils.split(urlPatterns, ",")); - registration.setName("xssFilter"); - registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE); - Map initParameters = new HashMap(); - initParameters.put("excludes", excludes); - registration.setInitParameters(initParameters); - return registration; - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Bean - public FilterRegistrationBean someFilterRegistration() - { - FilterRegistrationBean registration = new FilterRegistrationBean(); - registration.setFilter(new RepeatableFilter()); - registration.addUrlPatterns("/*"); - registration.setName("repeatableFilter"); - registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE); - return registration; - } - -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java deleted file mode 100644 index 3e745800..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.ruoyi.framework.config; - -import java.util.Random; -import com.google.code.kaptcha.text.impl.DefaultTextCreator; - -/** - * 验证码文本生成器 - * - * @author ruoyi - */ -public class KaptchaTextCreator extends DefaultTextCreator -{ - private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(","); - - @Override - public String getText() - { - Integer result = 0; - Random random = new Random(); - int x = random.nextInt(10); - int y = random.nextInt(10); - StringBuilder suChinese = new StringBuilder(); - int randomoperands = (int) Math.round(Math.random() * 2); - if (randomoperands == 0) - { - result = x * y; - suChinese.append(CNUMBERS[x]); - suChinese.append("*"); - suChinese.append(CNUMBERS[y]); - } - else if (randomoperands == 1) - { - if (!(x == 0) && y % x == 0) - { - result = y / x; - suChinese.append(CNUMBERS[y]); - suChinese.append("/"); - suChinese.append(CNUMBERS[x]); - } - else - { - result = x + y; - suChinese.append(CNUMBERS[x]); - suChinese.append("+"); - suChinese.append(CNUMBERS[y]); - } - } - else if (randomoperands == 2) - { - if (x >= y) - { - result = x - y; - suChinese.append(CNUMBERS[x]); - suChinese.append("-"); - suChinese.append(CNUMBERS[y]); - } - else - { - result = y - x; - suChinese.append(CNUMBERS[y]); - suChinese.append("-"); - suChinese.append(CNUMBERS[x]); - } - } - else - { - result = x + y; - suChinese.append(CNUMBERS[x]); - suChinese.append("+"); - suChinese.append(CNUMBERS[y]); - } - suChinese.append("=?@" + result); - return suChinese.toString(); - } -} \ No newline at end of file diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/MyBatisConfig.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/MyBatisConfig.java deleted file mode 100644 index 56463e7a..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/MyBatisConfig.java +++ /dev/null @@ -1,149 +0,0 @@ -package com.ruoyi.framework.config; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import javax.sql.DataSource; -import org.apache.ibatis.io.VFS; -import org.apache.ibatis.session.SqlSessionFactory; -import org.mybatis.spring.SqlSessionFactoryBean; -import org.mybatis.spring.SqlSessionTemplate; -import org.mybatis.spring.boot.autoconfigure.SpringBootVFS; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; -import org.springframework.core.env.Environment; -import org.springframework.core.io.DefaultResourceLoader; -import org.springframework.core.io.Resource; -import org.springframework.core.io.support.PathMatchingResourcePatternResolver; -import org.springframework.core.io.support.ResourcePatternResolver; -import org.springframework.core.type.classreading.CachingMetadataReaderFactory; -import org.springframework.core.type.classreading.MetadataReader; -import org.springframework.core.type.classreading.MetadataReaderFactory; -import org.springframework.jdbc.datasource.DataSourceTransactionManager; -import org.springframework.util.ClassUtils; -import com.ruoyi.common.utils.StringUtils; - -/** - * Mybatis支持*匹配扫描包 - * - * @author ruoyi - */ -@Configuration -public class MyBatisConfig -{ - @Autowired - private Environment env; - - static final String DEFAULT_RESOURCE_PATTERN = "**/*.class"; - - public static String setTypeAliasesPackage(String typeAliasesPackage) - { - ResourcePatternResolver resolver = (ResourcePatternResolver) new PathMatchingResourcePatternResolver(); - MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver); - List allResult = new ArrayList(); - try - { - for (String aliasesPackage : typeAliasesPackage.split(",")) - { - List result = new ArrayList(); - aliasesPackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX - + ClassUtils.convertClassNameToResourcePath(aliasesPackage.trim()) + "/" + DEFAULT_RESOURCE_PATTERN; - Resource[] resources = resolver.getResources(aliasesPackage); - if (resources != null && resources.length > 0) - { - MetadataReader metadataReader = null; - for (Resource resource : resources) - { - if (resource.isReadable()) - { - metadataReader = metadataReaderFactory.getMetadataReader(resource); - try - { - result.add(Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName()); - } - catch (ClassNotFoundException e) - { - e.printStackTrace(); - } - } - } - } - if (result.size() > 0) - { - HashSet hashResult = new HashSet(result); - allResult.addAll(hashResult); - } - } - if (allResult.size() > 0) - { - typeAliasesPackage = String.join(",", (String[]) allResult.toArray(new String[0])); - } - else - { - throw new RuntimeException("mybatis typeAliasesPackage 路径扫描错误,参数typeAliasesPackage:" + typeAliasesPackage + "未找到任何包"); - } - } - catch (IOException e) - { - e.printStackTrace(); - } - return typeAliasesPackage; - } - - public Resource[] resolveMapperLocations(String[] mapperLocations) - { - ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver(); - List resources = new ArrayList(); - if (mapperLocations != null) - { - for (String mapperLocation : mapperLocations) - { - try - { - Resource[] mappers = resourceResolver.getResources(mapperLocation); - resources.addAll(Arrays.asList(mappers)); - } - catch (IOException e) - { - // ignore - } - } - } - return resources.toArray(new Resource[resources.size()]); - } - - @Bean(name = "mysqlSessionFactory") - @Primary - public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception - { - String typeAliasesPackage = env.getProperty("mybatis.typeAliasesPackage"); - String mapperLocations = env.getProperty("mybatis.mapperLocations"); - String configLocation = env.getProperty("mybatis.configLocation"); - typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage); - VFS.addImplClass(SpringBootVFS.class); - - final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); - sessionFactory.setDataSource(dataSource); - sessionFactory.setTypeAliasesPackage(typeAliasesPackage); - sessionFactory.setMapperLocations(resolveMapperLocations(StringUtils.split(mapperLocations, ","))); - sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation)); - return sessionFactory.getObject(); - } - - @Bean(name = "mysqlTransactionManager") - @Primary - public DataSourceTransactionManager mysqlTransactionManager(@Qualifier("dynamicDataSource") DataSource dataSource) { - return new DataSourceTransactionManager(dataSource); - } - - @Bean(name = "mysqlSqlSessionTemplate") - @Primary - public SqlSessionTemplate mysqlSqlSessionTemplate(@Qualifier("mysqlSessionFactory") SqlSessionFactory sqlSessionFactory) { - return new SqlSessionTemplate(sqlSessionFactory); - } -} \ No newline at end of file diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java deleted file mode 100644 index 833f219c..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.ruoyi.framework.config; - -import org.springframework.cache.annotation.CachingConfigurerSupport; -import org.springframework.cache.annotation.EnableCaching; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.core.script.DefaultRedisScript; -import org.springframework.data.redis.serializer.StringRedisSerializer; -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonTypeInfo; -import com.fasterxml.jackson.annotation.PropertyAccessor; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; - -/** - * redis配置 - * - * @author ruoyi - */ -@Configuration -@EnableCaching -public class RedisConfig extends CachingConfigurerSupport -{ - @Bean - @SuppressWarnings(value = { "unchecked", "rawtypes" }) - public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) - { - RedisTemplate template = new RedisTemplate<>(); - template.setConnectionFactory(connectionFactory); - - FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class); - - ObjectMapper mapper = new ObjectMapper(); - mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); - mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); - serializer.setObjectMapper(mapper); - - // 使用StringRedisSerializer来序列化和反序列化redis的key值 - template.setKeySerializer(new StringRedisSerializer()); - template.setValueSerializer(serializer); - - // Hash的key也采用StringRedisSerializer的序列化方式 - template.setHashKeySerializer(new StringRedisSerializer()); - template.setHashValueSerializer(serializer); - - template.afterPropertiesSet(); - return template; - } - - @Bean - public DefaultRedisScript limitScript() - { - DefaultRedisScript redisScript = new DefaultRedisScript<>(); - redisScript.setScriptText(limitScriptText()); - redisScript.setResultType(Long.class); - return redisScript; - } - - /** - * 限流脚本 - */ - private String limitScriptText() - { - return "local key = KEYS[1]\n" + - "local count = tonumber(ARGV[1])\n" + - "local time = tonumber(ARGV[2])\n" + - "local current = redis.call('get', key);\n" + - "if current and tonumber(current) > count then\n" + - " return tonumber(current);\n" + - "end\n" + - "current = redis.call('incr', key)\n" + - "if tonumber(current) == 1 then\n" + - " redis.call('expire', key, time)\n" + - "end\n" + - "return tonumber(current);"; - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java deleted file mode 100644 index 50ad496c..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.ruoyi.framework.config; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.cors.CorsConfiguration; -import org.springframework.web.cors.UrlBasedCorsConfigurationSource; -import org.springframework.web.filter.CorsFilter; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; -import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import com.ruoyi.common.config.RuoYiConfig; -import com.ruoyi.common.constant.Constants; -import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor; - -/** - * 通用配置 - * - * @author ruoyi - */ -@Configuration -public class ResourcesConfig implements WebMvcConfigurer -{ - @Autowired - private RepeatSubmitInterceptor repeatSubmitInterceptor; - - @Override - public void addResourceHandlers(ResourceHandlerRegistry registry) - { - /** 本地文件上传路径 */ - registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**") - .addResourceLocations("file:" + RuoYiConfig.getProfile() + "/"); - - /** swagger配置 */ - registry.addResourceHandler("/swagger-ui/**") - .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/"); - } - - /** - * 自定义拦截规则 - */ - @Override - public void addInterceptors(InterceptorRegistry registry) - { - registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**"); - } - - /** - * 跨域配置 - */ - @Bean - public CorsFilter corsFilter() - { - CorsConfiguration config = new CorsConfiguration(); - config.setAllowCredentials(true); - // 设置访问源地址 - config.addAllowedOriginPattern("*"); - // 设置访问源请求头 - config.addAllowedHeader("*"); - // 设置访问源请求方法 - config.addAllowedMethod("*"); - // 有效期 1800秒 - config.setMaxAge(1800L); - // 添加映射路径,拦截一切请求 - UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); - source.registerCorsConfiguration("/**", config); - // 返回新的CorsFilter - return new CorsFilter(source); - } -} \ No newline at end of file diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java deleted file mode 100644 index 6980efb0..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java +++ /dev/null @@ -1,160 +0,0 @@ -package com.ruoyi.framework.config; - -import com.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter; -import com.ruoyi.framework.security.handle.AuthenticationEntryPointImpl; -import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.http.HttpMethod; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -import org.springframework.security.web.authentication.logout.LogoutFilter; -import org.springframework.web.filter.CorsFilter; - -/** - * spring security配置 - * - * @author ruoyi - */ -@EnableWebSecurity -@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) -public class SecurityConfig extends WebSecurityConfigurerAdapter -{ - /** - * 自定义用户认证逻辑 - */ - @Autowired - private UserDetailsService userDetailsService; - - /** - * 认证失败处理类 - */ - @Autowired - private AuthenticationEntryPointImpl unauthorizedHandler; - - /** - * 退出处理类 - */ - @Autowired - private LogoutSuccessHandlerImpl logoutSuccessHandler; - - /** - * token认证过滤器 - */ - @Autowired - private JwtAuthenticationTokenFilter authenticationTokenFilter; - - /** - * 跨域过滤器 - */ - @Autowired - private CorsFilter corsFilter; - - /** - * 解决 无法直接注入 AuthenticationManager - * - * @return - * @throws Exception - */ - @Bean - @Override - public AuthenticationManager authenticationManagerBean() throws Exception - { - return super.authenticationManagerBean(); - } - - /** - * anyRequest | 匹配所有请求路径 - * access | SpringEl表达式结果为true时可以访问 - * anonymous | 匿名可以访问 - * denyAll | 用户不能访问 - * fullyAuthenticated | 用户完全认证可以访问(非remember-me下自动登录) - * hasAnyAuthority | 如果有参数,参数表示权限,则其中任何一个权限可以访问 - * hasAnyRole | 如果有参数,参数表示角色,则其中任何一个角色可以访问 - * hasAuthority | 如果有参数,参数表示权限,则其权限可以访问 - * hasIpAddress | 如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问 - * hasRole | 如果有参数,参数表示角色,则其角色可以访问 - * permitAll | 用户可以任意访问 - * rememberMe | 允许通过remember-me登录的用户访问 - * authenticated | 用户登录后可访问 - */ - @Override - protected void configure(HttpSecurity httpSecurity) throws Exception - { - httpSecurity - // CSRF禁用,因为不使用session - .csrf().disable() - // 认证失败处理类 TODO 启用自定义认证会导致oauth授权地址不能访问 - .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and() - // 基于token,所以不需要session - .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() - // 过滤请求 - .authorizeRequests() - // 对于登录login 注册register 验证码captchaImage 允许匿名访问 - .antMatchers("/login", "/register", "/captchaImage","/iot/tool/register","/iot/tool/ntp","/iot/tool/download", - "/iot/tool/mqtt/auth","/iot/tool/mqtt/webhook","/auth/**/**").anonymous() - .antMatchers( - HttpMethod.GET, - "/", - "/*.html", - "/**/*.html", - "/**/*.css", - "/**/*.js", - "/profile/**" - ).permitAll() - .antMatchers("/swagger-ui.html").anonymous() - .antMatchers("/swagger-resources/**").anonymous() - .antMatchers("/webjars/**").anonymous() - .antMatchers("/*/api-docs").anonymous() - .antMatchers("/druid/**").anonymous() - /************ oauth ************************/ -// // 静态资源文件 -// .antMatchers("/oauth/logout/**","/oauth/css/**","/oauth/fonts/**").permitAll() -// // 智能音箱控制器由资源服务器管理 -// .antMatchers("/oauth/speaker/**").permitAll() - .anyRequest().authenticated() -// .and() -// .formLogin() -// .loginPage("/oauth/login") -// .permitAll() -// .and() -// .logout().logoutUrl("/oauth/logout") -// .permitAll() - /************* oauth **************************/ - .and() - .headers().frameOptions().disable(); - httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler); - // 添加JWT filter - httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); - // 添加CORS filter - httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class); - httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class); - - } - - /** - * 强散列哈希加密实现 - */ - @Bean - public BCryptPasswordEncoder bCryptPasswordEncoder() - { - return new BCryptPasswordEncoder(); - } - - /** - * 身份认证接口 - */ - @Override - protected void configure(AuthenticationManagerBuilder auth) throws Exception - { - auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder()); - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/ServerConfig.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/ServerConfig.java deleted file mode 100644 index b5b7de31..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/ServerConfig.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.ruoyi.framework.config; - -import javax.servlet.http.HttpServletRequest; -import org.springframework.stereotype.Component; -import com.ruoyi.common.utils.ServletUtils; - -/** - * 服务相关配置 - * - * @author ruoyi - */ -@Component -public class ServerConfig -{ - /** - * 获取完整的请求路径,包括:域名,端口,上下文访问路径 - * - * @return 服务地址 - */ - public String getUrl() - { - HttpServletRequest request = ServletUtils.getRequest(); - return getDomain(request); - } - - public static String getDomain(HttpServletRequest request) - { - StringBuffer url = request.getRequestURL(); - String contextPath = request.getServletContext().getContextPath(); - return url.delete(url.length() - request.getRequestURI().length(), url.length()).append(contextPath).toString(); - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java deleted file mode 100644 index 0d67c224..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.ruoyi.framework.config; - -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.ThreadPoolExecutor; -import org.apache.commons.lang3.concurrent.BasicThreadFactory; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; -import com.ruoyi.common.utils.Threads; - -/** - * 线程池配置 - * - * @author ruoyi - **/ -@Configuration -public class ThreadPoolConfig -{ - // 核心线程池大小 - private int corePoolSize = 50; - - // 最大可创建的线程数 - private int maxPoolSize = 200; - - // 队列最大长度 - private int queueCapacity = 1000; - - // 线程池维护线程所允许的空闲时间 - private int keepAliveSeconds = 300; - - @Bean(name = "threadPoolTaskExecutor") - public ThreadPoolTaskExecutor threadPoolTaskExecutor() - { - ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); - executor.setMaxPoolSize(maxPoolSize); - executor.setCorePoolSize(corePoolSize); - executor.setQueueCapacity(queueCapacity); - executor.setKeepAliveSeconds(keepAliveSeconds); - // 线程池对拒绝任务(无线程可用)的处理策略 - executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); - return executor; - } - - /** - * 执行周期性或定时任务 - */ - @Bean(name = "scheduledExecutorService") - protected ScheduledExecutorService scheduledExecutorService() - { - return new ScheduledThreadPoolExecutor(corePoolSize, - new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build()) - { - @Override - protected void afterExecute(Runnable r, Throwable t) - { - super.afterExecute(r, t); - Threads.printException(r, t); - } - }; - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java deleted file mode 100644 index 84f7e009..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.ruoyi.framework.config.properties; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Configuration; -import com.alibaba.druid.pool.DruidDataSource; - -/** - * druid 配置属性 - * - * @author ruoyi - */ -@Configuration -public class DruidProperties -{ - @Value("${spring.datasource.druid.initialSize}") - private int initialSize; - - @Value("${spring.datasource.druid.minIdle}") - private int minIdle; - - @Value("${spring.datasource.druid.maxActive}") - private int maxActive; - - @Value("${spring.datasource.druid.maxWait}") - private int maxWait; - - @Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}") - private int timeBetweenEvictionRunsMillis; - - @Value("${spring.datasource.druid.minEvictableIdleTimeMillis}") - private int minEvictableIdleTimeMillis; - - @Value("${spring.datasource.druid.maxEvictableIdleTimeMillis}") - private int maxEvictableIdleTimeMillis; - - @Value("${spring.datasource.druid.validationQuery}") - private String validationQuery; - - @Value("${spring.datasource.druid.testWhileIdle}") - private boolean testWhileIdle; - - @Value("${spring.datasource.druid.testOnBorrow}") - private boolean testOnBorrow; - - @Value("${spring.datasource.druid.testOnReturn}") - private boolean testOnReturn; - - public DruidDataSource dataSource(DruidDataSource datasource) - { - /** 配置初始化大小、最小、最大 */ - datasource.setInitialSize(initialSize); - datasource.setMaxActive(maxActive); - datasource.setMinIdle(minIdle); - - /** 配置获取连接等待超时的时间 */ - datasource.setMaxWait(maxWait); - - /** 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 */ - datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); - - /** 配置一个连接在池中最小、最大生存的时间,单位是毫秒 */ - datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); - datasource.setMaxEvictableIdleTimeMillis(maxEvictableIdleTimeMillis); - - /** - * 用来检测连接是否有效的sql,要求是一个查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。 - */ - datasource.setValidationQuery(validationQuery); - /** 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 */ - datasource.setTestWhileIdle(testWhileIdle); - /** 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 */ - datasource.setTestOnBorrow(testOnBorrow); - /** 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 */ - datasource.setTestOnReturn(testOnReturn); - return datasource; - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java deleted file mode 100644 index e70b8cfa..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.ruoyi.framework.datasource; - -import java.util.Map; -import javax.sql.DataSource; -import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; - -/** - * 动态数据源 - * - * @author ruoyi - */ -public class DynamicDataSource extends AbstractRoutingDataSource -{ - public DynamicDataSource(DataSource defaultTargetDataSource, Map targetDataSources) - { - super.setDefaultTargetDataSource(defaultTargetDataSource); - super.setTargetDataSources(targetDataSources); - super.afterPropertiesSet(); - } - - @Override - protected Object determineCurrentLookupKey() - { - return DynamicDataSourceContextHolder.getDataSourceType(); - } -} \ No newline at end of file diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java deleted file mode 100644 index 3572db91..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.ruoyi.framework.datasource; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * 数据源切换处理 - * - * @author ruoyi - */ -public class DynamicDataSourceContextHolder -{ - public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class); - - /** - * 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本, - * 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。 - */ - private static final ThreadLocal CONTEXT_HOLDER = new ThreadLocal<>(); - - /** - * 设置数据源的变量 - */ - public static void setDataSourceType(String dsType) - { - log.info("切换到{}数据源", dsType); - CONTEXT_HOLDER.set(dsType); - } - - /** - * 获得数据源的变量 - */ - public static String getDataSourceType() - { - return CONTEXT_HOLDER.get(); - } - - /** - * 清空数据源变量 - */ - public static void clearDataSourceType() - { - CONTEXT_HOLDER.remove(); - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java deleted file mode 100644 index 75757489..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.ruoyi.framework.interceptor; - -import java.lang.reflect.Method; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.springframework.stereotype.Component; -import org.springframework.web.method.HandlerMethod; -import org.springframework.web.servlet.HandlerInterceptor; -import com.alibaba.fastjson.JSONObject; -import com.ruoyi.common.annotation.RepeatSubmit; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.utils.ServletUtils; - -/** - * 防止重复提交拦截器 - * - * @author ruoyi - */ -@Component -public abstract class RepeatSubmitInterceptor implements HandlerInterceptor -{ - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception - { - if (handler instanceof HandlerMethod) - { - HandlerMethod handlerMethod = (HandlerMethod) handler; - Method method = handlerMethod.getMethod(); - RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class); - if (annotation != null) - { - if (this.isRepeatSubmit(request, annotation)) - { - AjaxResult ajaxResult = AjaxResult.error(annotation.message()); - ServletUtils.renderString(response, JSONObject.toJSONString(ajaxResult)); - return false; - } - } - return true; - } - else - { - return true; - } - } - - /** - * 验证是否重复提交由子类实现具体的防重复提交的规则 - * - * @param request - * @return - * @throws Exception - */ - public abstract boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation); -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java deleted file mode 100644 index 0138f140..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java +++ /dev/null @@ -1,114 +0,0 @@ -package com.ruoyi.framework.interceptor.impl; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import javax.servlet.http.HttpServletRequest; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; -import com.alibaba.fastjson.JSONObject; -import com.ruoyi.common.annotation.RepeatSubmit; -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.core.redis.RedisCache; -import com.ruoyi.common.filter.RepeatedlyRequestWrapper; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.http.HttpHelper; -import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor; - -/** - * 判断请求url和数据是否和上一次相同, - * 如果和上次相同,则是重复提交表单。 有效时间为10秒内。 - * - * @author ruoyi - */ -@Component -public class SameUrlDataInterceptor extends RepeatSubmitInterceptor -{ - public final String REPEAT_PARAMS = "repeatParams"; - - public final String REPEAT_TIME = "repeatTime"; - - // 令牌自定义标识 - @Value("${token.header}") - private String header; - - @Autowired - private RedisCache redisCache; - - @SuppressWarnings("unchecked") - @Override - public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation) - { - String nowParams = ""; - if (request instanceof RepeatedlyRequestWrapper) - { - RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request; - nowParams = HttpHelper.getBodyString(repeatedlyRequest); - } - - // body参数为空,获取Parameter的数据 - if (StringUtils.isEmpty(nowParams)) - { - nowParams = JSONObject.toJSONString(request.getParameterMap()); - } - Map nowDataMap = new HashMap(); - nowDataMap.put(REPEAT_PARAMS, nowParams); - nowDataMap.put(REPEAT_TIME, System.currentTimeMillis()); - - // 请求地址(作为存放cache的key值) - String url = request.getRequestURI(); - - // 唯一值(没有消息头则使用请求地址) - String submitKey = request.getHeader(header); - if (StringUtils.isEmpty(submitKey)) - { - submitKey = url; - } - - // 唯一标识(指定key + 消息头) - String cacheRepeatKey = Constants.REPEAT_SUBMIT_KEY + submitKey; - - Object sessionObj = redisCache.getCacheObject(cacheRepeatKey); - if (sessionObj != null) - { - Map sessionMap = (Map) sessionObj; - if (sessionMap.containsKey(url)) - { - Map preDataMap = (Map) sessionMap.get(url); - if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap, annotation.interval())) - { - return true; - } - } - } - Map cacheMap = new HashMap(); - cacheMap.put(url, nowDataMap); - redisCache.setCacheObject(cacheRepeatKey, cacheMap, annotation.interval(), TimeUnit.MILLISECONDS); - return false; - } - - /** - * 判断参数是否相同 - */ - private boolean compareParams(Map nowMap, Map preMap) - { - String nowParams = (String) nowMap.get(REPEAT_PARAMS); - String preParams = (String) preMap.get(REPEAT_PARAMS); - return nowParams.equals(preParams); - } - - /** - * 判断两次间隔时间 - */ - private boolean compareTime(Map nowMap, Map preMap, int interval) - { - long time1 = (Long) nowMap.get(REPEAT_TIME); - long time2 = (Long) preMap.get(REPEAT_TIME); - if ((time1 - time2) < interval) - { - return true; - } - return false; - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/manager/AsyncManager.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/manager/AsyncManager.java deleted file mode 100644 index 7387a02c..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/manager/AsyncManager.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.ruoyi.framework.manager; - -import java.util.TimerTask; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import com.ruoyi.common.utils.Threads; -import com.ruoyi.common.utils.spring.SpringUtils; - -/** - * 异步任务管理器 - * - * @author ruoyi - */ -public class AsyncManager -{ - /** - * 操作延迟10毫秒 - */ - private final int OPERATE_DELAY_TIME = 10; - - /** - * 异步操作任务调度线程池 - */ - private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService"); - - /** - * 单例模式 - */ - private AsyncManager(){} - - private static AsyncManager me = new AsyncManager(); - - public static AsyncManager me() - { - return me; - } - - /** - * 执行任务 - * - * @param task 任务 - */ - public void execute(TimerTask task) - { - executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS); - } - - /** - * 停止任务线程池 - */ - public void shutdown() - { - Threads.shutdownAndAwaitTermination(executor); - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java deleted file mode 100644 index e36ca3c5..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.ruoyi.framework.manager; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; -import javax.annotation.PreDestroy; - -/** - * 确保应用退出时能关闭后台线程 - * - * @author ruoyi - */ -@Component -public class ShutdownManager -{ - private static final Logger logger = LoggerFactory.getLogger("sys-user"); - - @PreDestroy - public void destroy() - { - shutdownAsyncManager(); - } - - /** - * 停止异步执行任务 - */ - private void shutdownAsyncManager() - { - try - { - logger.info("====关闭后台任务任务线程池===="); - AsyncManager.me().shutdown(); - } - catch (Exception e) - { - logger.error(e.getMessage(), e); - } - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java deleted file mode 100644 index 23d02308..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.ruoyi.framework.manager.factory; - -import java.util.TimerTask; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.utils.LogUtils; -import com.ruoyi.common.utils.ServletUtils; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.ip.AddressUtils; -import com.ruoyi.common.utils.ip.IpUtils; -import com.ruoyi.common.utils.spring.SpringUtils; -import com.ruoyi.system.domain.SysLogininfor; -import com.ruoyi.system.domain.SysOperLog; -import com.ruoyi.system.service.ISysLogininforService; -import com.ruoyi.system.service.ISysOperLogService; -import eu.bitwalker.useragentutils.UserAgent; - -/** - * 异步工厂(产生任务用) - * - * @author ruoyi - */ -public class AsyncFactory -{ - private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user"); - - /** - * 记录登录信息 - * - * @param username 用户名 - * @param status 状态 - * @param message 消息 - * @param args 列表 - * @return 任务task - */ - public static TimerTask recordLogininfor(final String username, final String status, final String message, - final Object... args) - { - final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent")); - final String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); - return new TimerTask() - { - @Override - public void run() - { - String address = AddressUtils.getRealAddressByIP(ip); - StringBuilder s = new StringBuilder(); - s.append(LogUtils.getBlock(ip)); - s.append(address); - s.append(LogUtils.getBlock(username)); - s.append(LogUtils.getBlock(status)); - s.append(LogUtils.getBlock(message)); - // 打印信息到日志 - sys_user_logger.info(s.toString(), args); - // 获取客户端操作系统 - String os = userAgent.getOperatingSystem().getName(); - // 获取客户端浏览器 - String browser = userAgent.getBrowser().getName(); - // 封装对象 - SysLogininfor logininfor = new SysLogininfor(); - logininfor.setUserName(username); - logininfor.setIpaddr(ip); - logininfor.setLoginLocation(address); - logininfor.setBrowser(browser); - logininfor.setOs(os); - logininfor.setMsg(message); - // 日志状态 - if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) - { - logininfor.setStatus(Constants.SUCCESS); - } - else if (Constants.LOGIN_FAIL.equals(status)) - { - logininfor.setStatus(Constants.FAIL); - } - // 插入数据 - SpringUtils.getBean(ISysLogininforService.class).insertLogininfor(logininfor); - } - }; - } - - /** - * 操作日志记录 - * - * @param operLog 操作日志信息 - * @return 任务task - */ - public static TimerTask recordOper(final SysOperLog operLog) - { - return new TimerTask() - { - @Override - public void run() - { - // 远程查询操作地点 - operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp())); - SpringUtils.getBean(ISysOperLogService.class).insertOperlog(operLog); - } - }; - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java deleted file mode 100644 index 3eb24954..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.ruoyi.framework.security.filter; - -import java.io.IOException; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; -import org.springframework.stereotype.Component; -import org.springframework.web.filter.OncePerRequestFilter; -import com.ruoyi.common.core.domain.model.LoginUser; -import com.ruoyi.common.utils.SecurityUtils; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.framework.web.service.TokenService; - -/** - * token过滤器 验证token有效性 - * - * @author ruoyi - */ -@Component -public class JwtAuthenticationTokenFilter extends OncePerRequestFilter -{ - @Autowired - private TokenService tokenService; - - @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) - throws ServletException, IOException - { - LoginUser loginUser = tokenService.getLoginUser(request); - if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication())) - { - tokenService.verifyToken(loginUser); - UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities()); - authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); - SecurityContextHolder.getContext().setAuthentication(authenticationToken); - } - chain.doFilter(request, response); - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java deleted file mode 100644 index c8145ac0..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.ruoyi.framework.security.handle; - -import java.io.IOException; -import java.io.Serializable; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.web.AuthenticationEntryPoint; -import org.springframework.stereotype.Component; -import com.alibaba.fastjson.JSON; -import com.ruoyi.common.constant.HttpStatus; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.utils.ServletUtils; -import com.ruoyi.common.utils.StringUtils; - -/** - * 认证失败处理类 返回未授权 - * - * @author ruoyi - */ -@Component -public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint, Serializable -{ - private static final long serialVersionUID = -8970718410437077606L; - - @Override - public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) - throws IOException - { -// if (isAjaxRequest(request)){ - int code = HttpStatus.UNAUTHORIZED; - String msg = StringUtils.format("请求访问:{},认证失败,无法访问系统资源", request.getRequestURI()); - ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(code, msg))); -// }else { -// response.sendRedirect("/oauth/login"); -// } - } - - - public static boolean isAjaxRequest(HttpServletRequest request) { - String ajaxFlag = request.getHeader("X-Requested-With"); - return ajaxFlag != null && "XMLHttpRequest".equals(ajaxFlag); - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java deleted file mode 100644 index e5fc11d0..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.ruoyi.framework.security.handle; - -import java.io.IOException; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.core.Authentication; -import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; -import com.alibaba.fastjson.JSON; -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.constant.HttpStatus; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.domain.model.LoginUser; -import com.ruoyi.common.utils.ServletUtils; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.framework.manager.AsyncManager; -import com.ruoyi.framework.manager.factory.AsyncFactory; -import com.ruoyi.framework.web.service.TokenService; - -/** - * 自定义退出处理类 返回成功 - * - * @author ruoyi - */ -@Configuration -public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler -{ - @Autowired - private TokenService tokenService; - - /** - * 退出处理 - * - * @return - */ - @Override - public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) - throws IOException, ServletException - { - LoginUser loginUser = tokenService.getLoginUser(request); - if (StringUtils.isNotNull(loginUser)) - { - String userName = loginUser.getUsername(); - // 删除用户缓存记录 - tokenService.delLoginUser(loginUser.getToken()); - // 记录用户退出日志 - AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGOUT, "退出成功")); - } - ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(HttpStatus.SUCCESS, "退出成功"))); - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java deleted file mode 100644 index 63b03da7..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java +++ /dev/null @@ -1,240 +0,0 @@ -package com.ruoyi.framework.web.domain; - -import java.net.UnknownHostException; -import java.util.LinkedList; -import java.util.List; -import java.util.Properties; -import com.ruoyi.common.utils.Arith; -import com.ruoyi.common.utils.ip.IpUtils; -import com.ruoyi.framework.web.domain.server.Cpu; -import com.ruoyi.framework.web.domain.server.Jvm; -import com.ruoyi.framework.web.domain.server.Mem; -import com.ruoyi.framework.web.domain.server.Sys; -import com.ruoyi.framework.web.domain.server.SysFile; -import oshi.SystemInfo; -import oshi.hardware.CentralProcessor; -import oshi.hardware.CentralProcessor.TickType; -import oshi.hardware.GlobalMemory; -import oshi.hardware.HardwareAbstractionLayer; -import oshi.software.os.FileSystem; -import oshi.software.os.OSFileStore; -import oshi.software.os.OperatingSystem; -import oshi.util.Util; - -/** - * 服务器相关信息 - * - * @author ruoyi - */ -public class Server -{ - private static final int OSHI_WAIT_SECOND = 1000; - - /** - * CPU相关信息 - */ - private Cpu cpu = new Cpu(); - - /** - * 內存相关信息 - */ - private Mem mem = new Mem(); - - /** - * JVM相关信息 - */ - private Jvm jvm = new Jvm(); - - /** - * 服务器相关信息 - */ - private Sys sys = new Sys(); - - /** - * 磁盘相关信息 - */ - private List sysFiles = new LinkedList(); - - public Cpu getCpu() - { - return cpu; - } - - public void setCpu(Cpu cpu) - { - this.cpu = cpu; - } - - public Mem getMem() - { - return mem; - } - - public void setMem(Mem mem) - { - this.mem = mem; - } - - public Jvm getJvm() - { - return jvm; - } - - public void setJvm(Jvm jvm) - { - this.jvm = jvm; - } - - public Sys getSys() - { - return sys; - } - - public void setSys(Sys sys) - { - this.sys = sys; - } - - public List getSysFiles() - { - return sysFiles; - } - - public void setSysFiles(List sysFiles) - { - this.sysFiles = sysFiles; - } - - public void copyTo() throws Exception - { - SystemInfo si = new SystemInfo(); - HardwareAbstractionLayer hal = si.getHardware(); - - setCpuInfo(hal.getProcessor()); - - setMemInfo(hal.getMemory()); - - setSysInfo(); - - setJvmInfo(); - - setSysFiles(si.getOperatingSystem()); - } - - /** - * 设置CPU信息 - */ - private void setCpuInfo(CentralProcessor processor) - { - // CPU信息 - long[] prevTicks = processor.getSystemCpuLoadTicks(); - Util.sleep(OSHI_WAIT_SECOND); - long[] ticks = processor.getSystemCpuLoadTicks(); - long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.getIndex()]; - long irq = ticks[TickType.IRQ.getIndex()] - prevTicks[TickType.IRQ.getIndex()]; - long softirq = ticks[TickType.SOFTIRQ.getIndex()] - prevTicks[TickType.SOFTIRQ.getIndex()]; - long steal = ticks[TickType.STEAL.getIndex()] - prevTicks[TickType.STEAL.getIndex()]; - long cSys = ticks[TickType.SYSTEM.getIndex()] - prevTicks[TickType.SYSTEM.getIndex()]; - long user = ticks[TickType.USER.getIndex()] - prevTicks[TickType.USER.getIndex()]; - long iowait = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()]; - long idle = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()]; - long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal; - cpu.setCpuNum(processor.getLogicalProcessorCount()); - cpu.setTotal(totalCpu); - cpu.setSys(cSys); - cpu.setUsed(user); - cpu.setWait(iowait); - cpu.setFree(idle); - } - - /** - * 设置内存信息 - */ - private void setMemInfo(GlobalMemory memory) - { - mem.setTotal(memory.getTotal()); - mem.setUsed(memory.getTotal() - memory.getAvailable()); - mem.setFree(memory.getAvailable()); - } - - /** - * 设置服务器信息 - */ - private void setSysInfo() - { - Properties props = System.getProperties(); - sys.setComputerName(IpUtils.getHostName()); - sys.setComputerIp(IpUtils.getHostIp()); - sys.setOsName(props.getProperty("os.name")); - sys.setOsArch(props.getProperty("os.arch")); - sys.setUserDir(props.getProperty("user.dir")); - } - - /** - * 设置Java虚拟机 - */ - private void setJvmInfo() throws UnknownHostException - { - Properties props = System.getProperties(); - jvm.setTotal(Runtime.getRuntime().totalMemory()); - jvm.setMax(Runtime.getRuntime().maxMemory()); - jvm.setFree(Runtime.getRuntime().freeMemory()); - jvm.setVersion(props.getProperty("java.version")); - jvm.setHome(props.getProperty("java.home")); - } - - /** - * 设置磁盘信息 - */ - private void setSysFiles(OperatingSystem os) - { - FileSystem fileSystem = os.getFileSystem(); - List fsArray = fileSystem.getFileStores(); - for (OSFileStore fs : fsArray) - { - long free = fs.getUsableSpace(); - long total = fs.getTotalSpace(); - long used = total - free; - SysFile sysFile = new SysFile(); - sysFile.setDirName(fs.getMount()); - sysFile.setSysTypeName(fs.getType()); - sysFile.setTypeName(fs.getName()); - sysFile.setTotal(convertFileSize(total)); - sysFile.setFree(convertFileSize(free)); - sysFile.setUsed(convertFileSize(used)); - sysFile.setUsage(Arith.mul(Arith.div(used, total, 4), 100)); - sysFiles.add(sysFile); - } - } - - /** - * 字节转换 - * - * @param size 字节大小 - * @return 转换后值 - */ - public String convertFileSize(long size) - { - long kb = 1024; - long mb = kb * 1024; - long gb = mb * 1024; - if (size >= gb) - { - return String.format("%.1f GB", (float) size / gb); - } - else if (size >= mb) - { - float f = (float) size / mb; - return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f); - } - else if (size >= kb) - { - float f = (float) size / kb; - return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f); - } - else - { - return String.format("%d B", size); - } - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java deleted file mode 100644 index a13a66cf..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.ruoyi.framework.web.domain.server; - -import com.ruoyi.common.utils.Arith; - -/** - * CPU相关信息 - * - * @author ruoyi - */ -public class Cpu -{ - /** - * 核心数 - */ - private int cpuNum; - - /** - * CPU总的使用率 - */ - private double total; - - /** - * CPU系统使用率 - */ - private double sys; - - /** - * CPU用户使用率 - */ - private double used; - - /** - * CPU当前等待率 - */ - private double wait; - - /** - * CPU当前空闲率 - */ - private double free; - - public int getCpuNum() - { - return cpuNum; - } - - public void setCpuNum(int cpuNum) - { - this.cpuNum = cpuNum; - } - - public double getTotal() - { - return Arith.round(Arith.mul(total, 100), 2); - } - - public void setTotal(double total) - { - this.total = total; - } - - public double getSys() - { - return Arith.round(Arith.mul(sys / total, 100), 2); - } - - public void setSys(double sys) - { - this.sys = sys; - } - - public double getUsed() - { - return Arith.round(Arith.mul(used / total, 100), 2); - } - - public void setUsed(double used) - { - this.used = used; - } - - public double getWait() - { - return Arith.round(Arith.mul(wait / total, 100), 2); - } - - public void setWait(double wait) - { - this.wait = wait; - } - - public double getFree() - { - return Arith.round(Arith.mul(free / total, 100), 2); - } - - public void setFree(double free) - { - this.free = free; - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java deleted file mode 100644 index 485d201d..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java +++ /dev/null @@ -1,122 +0,0 @@ -package com.ruoyi.framework.web.domain.server; - -import java.lang.management.ManagementFactory; -import com.ruoyi.common.utils.Arith; -import com.ruoyi.common.utils.DateUtils; - -/** - * JVM相关信息 - * - * @author ruoyi - */ -public class Jvm -{ - /** - * 当前JVM占用的内存总数(M) - */ - private double total; - - /** - * JVM最大可用内存总数(M) - */ - private double max; - - /** - * JVM空闲内存(M) - */ - private double free; - - /** - * JDK版本 - */ - private String version; - - /** - * JDK路径 - */ - private String home; - - public double getTotal() - { - return Arith.div(total, (1024 * 1024), 2); - } - - public void setTotal(double total) - { - this.total = total; - } - - public double getMax() - { - return Arith.div(max, (1024 * 1024), 2); - } - - public void setMax(double max) - { - this.max = max; - } - - public double getFree() - { - return Arith.div(free, (1024 * 1024), 2); - } - - public void setFree(double free) - { - this.free = free; - } - - public double getUsed() - { - return Arith.div(total - free, (1024 * 1024), 2); - } - - public double getUsage() - { - return Arith.mul(Arith.div(total - free, total, 4), 100); - } - - /** - * 获取JDK名称 - */ - public String getName() - { - return ManagementFactory.getRuntimeMXBean().getVmName(); - } - - public String getVersion() - { - return version; - } - - public void setVersion(String version) - { - this.version = version; - } - - public String getHome() - { - return home; - } - - public void setHome(String home) - { - this.home = home; - } - - /** - * JDK启动时间 - */ - public String getStartTime() - { - return DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, DateUtils.getServerStartDate()); - } - - /** - * JDK运行时间 - */ - public String getRunTime() - { - return DateUtils.getDatePoor(DateUtils.getNowDate(), DateUtils.getServerStartDate()); - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java deleted file mode 100644 index 13eec521..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.ruoyi.framework.web.domain.server; - -import com.ruoyi.common.utils.Arith; - -/** - * 內存相关信息 - * - * @author ruoyi - */ -public class Mem -{ - /** - * 内存总量 - */ - private double total; - - /** - * 已用内存 - */ - private double used; - - /** - * 剩余内存 - */ - private double free; - - public double getTotal() - { - return Arith.div(total, (1024 * 1024 * 1024), 2); - } - - public void setTotal(long total) - { - this.total = total; - } - - public double getUsed() - { - return Arith.div(used, (1024 * 1024 * 1024), 2); - } - - public void setUsed(long used) - { - this.used = used; - } - - public double getFree() - { - return Arith.div(free, (1024 * 1024 * 1024), 2); - } - - public void setFree(long free) - { - this.free = free; - } - - public double getUsage() - { - return Arith.mul(Arith.div(used, total, 4), 100); - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java deleted file mode 100644 index 45d64d9c..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.ruoyi.framework.web.domain.server; - -/** - * 系统相关信息 - * - * @author ruoyi - */ -public class Sys -{ - /** - * 服务器名称 - */ - private String computerName; - - /** - * 服务器Ip - */ - private String computerIp; - - /** - * 项目路径 - */ - private String userDir; - - /** - * 操作系统 - */ - private String osName; - - /** - * 系统架构 - */ - private String osArch; - - public String getComputerName() - { - return computerName; - } - - public void setComputerName(String computerName) - { - this.computerName = computerName; - } - - public String getComputerIp() - { - return computerIp; - } - - public void setComputerIp(String computerIp) - { - this.computerIp = computerIp; - } - - public String getUserDir() - { - return userDir; - } - - public void setUserDir(String userDir) - { - this.userDir = userDir; - } - - public String getOsName() - { - return osName; - } - - public void setOsName(String osName) - { - this.osName = osName; - } - - public String getOsArch() - { - return osArch; - } - - public void setOsArch(String osArch) - { - this.osArch = osArch; - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java deleted file mode 100644 index 1320cde6..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java +++ /dev/null @@ -1,114 +0,0 @@ -package com.ruoyi.framework.web.domain.server; - -/** - * 系统文件相关信息 - * - * @author ruoyi - */ -public class SysFile -{ - /** - * 盘符路径 - */ - private String dirName; - - /** - * 盘符类型 - */ - private String sysTypeName; - - /** - * 文件类型 - */ - private String typeName; - - /** - * 总大小 - */ - private String total; - - /** - * 剩余大小 - */ - private String free; - - /** - * 已经使用量 - */ - private String used; - - /** - * 资源的使用率 - */ - private double usage; - - public String getDirName() - { - return dirName; - } - - public void setDirName(String dirName) - { - this.dirName = dirName; - } - - public String getSysTypeName() - { - return sysTypeName; - } - - public void setSysTypeName(String sysTypeName) - { - this.sysTypeName = sysTypeName; - } - - public String getTypeName() - { - return typeName; - } - - public void setTypeName(String typeName) - { - this.typeName = typeName; - } - - public String getTotal() - { - return total; - } - - public void setTotal(String total) - { - this.total = total; - } - - public String getFree() - { - return free; - } - - public void setFree(String free) - { - this.free = free; - } - - public String getUsed() - { - return used; - } - - public void setUsed(String used) - { - this.used = used; - } - - public double getUsage() - { - return usage; - } - - public void setUsage(double usage) - { - this.usage = usage; - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java deleted file mode 100644 index 51dd8c54..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java +++ /dev/null @@ -1,114 +0,0 @@ -package com.ruoyi.framework.web.exception; - -import javax.servlet.http.HttpServletRequest; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.validation.BindException; -import org.springframework.web.HttpRequestMethodNotSupportedException; -import org.springframework.web.bind.MethodArgumentNotValidException; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; -import com.ruoyi.common.constant.HttpStatus; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.exception.DemoModeException; -import com.ruoyi.common.exception.ServiceException; -import com.ruoyi.common.utils.StringUtils; - -/** - * 全局异常处理器 - * - * @author ruoyi - */ -@RestControllerAdvice -public class GlobalExceptionHandler -{ - private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); - - /** - * 权限校验异常 - */ - @ExceptionHandler(AccessDeniedException.class) - public AjaxResult handleAccessDeniedException(AccessDeniedException e, HttpServletRequest request) - { - String requestURI = request.getRequestURI(); - log.error("请求地址'{}',权限校验失败'{}'", requestURI, e.getMessage()); - return AjaxResult.error(HttpStatus.FORBIDDEN, "没有权限,请联系管理员授权"); - } - - /** - * 请求方式不支持 - */ - @ExceptionHandler(HttpRequestMethodNotSupportedException.class) - public AjaxResult handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e, - HttpServletRequest request) - { - String requestURI = request.getRequestURI(); - log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod()); - return AjaxResult.error(e.getMessage()); - } - - /** - * 业务异常 - */ - @ExceptionHandler(ServiceException.class) - public AjaxResult handleServiceException(ServiceException e, HttpServletRequest request) - { - log.error(e.getMessage(), e); - Integer code = e.getCode(); - return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(e.getMessage()); - } - - /** - * 拦截未知的运行时异常 - */ - @ExceptionHandler(RuntimeException.class) - public AjaxResult handleRuntimeException(RuntimeException e, HttpServletRequest request) - { - String requestURI = request.getRequestURI(); - log.error("请求地址'{}',发生未知异常.", requestURI, e); - return AjaxResult.error(e.getMessage()); - } - - /** - * 系统异常 - */ - @ExceptionHandler(Exception.class) - public AjaxResult handleException(Exception e, HttpServletRequest request) - { - String requestURI = request.getRequestURI(); - log.error("请求地址'{}',发生系统异常.", requestURI, e); - return AjaxResult.error(e.getMessage()); - } - - /** - * 自定义验证异常 - */ - @ExceptionHandler(BindException.class) - public AjaxResult handleBindException(BindException e) - { - log.error(e.getMessage(), e); - String message = e.getAllErrors().get(0).getDefaultMessage(); - return AjaxResult.error(message); - } - - /** - * 自定义验证异常 - */ - @ExceptionHandler(MethodArgumentNotValidException.class) - public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e) - { - log.error(e.getMessage(), e); - String message = e.getBindingResult().getFieldError().getDefaultMessage(); - return AjaxResult.error(message); - } - - /** - * 演示模式异常 - */ - @ExceptionHandler(DemoModeException.class) - public AjaxResult handleDemoModeException(DemoModeException e) - { - return AjaxResult.error("演示模式,不允许操作"); - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java deleted file mode 100644 index 68b1d696..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java +++ /dev/null @@ -1,165 +0,0 @@ -package com.ruoyi.framework.web.service; - -import java.util.Set; -import org.springframework.stereotype.Service; -import org.springframework.util.CollectionUtils; -import com.ruoyi.common.core.domain.entity.SysRole; -import com.ruoyi.common.core.domain.model.LoginUser; -import com.ruoyi.common.utils.SecurityUtils; -import com.ruoyi.common.utils.StringUtils; - -/** - * RuoYi首创 自定义权限实现,ss取自SpringSecurity首字母 - * - * @author ruoyi - */ -@Service("ss") -public class PermissionService -{ - /** 所有权限标识 */ - private static final String ALL_PERMISSION = "*:*:*"; - - /** 管理员角色权限标识 */ - private static final String SUPER_ADMIN = "admin"; - - private static final String ROLE_DELIMETER = ","; - - private static final String PERMISSION_DELIMETER = ","; - - /** - * 验证用户是否具备某权限 - * - * @param permission 权限字符串 - * @return 用户是否具备某权限 - */ - public boolean hasPermi(String permission) - { - if (StringUtils.isEmpty(permission)) - { - return false; - } - LoginUser loginUser = SecurityUtils.getLoginUser(); - if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions())) - { - return false; - } - return hasPermissions(loginUser.getPermissions(), permission); - } - - /** - * 验证用户是否不具备某权限,与 hasPermi逻辑相反 - * - * @param permission 权限字符串 - * @return 用户是否不具备某权限 - */ - public boolean lacksPermi(String permission) - { - return hasPermi(permission) != true; - } - - /** - * 验证用户是否具有以下任意一个权限 - * - * @param permissions 以 PERMISSION_NAMES_DELIMETER 为分隔符的权限列表 - * @return 用户是否具有以下任意一个权限 - */ - public boolean hasAnyPermi(String permissions) - { - if (StringUtils.isEmpty(permissions)) - { - return false; - } - LoginUser loginUser = SecurityUtils.getLoginUser(); - if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions())) - { - return false; - } - Set authorities = loginUser.getPermissions(); - for (String permission : permissions.split(PERMISSION_DELIMETER)) - { - if (permission != null && hasPermissions(authorities, permission)) - { - return true; - } - } - return false; - } - - /** - * 判断用户是否拥有某个角色 - * - * @param role 角色字符串 - * @return 用户是否具备某角色 - */ - public boolean hasRole(String role) - { - if (StringUtils.isEmpty(role)) - { - return false; - } - LoginUser loginUser = SecurityUtils.getLoginUser(); - if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) - { - return false; - } - for (SysRole sysRole : loginUser.getUser().getRoles()) - { - String roleKey = sysRole.getRoleKey(); - if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role))) - { - return true; - } - } - return false; - } - - /** - * 验证用户是否不具备某角色,与 isRole逻辑相反。 - * - * @param role 角色名称 - * @return 用户是否不具备某角色 - */ - public boolean lacksRole(String role) - { - return hasRole(role) != true; - } - - /** - * 验证用户是否具有以下任意一个角色 - * - * @param roles 以 ROLE_NAMES_DELIMETER 为分隔符的角色列表 - * @return 用户是否具有以下任意一个角色 - */ - public boolean hasAnyRoles(String roles) - { - if (StringUtils.isEmpty(roles)) - { - return false; - } - LoginUser loginUser = SecurityUtils.getLoginUser(); - if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) - { - return false; - } - for (String role : roles.split(ROLE_DELIMETER)) - { - if (hasRole(role)) - { - return true; - } - } - return false; - } - - /** - * 判断是否包含权限 - * - * @param permissions 权限列表 - * @param permission 权限字符串 - * @return 用户是否具备某权限 - */ - private boolean hasPermissions(Set permissions, String permission) - { - return permissions.contains(ALL_PERMISSION) || permissions.contains(StringUtils.trim(permission)); - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java deleted file mode 100644 index 98718804..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java +++ /dev/null @@ -1,166 +0,0 @@ -package com.ruoyi.framework.web.service; - -import javax.annotation.Resource; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.stereotype.Component; -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.core.domain.entity.SysUser; -import com.ruoyi.common.core.domain.model.LoginUser; -import com.ruoyi.common.core.redis.RedisCache; -import com.ruoyi.common.exception.ServiceException; -import com.ruoyi.common.exception.user.CaptchaException; -import com.ruoyi.common.exception.user.CaptchaExpireException; -import com.ruoyi.common.exception.user.UserPasswordNotMatchException; -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.common.utils.MessageUtils; -import com.ruoyi.common.utils.ServletUtils; -import com.ruoyi.common.utils.ip.IpUtils; -import com.ruoyi.framework.manager.AsyncManager; -import com.ruoyi.framework.manager.factory.AsyncFactory; -import com.ruoyi.system.service.ISysConfigService; -import com.ruoyi.system.service.ISysUserService; - -/** - * 登录校验方法 - * - * @author ruoyi - */ -@Component -public class SysLoginService -{ - @Autowired - private TokenService tokenService; - - @Resource - private AuthenticationManager authenticationManager; - - @Autowired - private RedisCache redisCache; - - @Autowired - private ISysUserService userService; - - @Autowired - private ISysConfigService configService; - - @Autowired - private UserDetailsServiceImpl userDetailsServiceImpl; - - /** - * 登录验证 - * - * @param username 用户名 - * @param password 密码 - * @param code 验证码 - * @param uuid 唯一标识 - * @return 结果 - */ - public String login(String username, String password, String code, String uuid) - { - boolean captchaOnOff = configService.selectCaptchaOnOff(); - // 验证码开关 - if (captchaOnOff) - { - validateCaptcha(username, code, uuid); - } - return socialLogin(username,password); - } - - /** - * 第三方验证后,调用登录方法 - * @param username 用户名 - * @param password 密码 - * @return token - */ - public String socialLogin(String username, String password){ - // 用户验证 - Authentication authentication = null; - try - { - // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername - authentication = authenticationManager - .authenticate(new UsernamePasswordAuthenticationToken(username, password)); - } - catch (Exception e) - { - if (e instanceof BadCredentialsException) - { - AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"))); - throw new UserPasswordNotMatchException(); - } - else - { - AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage())); - throw new ServiceException(e.getMessage()); - } - } - AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"))); - LoginUser loginUser = (LoginUser) authentication.getPrincipal(); - recordLoginInfo(loginUser.getUserId()); - // 生成token - return tokenService.createToken(loginUser); - } - - /** - * 跳转登录认证接口 - * @param username - * @param encodePwd - * @return - */ - public String redirectLogin(String username,String encodePwd){ - UserDetails userDetails=userDetailsServiceImpl.loadUserByUsername(username); - if(!userDetails.getPassword().equals(encodePwd)){ - throw new UserPasswordNotMatchException(); - } - AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"))); - LoginUser loginUser = (LoginUser) userDetails; - recordLoginInfo(loginUser.getUserId()); - // 生成token - return tokenService.createToken(loginUser); - - } - - /** - * 校验验证码 - * - * @param username 用户名 - * @param code 验证码 - * @param uuid 唯一标识 - * @return 结果 - */ - public void validateCaptcha(String username, String code, String uuid) - { - String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid; - String captcha = redisCache.getCacheObject(verifyKey); - redisCache.deleteObject(verifyKey); - if (captcha == null) - { - AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"))); - throw new CaptchaExpireException(); - } - if (!code.equalsIgnoreCase(captcha)) - { - AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"))); - throw new CaptchaException(); - } - } - - /** - * 记录登录信息 - * - * @param userId 用户ID - */ - public void recordLoginInfo(Long userId) - { - SysUser sysUser = new SysUser(); - sysUser.setUserId(userId); - sysUser.setLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest())); - sysUser.setLoginDate(DateUtils.getNowDate()); - userService.updateUserProfile(sysUser); - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java deleted file mode 100644 index feb80387..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.ruoyi.framework.web.service; - -import java.util.HashSet; -import java.util.Set; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import com.ruoyi.common.core.domain.entity.SysUser; -import com.ruoyi.system.service.ISysMenuService; -import com.ruoyi.system.service.ISysRoleService; - -/** - * 用户权限处理 - * - * @author ruoyi - */ -@Component -public class SysPermissionService -{ - @Autowired - private ISysRoleService roleService; - - @Autowired - private ISysMenuService menuService; - - /** - * 获取角色数据权限 - * - * @param user 用户信息 - * @return 角色权限信息 - */ - public Set getRolePermission(SysUser user) - { - Set roles = new HashSet(); - // 管理员拥有所有权限 - if (user.isAdmin()) - { - roles.add("admin"); - } - else - { - roles.addAll(roleService.selectRolePermissionByUserId(user.getUserId())); - } - return roles; - } - - /** - * 获取菜单数据权限 - * - * @param user 用户信息 - * @return 菜单权限信息 - */ - public Set getMenuPermission(SysUser user) - { - Set perms = new HashSet(); - // 管理员拥有所有权限 - if (user.isAdmin()) - { - perms.add("*:*:*"); - } - else - { - perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId())); - } - return perms; - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java deleted file mode 100644 index 9d346d43..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java +++ /dev/null @@ -1,115 +0,0 @@ -package com.ruoyi.framework.web.service; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.constant.UserConstants; -import com.ruoyi.common.core.domain.entity.SysUser; -import com.ruoyi.common.core.domain.model.RegisterBody; -import com.ruoyi.common.core.redis.RedisCache; -import com.ruoyi.common.exception.user.CaptchaException; -import com.ruoyi.common.exception.user.CaptchaExpireException; -import com.ruoyi.common.utils.MessageUtils; -import com.ruoyi.common.utils.SecurityUtils; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.framework.manager.AsyncManager; -import com.ruoyi.framework.manager.factory.AsyncFactory; -import com.ruoyi.system.service.ISysConfigService; -import com.ruoyi.system.service.ISysUserService; - -/** - * 注册校验方法 - * - * @author ruoyi - */ -@Component -public class SysRegisterService -{ - @Autowired - private ISysUserService userService; - - @Autowired - private ISysConfigService configService; - - @Autowired - private RedisCache redisCache; - - /** - * 注册 - */ - public String register(RegisterBody registerBody) - { - String msg = "", username = registerBody.getUsername(), password = registerBody.getPassword(); - - boolean captchaOnOff = configService.selectCaptchaOnOff(); - // 验证码开关 - if (captchaOnOff) - { - validateCaptcha(username, registerBody.getCode(), registerBody.getUuid()); - } - - if (StringUtils.isEmpty(username)) - { - msg = "用户名不能为空"; - } - else if (StringUtils.isEmpty(password)) - { - msg = "用户密码不能为空"; - } - else if (username.length() < UserConstants.USERNAME_MIN_LENGTH - || username.length() > UserConstants.USERNAME_MAX_LENGTH) - { - msg = "账户长度必须在2到20个字符之间"; - } - else if (password.length() < UserConstants.PASSWORD_MIN_LENGTH - || password.length() > UserConstants.PASSWORD_MAX_LENGTH) - { - msg = "密码长度必须在5到20个字符之间"; - } - else if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(username))) - { - msg = "保存用户'" + username + "'失败,注册账号已存在"; - } - else - { - SysUser sysUser = new SysUser(); - sysUser.setUserName(username); - sysUser.setNickName(username); - sysUser.setPassword(SecurityUtils.encryptPassword(registerBody.getPassword())); - boolean regFlag = userService.registerUser(sysUser); - if (!regFlag) - { - msg = "注册失败,请联系系统管理人员"; - } - else - { - AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.REGISTER, - MessageUtils.message("user.register.success"))); - } - } - return msg; - } - - /** - * 校验验证码 - * - * @param username 用户名 - * @param code 验证码 - * @param uuid 唯一标识 - * @return 结果 - */ - public void validateCaptcha(String username, String code, String uuid) - { - String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid; - String captcha = redisCache.getCacheObject(verifyKey); - redisCache.deleteObject(verifyKey); - if (captcha == null) - { - throw new CaptchaExpireException(); - } - if (!code.equalsIgnoreCase(captcha)) - { - throw new CaptchaException(); - } - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java deleted file mode 100644 index 308171b5..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java +++ /dev/null @@ -1,214 +0,0 @@ -package com.ruoyi.framework.web.service; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import javax.servlet.http.HttpServletRequest; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.core.domain.model.LoginUser; -import com.ruoyi.common.core.redis.RedisCache; -import com.ruoyi.common.utils.ServletUtils; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.ip.AddressUtils; -import com.ruoyi.common.utils.ip.IpUtils; -import com.ruoyi.common.utils.uuid.IdUtils; -import eu.bitwalker.useragentutils.UserAgent; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; - -/** - * token验证处理 - * - * @author ruoyi - */ -@Component -public class TokenService { - // 令牌自定义标识 - @Value("${token.header}") - private String header; - - // 令牌秘钥 - @Value("${token.secret}") - private String secret; - - // 令牌有效期(默认30分钟) - @Value("${token.expireTime}") - private int expireTime; - - protected static final long MILLIS_SECOND = 1000; - - protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND; - - private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L; - - @Autowired - private RedisCache redisCache; - - /** - * 获取用户身份信息 - * - * @return 用户信息 - */ - public LoginUser getLoginUser(HttpServletRequest request) { - // 获取请求携带的令牌 - String token = getToken(request); - return getLoginUserByToken(token); - } - - /** - * 获取用户身份信息 - * - * @return 用户信息 - */ - public LoginUser getLoginUserByToken(String token) { - if (StringUtils.isNotEmpty(token)) { - try { - Claims claims = parseToken(token); - // 解析对应的权限以及用户信息 - String uuid = (String) claims.get(Constants.LOGIN_USER_KEY); - String userKey = getTokenKey(uuid); - LoginUser user = redisCache.getCacheObject(userKey); - return user; - } catch (Exception e) { - } - } - return null; - } - - /** - * 设置用户身份信息 - */ - public void setLoginUser(LoginUser loginUser) { - if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken())) { - refreshToken(loginUser); - } - } - - /** - * 删除用户身份信息 - */ - public void delLoginUser(String token) { - if (StringUtils.isNotEmpty(token)) { - String userKey = getTokenKey(token); - redisCache.deleteObject(userKey); - } - } - - /** - * 创建令牌 - * - * @param loginUser 用户信息 - * @return 令牌 - */ - public String createToken(LoginUser loginUser) { - String token = IdUtils.fastUUID(); - loginUser.setToken(token); - setUserAgent(loginUser); - refreshToken(loginUser); - - Map claims = new HashMap<>(); - claims.put(Constants.LOGIN_USER_KEY, token); - return createToken(claims); - } - - /** - * 验证令牌有效期,相差不足20分钟,自动刷新缓存 - * - * @param loginUser - * @return 令牌 - */ - public void verifyToken(LoginUser loginUser) { - long expireTime = loginUser.getExpireTime(); - long currentTime = System.currentTimeMillis(); - if (expireTime - currentTime <= MILLIS_MINUTE_TEN) { - refreshToken(loginUser); - } - } - - /** - * 刷新令牌有效期 - * - * @param loginUser 登录信息 - */ - public void refreshToken(LoginUser loginUser) { - loginUser.setLoginTime(System.currentTimeMillis()); - loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE); - // 根据uuid将loginUser缓存 - String userKey = getTokenKey(loginUser.getToken()); - redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES); - } - - /** - * 设置用户代理信息 - * - * @param loginUser 登录信息 - */ - public void setUserAgent(LoginUser loginUser) { - UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent")); - String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); - loginUser.setIpaddr(ip); - loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip)); - loginUser.setBrowser(userAgent.getBrowser().getName()); - loginUser.setOs(userAgent.getOperatingSystem().getName()); - } - - /** - * 从数据声明生成令牌 - * - * @param claims 数据声明 - * @return 令牌 - */ - private String createToken(Map claims) { - String token = Jwts.builder() - .setClaims(claims) - .signWith(SignatureAlgorithm.HS512, secret).compact(); - return token; - } - - /** - * 从令牌中获取数据声明 - * - * @param token 令牌 - * @return 数据声明 - */ - private Claims parseToken(String token) { - return Jwts.parser() - .setSigningKey(secret) - .parseClaimsJws(token) - .getBody(); - } - - /** - * 从令牌中获取用户名 - * - * @param token 令牌 - * @return 用户名 - */ - public String getUsernameFromToken(String token) { - Claims claims = parseToken(token); - return claims.getSubject(); - } - - /** - * 获取请求token - * - * @param request - * @return token - */ - private String getToken(HttpServletRequest request) { - String token = request.getHeader(header); - if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX)) { - token = token.replace(Constants.TOKEN_PREFIX, ""); - } - return token; - } - - private String getTokenKey(String uuid) { - return Constants.LOGIN_TOKEN_KEY + uuid; - } -} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java deleted file mode 100644 index 4b808f9c..00000000 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.ruoyi.framework.web.service; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.stereotype.Service; -import com.ruoyi.common.core.domain.entity.SysUser; -import com.ruoyi.common.core.domain.model.LoginUser; -import com.ruoyi.common.enums.UserStatus; -import com.ruoyi.common.exception.ServiceException; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.system.service.ISysUserService; - -/** - * 用户验证处理 - * - * @author ruoyi - */ -@Service -public class UserDetailsServiceImpl implements UserDetailsService -{ - private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class); - - @Autowired - private ISysUserService userService; - - @Autowired - private SysPermissionService permissionService; - - @Override - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException - { - SysUser user = userService.selectUserByUserName(username); - if (StringUtils.isNull(user)) - { - log.info("登录用户:{} 不存在.", username); - throw new ServiceException("登录用户:" + username + " 不存在"); - } - else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) - { - log.info("登录用户:{} 已被删除.", username); - throw new ServiceException("对不起,您的账号:" + username + " 已被删除"); - } - else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) - { - log.info("登录用户:{} 已被停用.", username); - throw new ServiceException("对不起,您的账号:" + username + " 已停用"); - } - UserDetails details=createLoginUser(user); - return createLoginUser(user); - } - - public UserDetails createLoginUser(SysUser user) - { - return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user)); - } -} diff --git a/springboot/wumei-generator/pom.xml b/springboot/wumei-generator/pom.xml deleted file mode 100644 index 43c0aae8..00000000 --- a/springboot/wumei-generator/pom.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - wumei - com.wumei - 3.8.0 - - 4.0.0 - - wumei-generator - - - generator代码生成 - - - - - - - org.apache.velocity - velocity-engine-core - - - - - commons-collections - commons-collections - - - - - com.wumei - wumei-common - - - - - \ No newline at end of file diff --git a/springboot/wumei-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java b/springboot/wumei-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java deleted file mode 100644 index cc4cd14c..00000000 --- a/springboot/wumei-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.ruoyi.generator.config; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.PropertySource; -import org.springframework.stereotype.Component; - -/** - * 读取代码生成相关配置 - * - * @author ruoyi - */ -@Component -@ConfigurationProperties(prefix = "gen") -@PropertySource(value = { "classpath:generator.yml" }) -public class GenConfig -{ - /** 作者 */ - public static String author; - - /** 生成包路径 */ - public static String packageName; - - /** 自动去除表前缀,默认是false */ - public static boolean autoRemovePre; - - /** 表前缀(类名不会包含表前缀) */ - public static String tablePrefix; - - public static String getAuthor() - { - return author; - } - - @Value("${author}") - public void setAuthor(String author) - { - GenConfig.author = author; - } - - public static String getPackageName() - { - return packageName; - } - - @Value("${packageName}") - public void setPackageName(String packageName) - { - GenConfig.packageName = packageName; - } - - public static boolean getAutoRemovePre() - { - return autoRemovePre; - } - - @Value("${autoRemovePre}") - public void setAutoRemovePre(boolean autoRemovePre) - { - GenConfig.autoRemovePre = autoRemovePre; - } - - public static String getTablePrefix() - { - return tablePrefix; - } - - @Value("${tablePrefix}") - public void setTablePrefix(String tablePrefix) - { - GenConfig.tablePrefix = tablePrefix; - } -} diff --git a/springboot/wumei-generator/src/main/java/com/ruoyi/generator/controller/GenController.java b/springboot/wumei-generator/src/main/java/com/ruoyi/generator/controller/GenController.java deleted file mode 100644 index 6dfe5e31..00000000 --- a/springboot/wumei-generator/src/main/java/com/ruoyi/generator/controller/GenController.java +++ /dev/null @@ -1,214 +0,0 @@ -package com.ruoyi.generator.controller; - -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import javax.servlet.http.HttpServletResponse; -import org.apache.commons.io.IOUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.page.TableDataInfo; -import com.ruoyi.common.core.text.Convert; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.generator.domain.GenTable; -import com.ruoyi.generator.domain.GenTableColumn; -import com.ruoyi.generator.service.IGenTableColumnService; -import com.ruoyi.generator.service.IGenTableService; - -/** - * 代码生成 操作处理 - * - * @author ruoyi - */ -@RestController -@RequestMapping("/tool/gen") -public class GenController extends BaseController -{ - @Autowired - private IGenTableService genTableService; - - @Autowired - private IGenTableColumnService genTableColumnService; - - /** - * 查询代码生成列表 - */ - @PreAuthorize("@ss.hasPermi('tool:gen:list')") - @GetMapping("/list") - public TableDataInfo genList(GenTable genTable) - { - startPage(); - List list = genTableService.selectGenTableList(genTable); - return getDataTable(list); - } - - /** - * 修改代码生成业务 - */ - @PreAuthorize("@ss.hasPermi('tool:gen:query')") - @GetMapping(value = "/{talbleId}") - public AjaxResult getInfo(@PathVariable Long talbleId) - { - GenTable table = genTableService.selectGenTableById(talbleId); - List tables = genTableService.selectGenTableAll(); - List list = genTableColumnService.selectGenTableColumnListByTableId(talbleId); - Map map = new HashMap(); - map.put("info", table); - map.put("rows", list); - map.put("tables", tables); - return AjaxResult.success(map); - } - - /** - * 查询数据库列表 - */ - @PreAuthorize("@ss.hasPermi('tool:gen:list')") - @GetMapping("/db/list") - public TableDataInfo dataList(GenTable genTable) - { - startPage(); - List list = genTableService.selectDbTableList(genTable); - return getDataTable(list); - } - - /** - * 查询数据表字段列表 - */ - @PreAuthorize("@ss.hasPermi('tool:gen:list')") - @GetMapping(value = "/column/{talbleId}") - public TableDataInfo columnList(Long tableId) - { - TableDataInfo dataInfo = new TableDataInfo(); - List list = genTableColumnService.selectGenTableColumnListByTableId(tableId); - dataInfo.setRows(list); - dataInfo.setTotal(list.size()); - return dataInfo; - } - - /** - * 导入表结构(保存) - */ - @PreAuthorize("@ss.hasPermi('tool:gen:import')") - @Log(title = "代码生成", businessType = BusinessType.IMPORT) - @PostMapping("/importTable") - public AjaxResult importTableSave(String tables) - { - String[] tableNames = Convert.toStrArray(tables); - // 查询表信息 - List tableList = genTableService.selectDbTableListByNames(tableNames); - genTableService.importGenTable(tableList); - return AjaxResult.success(); - } - - /** - * 修改保存代码生成业务 - */ - @PreAuthorize("@ss.hasPermi('tool:gen:edit')") - @Log(title = "代码生成", businessType = BusinessType.UPDATE) - @PutMapping - public AjaxResult editSave(@Validated @RequestBody GenTable genTable) - { - genTableService.validateEdit(genTable); - genTableService.updateGenTable(genTable); - return AjaxResult.success(); - } - - /** - * 删除代码生成 - */ - @PreAuthorize("@ss.hasPermi('tool:gen:remove')") - @Log(title = "代码生成", businessType = BusinessType.DELETE) - @DeleteMapping("/{tableIds}") - public AjaxResult remove(@PathVariable Long[] tableIds) - { - genTableService.deleteGenTableByIds(tableIds); - return AjaxResult.success(); - } - - /** - * 预览代码 - */ - @PreAuthorize("@ss.hasPermi('tool:gen:preview')") - @GetMapping("/preview/{tableId}") - public AjaxResult preview(@PathVariable("tableId") Long tableId) throws IOException - { - Map dataMap = genTableService.previewCode(tableId); - return AjaxResult.success(dataMap); - } - - /** - * 生成代码(下载方式) - */ - @PreAuthorize("@ss.hasPermi('tool:gen:code')") - @Log(title = "代码生成", businessType = BusinessType.GENCODE) - @GetMapping("/download/{tableName}") - public void download(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException - { - byte[] data = genTableService.downloadCode(tableName); - genCode(response, data); - } - - /** - * 生成代码(自定义路径) - */ - @PreAuthorize("@ss.hasPermi('tool:gen:code')") - @Log(title = "代码生成", businessType = BusinessType.GENCODE) - @GetMapping("/genCode/{tableName}") - public AjaxResult genCode(@PathVariable("tableName") String tableName) - { - genTableService.generatorCode(tableName); - return AjaxResult.success(); - } - - /** - * 同步数据库 - */ - @PreAuthorize("@ss.hasPermi('tool:gen:edit')") - @Log(title = "代码生成", businessType = BusinessType.UPDATE) - @GetMapping("/synchDb/{tableName}") - public AjaxResult synchDb(@PathVariable("tableName") String tableName) - { - genTableService.synchDb(tableName); - return AjaxResult.success(); - } - - /** - * 批量生成代码 - */ - @PreAuthorize("@ss.hasPermi('tool:gen:code')") - @Log(title = "代码生成", businessType = BusinessType.GENCODE) - @GetMapping("/batchGenCode") - public void batchGenCode(HttpServletResponse response, String tables) throws IOException - { - String[] tableNames = Convert.toStrArray(tables); - byte[] data = genTableService.downloadCode(tableNames); - genCode(response, data); - } - - /** - * 生成zip文件 - */ - private void genCode(HttpServletResponse response, byte[] data) throws IOException - { - response.reset(); - response.addHeader("Access-Control-Allow-Origin", "*"); - response.addHeader("Access-Control-Expose-Headers", "Content-Disposition"); - response.setHeader("Content-Disposition", "attachment; filename=\"ruoyi.zip\""); - response.addHeader("Content-Length", "" + data.length); - response.setContentType("application/octet-stream; charset=UTF-8"); - IOUtils.write(data, response.getOutputStream()); - } -} \ No newline at end of file diff --git a/springboot/wumei-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java b/springboot/wumei-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java deleted file mode 100644 index 269779cf..00000000 --- a/springboot/wumei-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java +++ /dev/null @@ -1,372 +0,0 @@ -package com.ruoyi.generator.domain; - -import java.util.List; -import javax.validation.Valid; -import javax.validation.constraints.NotBlank; -import org.apache.commons.lang3.ArrayUtils; -import com.ruoyi.common.constant.GenConstants; -import com.ruoyi.common.core.domain.BaseEntity; -import com.ruoyi.common.utils.StringUtils; - -/** - * 业务表 gen_table - * - * @author ruoyi - */ -public class GenTable extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 编号 */ - private Long tableId; - - /** 表名称 */ - @NotBlank(message = "表名称不能为空") - private String tableName; - - /** 表描述 */ - @NotBlank(message = "表描述不能为空") - private String tableComment; - - /** 关联父表的表名 */ - private String subTableName; - - /** 本表关联父表的外键名 */ - private String subTableFkName; - - /** 实体类名称(首字母大写) */ - @NotBlank(message = "实体类名称不能为空") - private String className; - - /** 使用的模板(crud单表操作 tree树表操作 sub主子表操作) */ - private String tplCategory; - - /** 生成包路径 */ - @NotBlank(message = "生成包路径不能为空") - private String packageName; - - /** 生成模块名 */ - @NotBlank(message = "生成模块名不能为空") - private String moduleName; - - /** 生成业务名 */ - @NotBlank(message = "生成业务名不能为空") - private String businessName; - - /** 生成功能名 */ - @NotBlank(message = "生成功能名不能为空") - private String functionName; - - /** 生成作者 */ - @NotBlank(message = "作者不能为空") - private String functionAuthor; - - /** 生成代码方式(0zip压缩包 1自定义路径) */ - private String genType; - - /** 生成路径(不填默认项目路径) */ - private String genPath; - - /** 主键信息 */ - private GenTableColumn pkColumn; - - /** 子表信息 */ - private GenTable subTable; - - /** 表列信息 */ - @Valid - private List columns; - - /** 其它生成选项 */ - private String options; - - /** 树编码字段 */ - private String treeCode; - - /** 树父编码字段 */ - private String treeParentCode; - - /** 树名称字段 */ - private String treeName; - - /** 上级菜单ID字段 */ - private String parentMenuId; - - /** 上级菜单名称字段 */ - private String parentMenuName; - - public Long getTableId() - { - return tableId; - } - - public void setTableId(Long tableId) - { - this.tableId = tableId; - } - - public String getTableName() - { - return tableName; - } - - public void setTableName(String tableName) - { - this.tableName = tableName; - } - - public String getTableComment() - { - return tableComment; - } - - public void setTableComment(String tableComment) - { - this.tableComment = tableComment; - } - - public String getSubTableName() - { - return subTableName; - } - - public void setSubTableName(String subTableName) - { - this.subTableName = subTableName; - } - - public String getSubTableFkName() - { - return subTableFkName; - } - - public void setSubTableFkName(String subTableFkName) - { - this.subTableFkName = subTableFkName; - } - - public String getClassName() - { - return className; - } - - public void setClassName(String className) - { - this.className = className; - } - - public String getTplCategory() - { - return tplCategory; - } - - public void setTplCategory(String tplCategory) - { - this.tplCategory = tplCategory; - } - - public String getPackageName() - { - return packageName; - } - - public void setPackageName(String packageName) - { - this.packageName = packageName; - } - - public String getModuleName() - { - return moduleName; - } - - public void setModuleName(String moduleName) - { - this.moduleName = moduleName; - } - - public String getBusinessName() - { - return businessName; - } - - public void setBusinessName(String businessName) - { - this.businessName = businessName; - } - - public String getFunctionName() - { - return functionName; - } - - public void setFunctionName(String functionName) - { - this.functionName = functionName; - } - - public String getFunctionAuthor() - { - return functionAuthor; - } - - public void setFunctionAuthor(String functionAuthor) - { - this.functionAuthor = functionAuthor; - } - - public String getGenType() - { - return genType; - } - - public void setGenType(String genType) - { - this.genType = genType; - } - - public String getGenPath() - { - return genPath; - } - - public void setGenPath(String genPath) - { - this.genPath = genPath; - } - - public GenTableColumn getPkColumn() - { - return pkColumn; - } - - public void setPkColumn(GenTableColumn pkColumn) - { - this.pkColumn = pkColumn; - } - - public GenTable getSubTable() - { - return subTable; - } - - public void setSubTable(GenTable subTable) - { - this.subTable = subTable; - } - - public List getColumns() - { - return columns; - } - - public void setColumns(List columns) - { - this.columns = columns; - } - - public String getOptions() - { - return options; - } - - public void setOptions(String options) - { - this.options = options; - } - - public String getTreeCode() - { - return treeCode; - } - - public void setTreeCode(String treeCode) - { - this.treeCode = treeCode; - } - - public String getTreeParentCode() - { - return treeParentCode; - } - - public void setTreeParentCode(String treeParentCode) - { - this.treeParentCode = treeParentCode; - } - - public String getTreeName() - { - return treeName; - } - - public void setTreeName(String treeName) - { - this.treeName = treeName; - } - - public String getParentMenuId() - { - return parentMenuId; - } - - public void setParentMenuId(String parentMenuId) - { - this.parentMenuId = parentMenuId; - } - - public String getParentMenuName() - { - return parentMenuName; - } - - public void setParentMenuName(String parentMenuName) - { - this.parentMenuName = parentMenuName; - } - - public boolean isSub() - { - return isSub(this.tplCategory); - } - - public static boolean isSub(String tplCategory) - { - return tplCategory != null && StringUtils.equals(GenConstants.TPL_SUB, tplCategory); - } - - public boolean isTree() - { - return isTree(this.tplCategory); - } - - public static boolean isTree(String tplCategory) - { - return tplCategory != null && StringUtils.equals(GenConstants.TPL_TREE, tplCategory); - } - - public boolean isCrud() - { - return isCrud(this.tplCategory); - } - - public static boolean isCrud(String tplCategory) - { - return tplCategory != null && StringUtils.equals(GenConstants.TPL_CRUD, tplCategory); - } - - public boolean isSuperColumn(String javaField) - { - return isSuperColumn(this.tplCategory, javaField); - } - - public static boolean isSuperColumn(String tplCategory, String javaField) - { - if (isTree(tplCategory)) - { - return StringUtils.equalsAnyIgnoreCase(javaField, - ArrayUtils.addAll(GenConstants.TREE_ENTITY, GenConstants.BASE_ENTITY)); - } - return StringUtils.equalsAnyIgnoreCase(javaField, GenConstants.BASE_ENTITY); - } -} \ No newline at end of file diff --git a/springboot/wumei-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java b/springboot/wumei-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java deleted file mode 100644 index d1733b64..00000000 --- a/springboot/wumei-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java +++ /dev/null @@ -1,373 +0,0 @@ -package com.ruoyi.generator.domain; - -import javax.validation.constraints.NotBlank; -import com.ruoyi.common.core.domain.BaseEntity; -import com.ruoyi.common.utils.StringUtils; - -/** - * 代码生成业务字段表 gen_table_column - * - * @author ruoyi - */ -public class GenTableColumn extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 编号 */ - private Long columnId; - - /** 归属表编号 */ - private Long tableId; - - /** 列名称 */ - private String columnName; - - /** 列描述 */ - private String columnComment; - - /** 列类型 */ - private String columnType; - - /** JAVA类型 */ - private String javaType; - - /** JAVA字段名 */ - @NotBlank(message = "Java属性不能为空") - private String javaField; - - /** 是否主键(1是) */ - private String isPk; - - /** 是否自增(1是) */ - private String isIncrement; - - /** 是否必填(1是) */ - private String isRequired; - - /** 是否为插入字段(1是) */ - private String isInsert; - - /** 是否编辑字段(1是) */ - private String isEdit; - - /** 是否列表字段(1是) */ - private String isList; - - /** 是否查询字段(1是) */ - private String isQuery; - - /** 查询方式(EQ等于、NE不等于、GT大于、LT小于、LIKE模糊、BETWEEN范围) */ - private String queryType; - - /** 显示类型(input文本框、textarea文本域、select下拉框、checkbox复选框、radio单选框、datetime日期控件、image图片上传控件、upload文件上传控件、editor富文本控件) */ - private String htmlType; - - /** 字典类型 */ - private String dictType; - - /** 排序 */ - private Integer sort; - - public void setColumnId(Long columnId) - { - this.columnId = columnId; - } - - public Long getColumnId() - { - return columnId; - } - - public void setTableId(Long tableId) - { - this.tableId = tableId; - } - - public Long getTableId() - { - return tableId; - } - - public void setColumnName(String columnName) - { - this.columnName = columnName; - } - - public String getColumnName() - { - return columnName; - } - - public void setColumnComment(String columnComment) - { - this.columnComment = columnComment; - } - - public String getColumnComment() - { - return columnComment; - } - - public void setColumnType(String columnType) - { - this.columnType = columnType; - } - - public String getColumnType() - { - return columnType; - } - - public void setJavaType(String javaType) - { - this.javaType = javaType; - } - - public String getJavaType() - { - return javaType; - } - - public void setJavaField(String javaField) - { - this.javaField = javaField; - } - - public String getJavaField() - { - return javaField; - } - - public String getCapJavaField() - { - return StringUtils.capitalize(javaField); - } - - public void setIsPk(String isPk) - { - this.isPk = isPk; - } - - public String getIsPk() - { - return isPk; - } - - public boolean isPk() - { - return isPk(this.isPk); - } - - public boolean isPk(String isPk) - { - return isPk != null && StringUtils.equals("1", isPk); - } - - public String getIsIncrement() - { - return isIncrement; - } - - public void setIsIncrement(String isIncrement) - { - this.isIncrement = isIncrement; - } - - public boolean isIncrement() - { - return isIncrement(this.isIncrement); - } - - public boolean isIncrement(String isIncrement) - { - return isIncrement != null && StringUtils.equals("1", isIncrement); - } - - public void setIsRequired(String isRequired) - { - this.isRequired = isRequired; - } - - public String getIsRequired() - { - return isRequired; - } - - public boolean isRequired() - { - return isRequired(this.isRequired); - } - - public boolean isRequired(String isRequired) - { - return isRequired != null && StringUtils.equals("1", isRequired); - } - - public void setIsInsert(String isInsert) - { - this.isInsert = isInsert; - } - - public String getIsInsert() - { - return isInsert; - } - - public boolean isInsert() - { - return isInsert(this.isInsert); - } - - public boolean isInsert(String isInsert) - { - return isInsert != null && StringUtils.equals("1", isInsert); - } - - public void setIsEdit(String isEdit) - { - this.isEdit = isEdit; - } - - public String getIsEdit() - { - return isEdit; - } - - public boolean isEdit() - { - return isInsert(this.isEdit); - } - - public boolean isEdit(String isEdit) - { - return isEdit != null && StringUtils.equals("1", isEdit); - } - - public void setIsList(String isList) - { - this.isList = isList; - } - - public String getIsList() - { - return isList; - } - - public boolean isList() - { - return isList(this.isList); - } - - public boolean isList(String isList) - { - return isList != null && StringUtils.equals("1", isList); - } - - public void setIsQuery(String isQuery) - { - this.isQuery = isQuery; - } - - public String getIsQuery() - { - return isQuery; - } - - public boolean isQuery() - { - return isQuery(this.isQuery); - } - - public boolean isQuery(String isQuery) - { - return isQuery != null && StringUtils.equals("1", isQuery); - } - - public void setQueryType(String queryType) - { - this.queryType = queryType; - } - - public String getQueryType() - { - return queryType; - } - - public String getHtmlType() - { - return htmlType; - } - - public void setHtmlType(String htmlType) - { - this.htmlType = htmlType; - } - - public void setDictType(String dictType) - { - this.dictType = dictType; - } - - public String getDictType() - { - return dictType; - } - - public void setSort(Integer sort) - { - this.sort = sort; - } - - public Integer getSort() - { - return sort; - } - - public boolean isSuperColumn() - { - return isSuperColumn(this.javaField); - } - - public static boolean isSuperColumn(String javaField) - { - return StringUtils.equalsAnyIgnoreCase(javaField, - // BaseEntity - "createBy", "createTime", "updateBy", "updateTime", "remark", - // TreeEntity - "parentName", "parentId", "orderNum", "ancestors"); - } - - public boolean isUsableColumn() - { - return isUsableColumn(javaField); - } - - public static boolean isUsableColumn(String javaField) - { - // isSuperColumn()中的名单用于避免生成多余Domain属性,若某些属性在生成页面时需要用到不能忽略,则放在此处白名单 - return StringUtils.equalsAnyIgnoreCase(javaField, "parentId", "orderNum", "remark"); - } - - public String readConverterExp() - { - String remarks = StringUtils.substringBetween(this.columnComment, "(", ")"); - StringBuffer sb = new StringBuffer(); - if (StringUtils.isNotEmpty(remarks)) - { - for (String value : remarks.split(" ")) - { - if (StringUtils.isNotEmpty(value)) - { - Object startStr = value.subSequence(0, 1); - String endStr = value.substring(1); - sb.append("").append(startStr).append("=").append(endStr).append(","); - } - } - return sb.deleteCharAt(sb.length() - 1).toString(); - } - else - { - return this.columnComment; - } - } -} diff --git a/springboot/wumei-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java b/springboot/wumei-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java deleted file mode 100644 index 951e1667..00000000 --- a/springboot/wumei-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.ruoyi.generator.mapper; - -import java.util.List; -import com.ruoyi.generator.domain.GenTableColumn; - -/** - * 业务字段 数据层 - * - * @author ruoyi - */ -public interface GenTableColumnMapper -{ - /** - * 根据表名称查询列信息 - * - * @param tableName 表名称 - * @return 列信息 - */ - public List selectDbTableColumnsByName(String tableName); - - /** - * 查询业务字段列表 - * - * @param tableId 业务字段编号 - * @return 业务字段集合 - */ - public List selectGenTableColumnListByTableId(Long tableId); - - /** - * 新增业务字段 - * - * @param genTableColumn 业务字段信息 - * @return 结果 - */ - public int insertGenTableColumn(GenTableColumn genTableColumn); - - /** - * 修改业务字段 - * - * @param genTableColumn 业务字段信息 - * @return 结果 - */ - public int updateGenTableColumn(GenTableColumn genTableColumn); - - /** - * 删除业务字段 - * - * @param genTableColumns 列数据 - * @return 结果 - */ - public int deleteGenTableColumns(List genTableColumns); - - /** - * 批量删除业务字段 - * - * @param ids 需要删除的数据ID - * @return 结果 - */ - public int deleteGenTableColumnByIds(Long[] ids); -} diff --git a/springboot/wumei-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java b/springboot/wumei-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java deleted file mode 100644 index 9b330df8..00000000 --- a/springboot/wumei-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.ruoyi.generator.mapper; - -import java.util.List; -import com.ruoyi.generator.domain.GenTable; - -/** - * 业务 数据层 - * - * @author ruoyi - */ -public interface GenTableMapper -{ - /** - * 查询业务列表 - * - * @param genTable 业务信息 - * @return 业务集合 - */ - public List selectGenTableList(GenTable genTable); - - /** - * 查询据库列表 - * - * @param genTable 业务信息 - * @return 数据库表集合 - */ - public List selectDbTableList(GenTable genTable); - - /** - * 查询据库列表 - * - * @param tableNames 表名称组 - * @return 数据库表集合 - */ - public List selectDbTableListByNames(String[] tableNames); - - /** - * 查询所有表信息 - * - * @return 表信息集合 - */ - public List selectGenTableAll(); - - /** - * 查询表ID业务信息 - * - * @param id 业务ID - * @return 业务信息 - */ - public GenTable selectGenTableById(Long id); - - /** - * 查询表名称业务信息 - * - * @param tableName 表名称 - * @return 业务信息 - */ - public GenTable selectGenTableByName(String tableName); - - /** - * 新增业务 - * - * @param genTable 业务信息 - * @return 结果 - */ - public int insertGenTable(GenTable genTable); - - /** - * 修改业务 - * - * @param genTable 业务信息 - * @return 结果 - */ - public int updateGenTable(GenTable genTable); - - /** - * 批量删除业务 - * - * @param ids 需要删除的数据ID - * @return 结果 - */ - public int deleteGenTableByIds(Long[] ids); -} diff --git a/springboot/wumei-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java b/springboot/wumei-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java deleted file mode 100644 index 0679689d..00000000 --- a/springboot/wumei-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.ruoyi.generator.service; - -import java.util.List; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import com.ruoyi.common.core.text.Convert; -import com.ruoyi.generator.domain.GenTableColumn; -import com.ruoyi.generator.mapper.GenTableColumnMapper; - -/** - * 业务字段 服务层实现 - * - * @author ruoyi - */ -@Service -public class GenTableColumnServiceImpl implements IGenTableColumnService -{ - @Autowired - private GenTableColumnMapper genTableColumnMapper; - - /** - * 查询业务字段列表 - * - * @param tableId 业务字段编号 - * @return 业务字段集合 - */ - @Override - public List selectGenTableColumnListByTableId(Long tableId) - { - return genTableColumnMapper.selectGenTableColumnListByTableId(tableId); - } - - /** - * 新增业务字段 - * - * @param genTableColumn 业务字段信息 - * @return 结果 - */ - @Override - public int insertGenTableColumn(GenTableColumn genTableColumn) - { - return genTableColumnMapper.insertGenTableColumn(genTableColumn); - } - - /** - * 修改业务字段 - * - * @param genTableColumn 业务字段信息 - * @return 结果 - */ - @Override - public int updateGenTableColumn(GenTableColumn genTableColumn) - { - return genTableColumnMapper.updateGenTableColumn(genTableColumn); - } - - /** - * 删除业务字段对象 - * - * @param ids 需要删除的数据ID - * @return 结果 - */ - @Override - public int deleteGenTableColumnByIds(String ids) - { - return genTableColumnMapper.deleteGenTableColumnByIds(Convert.toLongArray(ids)); - } -} diff --git a/springboot/wumei-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java b/springboot/wumei-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java deleted file mode 100644 index 499da03e..00000000 --- a/springboot/wumei-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java +++ /dev/null @@ -1,500 +0,0 @@ -package com.ruoyi.generator.service; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.StringWriter; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.apache.velocity.Template; -import org.apache.velocity.VelocityContext; -import org.apache.velocity.app.Velocity; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.constant.GenConstants; -import com.ruoyi.common.core.text.CharsetKit; -import com.ruoyi.common.exception.ServiceException; -import com.ruoyi.common.utils.SecurityUtils; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.generator.domain.GenTable; -import com.ruoyi.generator.domain.GenTableColumn; -import com.ruoyi.generator.mapper.GenTableColumnMapper; -import com.ruoyi.generator.mapper.GenTableMapper; -import com.ruoyi.generator.util.GenUtils; -import com.ruoyi.generator.util.VelocityInitializer; -import com.ruoyi.generator.util.VelocityUtils; - -/** - * 业务 服务层实现 - * - * @author ruoyi - */ -@Service -public class GenTableServiceImpl implements IGenTableService -{ - private static final Logger log = LoggerFactory.getLogger(GenTableServiceImpl.class); - - @Autowired - private GenTableMapper genTableMapper; - - @Autowired - private GenTableColumnMapper genTableColumnMapper; - - /** - * 查询业务信息 - * - * @param id 业务ID - * @return 业务信息 - */ - @Override - public GenTable selectGenTableById(Long id) - { - GenTable genTable = genTableMapper.selectGenTableById(id); - setTableFromOptions(genTable); - return genTable; - } - - /** - * 查询业务列表 - * - * @param genTable 业务信息 - * @return 业务集合 - */ - @Override - public List selectGenTableList(GenTable genTable) - { - return genTableMapper.selectGenTableList(genTable); - } - - /** - * 查询据库列表 - * - * @param genTable 业务信息 - * @return 数据库表集合 - */ - @Override - public List selectDbTableList(GenTable genTable) - { - return genTableMapper.selectDbTableList(genTable); - } - - /** - * 查询据库列表 - * - * @param tableNames 表名称组 - * @return 数据库表集合 - */ - @Override - public List selectDbTableListByNames(String[] tableNames) - { - return genTableMapper.selectDbTableListByNames(tableNames); - } - - /** - * 查询所有表信息 - * - * @return 表信息集合 - */ - @Override - public List selectGenTableAll() - { - return genTableMapper.selectGenTableAll(); - } - - /** - * 修改业务 - * - * @param genTable 业务信息 - * @return 结果 - */ - @Override - @Transactional - public void updateGenTable(GenTable genTable) - { - String options = JSON.toJSONString(genTable.getParams()); - genTable.setOptions(options); - int row = genTableMapper.updateGenTable(genTable); - if (row > 0) - { - for (GenTableColumn cenTableColumn : genTable.getColumns()) - { - genTableColumnMapper.updateGenTableColumn(cenTableColumn); - } - } - } - - /** - * 删除业务对象 - * - * @param tableIds 需要删除的数据ID - * @return 结果 - */ - @Override - @Transactional - public void deleteGenTableByIds(Long[] tableIds) - { - genTableMapper.deleteGenTableByIds(tableIds); - genTableColumnMapper.deleteGenTableColumnByIds(tableIds); - } - - /** - * 导入表结构 - * - * @param tableList 导入表列表 - */ - @Override - @Transactional - public void importGenTable(List tableList) - { - String operName = SecurityUtils.getUsername(); - try - { - for (GenTable table : tableList) - { - String tableName = table.getTableName(); - GenUtils.initTable(table, operName); - int row = genTableMapper.insertGenTable(table); - if (row > 0) - { - // 保存列信息 - List genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName); - for (GenTableColumn column : genTableColumns) - { - GenUtils.initColumnField(column, table); - genTableColumnMapper.insertGenTableColumn(column); - } - } - } - } - catch (Exception e) - { - throw new ServiceException("导入失败:" + e.getMessage()); - } - } - - /** - * 预览代码 - * - * @param tableId 表编号 - * @return 预览数据列表 - */ - @Override - public Map previewCode(Long tableId) - { - Map dataMap = new LinkedHashMap<>(); - // 查询表信息 - GenTable table = genTableMapper.selectGenTableById(tableId); - // 设置主子表信息 - setSubTable(table); - // 设置主键列信息 - setPkColumn(table); - VelocityInitializer.initVelocity(); - - VelocityContext context = VelocityUtils.prepareContext(table); - - // 获取模板列表 - List templates = VelocityUtils.getTemplateList(table.getTplCategory()); - for (String template : templates) - { - // 渲染模板 - StringWriter sw = new StringWriter(); - Template tpl = Velocity.getTemplate(template, Constants.UTF8); - tpl.merge(context, sw); - dataMap.put(template, sw.toString()); - } - return dataMap; - } - - /** - * 生成代码(下载方式) - * - * @param tableName 表名称 - * @return 数据 - */ - @Override - public byte[] downloadCode(String tableName) - { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - ZipOutputStream zip = new ZipOutputStream(outputStream); - generatorCode(tableName, zip); - IOUtils.closeQuietly(zip); - return outputStream.toByteArray(); - } - - /** - * 生成代码(自定义路径) - * - * @param tableName 表名称 - */ - @Override - public void generatorCode(String tableName) - { - // 查询表信息 - GenTable table = genTableMapper.selectGenTableByName(tableName); - // 设置主子表信息 - setSubTable(table); - // 设置主键列信息 - setPkColumn(table); - - VelocityInitializer.initVelocity(); - - VelocityContext context = VelocityUtils.prepareContext(table); - - // 获取模板列表 - List templates = VelocityUtils.getTemplateList(table.getTplCategory()); - for (String template : templates) - { - if (!StringUtils.containsAny(template, "sql.vm", "api.js.vm", "index.vue.vm", "index-tree.vue.vm")) - { - // 渲染模板 - StringWriter sw = new StringWriter(); - Template tpl = Velocity.getTemplate(template, Constants.UTF8); - tpl.merge(context, sw); - try - { - String path = getGenPath(table, template); - FileUtils.writeStringToFile(new File(path), sw.toString(), CharsetKit.UTF_8); - } - catch (IOException e) - { - throw new ServiceException("渲染模板失败,表名:" + table.getTableName()); - } - } - } - } - - /** - * 同步数据库 - * - * @param tableName 表名称 - */ - @Override - @Transactional - public void synchDb(String tableName) - { - GenTable table = genTableMapper.selectGenTableByName(tableName); - List tableColumns = table.getColumns(); - List tableColumnNames = tableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList()); - - List dbTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName); - if (StringUtils.isEmpty(dbTableColumns)) - { - throw new ServiceException("同步数据失败,原表结构不存在"); - } - List dbTableColumnNames = dbTableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList()); - - dbTableColumns.forEach(column -> { - if (!tableColumnNames.contains(column.getColumnName())) - { - GenUtils.initColumnField(column, table); - genTableColumnMapper.insertGenTableColumn(column); - } - }); - - List delColumns = tableColumns.stream().filter(column -> !dbTableColumnNames.contains(column.getColumnName())).collect(Collectors.toList()); - if (StringUtils.isNotEmpty(delColumns)) - { - genTableColumnMapper.deleteGenTableColumns(delColumns); - } - } - - /** - * 批量生成代码(下载方式) - * - * @param tableNames 表数组 - * @return 数据 - */ - @Override - public byte[] downloadCode(String[] tableNames) - { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - ZipOutputStream zip = new ZipOutputStream(outputStream); - for (String tableName : tableNames) - { - generatorCode(tableName, zip); - } - IOUtils.closeQuietly(zip); - return outputStream.toByteArray(); - } - - /** - * 查询表信息并生成代码 - */ - private void generatorCode(String tableName, ZipOutputStream zip) - { - // 查询表信息 - GenTable table = genTableMapper.selectGenTableByName(tableName); - // 设置主子表信息 - setSubTable(table); - // 设置主键列信息 - setPkColumn(table); - - VelocityInitializer.initVelocity(); - - VelocityContext context = VelocityUtils.prepareContext(table); - - // 获取模板列表 - List templates = VelocityUtils.getTemplateList(table.getTplCategory()); - for (String template : templates) - { - // 渲染模板 - StringWriter sw = new StringWriter(); - Template tpl = Velocity.getTemplate(template, Constants.UTF8); - tpl.merge(context, sw); - try - { - // 添加到zip - zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table))); - IOUtils.write(sw.toString(), zip, Constants.UTF8); - IOUtils.closeQuietly(sw); - zip.flush(); - zip.closeEntry(); - } - catch (IOException e) - { - log.error("渲染模板失败,表名:" + table.getTableName(), e); - } - } - } - - /** - * 修改保存参数校验 - * - * @param genTable 业务信息 - */ - @Override - public void validateEdit(GenTable genTable) - { - if (GenConstants.TPL_TREE.equals(genTable.getTplCategory())) - { - String options = JSON.toJSONString(genTable.getParams()); - JSONObject paramsObj = JSONObject.parseObject(options); - if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_CODE))) - { - throw new ServiceException("树编码字段不能为空"); - } - else if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_PARENT_CODE))) - { - throw new ServiceException("树父编码字段不能为空"); - } - else if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_NAME))) - { - throw new ServiceException("树名称字段不能为空"); - } - else if (GenConstants.TPL_SUB.equals(genTable.getTplCategory())) - { - if (StringUtils.isEmpty(genTable.getSubTableName())) - { - throw new ServiceException("关联子表的表名不能为空"); - } - else if (StringUtils.isEmpty(genTable.getSubTableFkName())) - { - throw new ServiceException("子表关联的外键名不能为空"); - } - } - } - } - - /** - * 设置主键列信息 - * - * @param table 业务表信息 - */ - public void setPkColumn(GenTable table) - { - for (GenTableColumn column : table.getColumns()) - { - if (column.isPk()) - { - table.setPkColumn(column); - break; - } - } - if (StringUtils.isNull(table.getPkColumn())) - { - table.setPkColumn(table.getColumns().get(0)); - } - if (GenConstants.TPL_SUB.equals(table.getTplCategory())) - { - for (GenTableColumn column : table.getSubTable().getColumns()) - { - if (column.isPk()) - { - table.getSubTable().setPkColumn(column); - break; - } - } - if (StringUtils.isNull(table.getSubTable().getPkColumn())) - { - table.getSubTable().setPkColumn(table.getSubTable().getColumns().get(0)); - } - } - } - - /** - * 设置主子表信息 - * - * @param table 业务表信息 - */ - public void setSubTable(GenTable table) - { - String subTableName = table.getSubTableName(); - if (StringUtils.isNotEmpty(subTableName)) - { - table.setSubTable(genTableMapper.selectGenTableByName(subTableName)); - } - } - - /** - * 设置代码生成其他选项值 - * - * @param genTable 设置后的生成对象 - */ - public void setTableFromOptions(GenTable genTable) - { - JSONObject paramsObj = JSONObject.parseObject(genTable.getOptions()); - if (StringUtils.isNotNull(paramsObj)) - { - String treeCode = paramsObj.getString(GenConstants.TREE_CODE); - String treeParentCode = paramsObj.getString(GenConstants.TREE_PARENT_CODE); - String treeName = paramsObj.getString(GenConstants.TREE_NAME); - String parentMenuId = paramsObj.getString(GenConstants.PARENT_MENU_ID); - String parentMenuName = paramsObj.getString(GenConstants.PARENT_MENU_NAME); - - genTable.setTreeCode(treeCode); - genTable.setTreeParentCode(treeParentCode); - genTable.setTreeName(treeName); - genTable.setParentMenuId(parentMenuId); - genTable.setParentMenuName(parentMenuName); - } - } - - /** - * 获取代码生成地址 - * - * @param table 业务表信息 - * @param template 模板文件路径 - * @return 生成地址 - */ - public static String getGenPath(GenTable table, String template) - { - String genPath = table.getGenPath(); - if (StringUtils.equals(genPath, "/")) - { - return System.getProperty("user.dir") + File.separator + "src" + File.separator + VelocityUtils.getFileName(template, table); - } - return genPath + File.separator + VelocityUtils.getFileName(template, table); - } -} \ No newline at end of file diff --git a/springboot/wumei-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java b/springboot/wumei-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java deleted file mode 100644 index 3037f707..00000000 --- a/springboot/wumei-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.ruoyi.generator.service; - -import java.util.List; -import com.ruoyi.generator.domain.GenTableColumn; - -/** - * 业务字段 服务层 - * - * @author ruoyi - */ -public interface IGenTableColumnService -{ - /** - * 查询业务字段列表 - * - * @param tableId 业务字段编号 - * @return 业务字段集合 - */ - public List selectGenTableColumnListByTableId(Long tableId); - - /** - * 新增业务字段 - * - * @param genTableColumn 业务字段信息 - * @return 结果 - */ - public int insertGenTableColumn(GenTableColumn genTableColumn); - - /** - * 修改业务字段 - * - * @param genTableColumn 业务字段信息 - * @return 结果 - */ - public int updateGenTableColumn(GenTableColumn genTableColumn); - - /** - * 删除业务字段信息 - * - * @param ids 需要删除的数据ID - * @return 结果 - */ - public int deleteGenTableColumnByIds(String ids); -} diff --git a/springboot/wumei-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java b/springboot/wumei-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java deleted file mode 100644 index 9d53f95f..00000000 --- a/springboot/wumei-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java +++ /dev/null @@ -1,121 +0,0 @@ -package com.ruoyi.generator.service; - -import java.util.List; -import java.util.Map; -import com.ruoyi.generator.domain.GenTable; - -/** - * 业务 服务层 - * - * @author ruoyi - */ -public interface IGenTableService -{ - /** - * 查询业务列表 - * - * @param genTable 业务信息 - * @return 业务集合 - */ - public List selectGenTableList(GenTable genTable); - - /** - * 查询据库列表 - * - * @param genTable 业务信息 - * @return 数据库表集合 - */ - public List selectDbTableList(GenTable genTable); - - /** - * 查询据库列表 - * - * @param tableNames 表名称组 - * @return 数据库表集合 - */ - public List selectDbTableListByNames(String[] tableNames); - - /** - * 查询所有表信息 - * - * @return 表信息集合 - */ - public List selectGenTableAll(); - - /** - * 查询业务信息 - * - * @param id 业务ID - * @return 业务信息 - */ - public GenTable selectGenTableById(Long id); - - /** - * 修改业务 - * - * @param genTable 业务信息 - * @return 结果 - */ - public void updateGenTable(GenTable genTable); - - /** - * 删除业务信息 - * - * @param tableIds 需要删除的表数据ID - * @return 结果 - */ - public void deleteGenTableByIds(Long[] tableIds); - - /** - * 导入表结构 - * - * @param tableList 导入表列表 - */ - public void importGenTable(List tableList); - - /** - * 预览代码 - * - * @param tableId 表编号 - * @return 预览数据列表 - */ - public Map previewCode(Long tableId); - - /** - * 生成代码(下载方式) - * - * @param tableName 表名称 - * @return 数据 - */ - public byte[] downloadCode(String tableName); - - /** - * 生成代码(自定义路径) - * - * @param tableName 表名称 - * @return 数据 - */ - public void generatorCode(String tableName); - - /** - * 同步数据库 - * - * @param tableName 表名称 - */ - public void synchDb(String tableName); - - /** - * 批量生成代码(下载方式) - * - * @param tableNames 表数组 - * @return 数据 - */ - public byte[] downloadCode(String[] tableNames); - - /** - * 修改保存参数校验 - * - * @param genTable 业务信息 - */ - public void validateEdit(GenTable genTable); -} diff --git a/springboot/wumei-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java b/springboot/wumei-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java deleted file mode 100644 index 06c68214..00000000 --- a/springboot/wumei-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java +++ /dev/null @@ -1,258 +0,0 @@ -package com.ruoyi.generator.util; - -import java.util.Arrays; -import org.apache.commons.lang3.RegExUtils; -import com.ruoyi.common.constant.GenConstants; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.generator.config.GenConfig; -import com.ruoyi.generator.domain.GenTable; -import com.ruoyi.generator.domain.GenTableColumn; - -/** - * 代码生成器 工具类 - * - * @author ruoyi - */ -public class GenUtils -{ - /** - * 初始化表信息 - */ - public static void initTable(GenTable genTable, String operName) - { - genTable.setClassName(convertClassName(genTable.getTableName())); - genTable.setPackageName(GenConfig.getPackageName()); - genTable.setModuleName(getModuleName(GenConfig.getPackageName())); - genTable.setBusinessName(getBusinessName(genTable.getTableName())); - genTable.setFunctionName(replaceText(genTable.getTableComment())); - genTable.setFunctionAuthor(GenConfig.getAuthor()); - genTable.setCreateBy(operName); - } - - /** - * 初始化列属性字段 - */ - public static void initColumnField(GenTableColumn column, GenTable table) - { - String dataType = getDbType(column.getColumnType()); - String columnName = column.getColumnName(); - column.setTableId(table.getTableId()); - column.setCreateBy(table.getCreateBy()); - // 设置java字段名 - column.setJavaField(StringUtils.toCamelCase(columnName)); - // 设置默认类型 - column.setJavaType(GenConstants.TYPE_STRING); - - if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType) || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType)) - { - // 字符串长度超过500设置为文本域 - Integer columnLength = getColumnLength(column.getColumnType()); - String htmlType = columnLength >= 500 || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType) ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT; - column.setHtmlType(htmlType); - } - else if (arraysContains(GenConstants.COLUMNTYPE_TIME, dataType)) - { - column.setJavaType(GenConstants.TYPE_DATE); - column.setHtmlType(GenConstants.HTML_DATETIME); - } - else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType)) - { - column.setHtmlType(GenConstants.HTML_INPUT); - - // 如果是浮点型 统一用BigDecimal - String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ","); - if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0) - { - column.setJavaType(GenConstants.TYPE_BIGDECIMAL); - } - // 如果是整形 - else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10) - { - column.setJavaType(GenConstants.TYPE_INTEGER); - } - // 长整形 - else - { - column.setJavaType(GenConstants.TYPE_LONG); - } - } - - // 插入字段(默认所有字段都需要插入) - column.setIsInsert(GenConstants.REQUIRE); - - // 编辑字段 - if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName) && !column.isPk()) - { - column.setIsEdit(GenConstants.REQUIRE); - } - // 列表字段 - if (!arraysContains(GenConstants.COLUMNNAME_NOT_LIST, columnName) && !column.isPk()) - { - column.setIsList(GenConstants.REQUIRE); - } - // 查询字段 - if (!arraysContains(GenConstants.COLUMNNAME_NOT_QUERY, columnName) && !column.isPk()) - { - column.setIsQuery(GenConstants.REQUIRE); - } - - // 查询字段类型 - if (StringUtils.endsWithIgnoreCase(columnName, "name")) - { - column.setQueryType(GenConstants.QUERY_LIKE); - } - // 状态字段设置单选框 - if (StringUtils.endsWithIgnoreCase(columnName, "status")) - { - column.setHtmlType(GenConstants.HTML_RADIO); - } - // 类型&性别字段设置下拉框 - else if (StringUtils.endsWithIgnoreCase(columnName, "type") - || StringUtils.endsWithIgnoreCase(columnName, "sex")) - { - column.setHtmlType(GenConstants.HTML_SELECT); - } - // 图片字段设置图片上传控件 - else if (StringUtils.endsWithIgnoreCase(columnName, "image")) - { - column.setHtmlType(GenConstants.HTML_IMAGE_UPLOAD); - } - // 文件字段设置文件上传控件 - else if (StringUtils.endsWithIgnoreCase(columnName, "file")) - { - column.setHtmlType(GenConstants.HTML_FILE_UPLOAD); - } - // 内容字段设置富文本控件 - else if (StringUtils.endsWithIgnoreCase(columnName, "content")) - { - column.setHtmlType(GenConstants.HTML_EDITOR); - } - } - - /** - * 校验数组是否包含指定值 - * - * @param arr 数组 - * @param targetValue 值 - * @return 是否包含 - */ - public static boolean arraysContains(String[] arr, String targetValue) - { - return Arrays.asList(arr).contains(targetValue); - } - - /** - * 获取模块名 - * - * @param packageName 包名 - * @return 模块名 - */ - public static String getModuleName(String packageName) - { - int lastIndex = packageName.lastIndexOf("."); - int nameLength = packageName.length(); - String moduleName = StringUtils.substring(packageName, lastIndex + 1, nameLength); - return moduleName; - } - - /** - * 获取业务名 - * - * @param tableName 表名 - * @return 业务名 - */ - public static String getBusinessName(String tableName) - { - int lastIndex = tableName.lastIndexOf("_"); - int nameLength = tableName.length(); - String businessName = StringUtils.substring(tableName, lastIndex + 1, nameLength); - return businessName; - } - - /** - * 表名转换成Java类名 - * - * @param tableName 表名称 - * @return 类名 - */ - public static String convertClassName(String tableName) - { - boolean autoRemovePre = GenConfig.getAutoRemovePre(); - String tablePrefix = GenConfig.getTablePrefix(); - if (autoRemovePre && StringUtils.isNotEmpty(tablePrefix)) - { - String[] searchList = StringUtils.split(tablePrefix, ","); - tableName = replaceFirst(tableName, searchList); - } - return StringUtils.convertToCamelCase(tableName); - } - - /** - * 批量替换前缀 - * - * @param replacementm 替换值 - * @param searchList 替换列表 - * @return - */ - public static String replaceFirst(String replacementm, String[] searchList) - { - String text = replacementm; - for (String searchString : searchList) - { - if (replacementm.startsWith(searchString)) - { - text = replacementm.replaceFirst(searchString, ""); - break; - } - } - return text; - } - - /** - * 关键字替换 - * - * @param text 需要被替换的名字 - * @return 替换后的名字 - */ - public static String replaceText(String text) - { - return RegExUtils.replaceAll(text, "(?:表|若依)", ""); - } - - /** - * 获取数据库类型字段 - * - * @param columnType 列类型 - * @return 截取后的列类型 - */ - public static String getDbType(String columnType) - { - if (StringUtils.indexOf(columnType, "(") > 0) - { - return StringUtils.substringBefore(columnType, "("); - } - else - { - return columnType; - } - } - - /** - * 获取字段长度 - * - * @param columnType 列类型 - * @return 截取后的列类型 - */ - public static Integer getColumnLength(String columnType) - { - if (StringUtils.indexOf(columnType, "(") > 0) - { - String length = StringUtils.substringBetween(columnType, "(", ")"); - return Integer.valueOf(length); - } - else - { - return 0; - } - } -} diff --git a/springboot/wumei-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java b/springboot/wumei-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java deleted file mode 100644 index 9f694038..00000000 --- a/springboot/wumei-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.ruoyi.generator.util; - -import java.util.Properties; -import org.apache.velocity.app.Velocity; -import com.ruoyi.common.constant.Constants; - -/** - * VelocityEngine工厂 - * - * @author ruoyi - */ -public class VelocityInitializer -{ - /** - * 初始化vm方法 - */ - public static void initVelocity() - { - Properties p = new Properties(); - try - { - // 加载classpath目录下的vm文件 - p.setProperty("resource.loader.file.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); - // 定义字符集 - p.setProperty(Velocity.INPUT_ENCODING, Constants.UTF8); - // 初始化Velocity引擎,指定配置Properties - Velocity.init(p); - } - catch (Exception e) - { - throw new RuntimeException(e); - } - } -} diff --git a/springboot/wumei-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java b/springboot/wumei-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java deleted file mode 100644 index 5a580d1b..00000000 --- a/springboot/wumei-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java +++ /dev/null @@ -1,385 +0,0 @@ -package com.ruoyi.generator.util; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import org.apache.velocity.VelocityContext; -import com.alibaba.fastjson.JSONObject; -import com.ruoyi.common.constant.GenConstants; -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.generator.domain.GenTable; -import com.ruoyi.generator.domain.GenTableColumn; - -/** - * 模板处理工具类 - * - * @author ruoyi - */ -public class VelocityUtils -{ - /** 项目空间路径 */ - private static final String PROJECT_PATH = "main/java"; - - /** mybatis空间路径 */ - private static final String MYBATIS_PATH = "main/resources/mapper"; - - /** 默认上级菜单,系统工具 */ - private static final String DEFAULT_PARENT_MENU_ID = "3"; - - /** - * 设置模板变量信息 - * - * @return 模板列表 - */ - public static VelocityContext prepareContext(GenTable genTable) - { - String moduleName = genTable.getModuleName(); - String businessName = genTable.getBusinessName(); - String packageName = genTable.getPackageName(); - String tplCategory = genTable.getTplCategory(); - String functionName = genTable.getFunctionName(); - - VelocityContext velocityContext = new VelocityContext(); - velocityContext.put("tplCategory", genTable.getTplCategory()); - velocityContext.put("tableName", genTable.getTableName()); - velocityContext.put("functionName", StringUtils.isNotEmpty(functionName) ? functionName : "【请填写功能名称】"); - velocityContext.put("ClassName", genTable.getClassName()); - velocityContext.put("className", StringUtils.uncapitalize(genTable.getClassName())); - velocityContext.put("moduleName", genTable.getModuleName()); - velocityContext.put("BusinessName", StringUtils.capitalize(genTable.getBusinessName())); - velocityContext.put("businessName", genTable.getBusinessName()); - velocityContext.put("basePackage", getPackagePrefix(packageName)); - velocityContext.put("packageName", packageName); - velocityContext.put("author", genTable.getFunctionAuthor()); - velocityContext.put("datetime", DateUtils.getDate()); - velocityContext.put("pkColumn", genTable.getPkColumn()); - velocityContext.put("importList", getImportList(genTable)); - velocityContext.put("permissionPrefix", getPermissionPrefix(moduleName, businessName)); - velocityContext.put("columns", genTable.getColumns()); - velocityContext.put("table", genTable); - velocityContext.put("dicts", getDicts(genTable)); - setMenuVelocityContext(velocityContext, genTable); - if (GenConstants.TPL_TREE.equals(tplCategory)) - { - setTreeVelocityContext(velocityContext, genTable); - } - if (GenConstants.TPL_SUB.equals(tplCategory)) - { - setSubVelocityContext(velocityContext, genTable); - } - return velocityContext; - } - - public static void setMenuVelocityContext(VelocityContext context, GenTable genTable) - { - String options = genTable.getOptions(); - JSONObject paramsObj = JSONObject.parseObject(options); - String parentMenuId = getParentMenuId(paramsObj); - context.put("parentMenuId", parentMenuId); - } - - public static void setTreeVelocityContext(VelocityContext context, GenTable genTable) - { - String options = genTable.getOptions(); - JSONObject paramsObj = JSONObject.parseObject(options); - String treeCode = getTreecode(paramsObj); - String treeParentCode = getTreeParentCode(paramsObj); - String treeName = getTreeName(paramsObj); - - context.put("treeCode", treeCode); - context.put("treeParentCode", treeParentCode); - context.put("treeName", treeName); - context.put("expandColumn", getExpandColumn(genTable)); - if (paramsObj.containsKey(GenConstants.TREE_PARENT_CODE)) - { - context.put("tree_parent_code", paramsObj.getString(GenConstants.TREE_PARENT_CODE)); - } - if (paramsObj.containsKey(GenConstants.TREE_NAME)) - { - context.put("tree_name", paramsObj.getString(GenConstants.TREE_NAME)); - } - } - - public static void setSubVelocityContext(VelocityContext context, GenTable genTable) - { - GenTable subTable = genTable.getSubTable(); - String subTableName = genTable.getSubTableName(); - String subTableFkName = genTable.getSubTableFkName(); - String subClassName = genTable.getSubTable().getClassName(); - String subTableFkClassName = StringUtils.convertToCamelCase(subTableFkName); - - context.put("subTable", subTable); - context.put("subTableName", subTableName); - context.put("subTableFkName", subTableFkName); - context.put("subTableFkClassName", subTableFkClassName); - context.put("subTableFkclassName", StringUtils.uncapitalize(subTableFkClassName)); - context.put("subClassName", subClassName); - context.put("subclassName", StringUtils.uncapitalize(subClassName)); - context.put("subImportList", getImportList(genTable.getSubTable())); - } - - /** - * 获取模板信息 - * - * @return 模板列表 - */ - public static List getTemplateList(String tplCategory) - { - List templates = new ArrayList(); - templates.add("vm/java/domain.java.vm"); - templates.add("vm/java/mapper.java.vm"); - templates.add("vm/java/service.java.vm"); - templates.add("vm/java/serviceImpl.java.vm"); - templates.add("vm/java/controller.java.vm"); - templates.add("vm/xml/mapper.xml.vm"); - templates.add("vm/sql/sql.vm"); - templates.add("vm/js/api.js.vm"); - if (GenConstants.TPL_CRUD.equals(tplCategory)) - { - templates.add("vm/vue/index.vue.vm"); - } - else if (GenConstants.TPL_TREE.equals(tplCategory)) - { - templates.add("vm/vue/index-tree.vue.vm"); - } - else if (GenConstants.TPL_SUB.equals(tplCategory)) - { - templates.add("vm/vue/index.vue.vm"); - templates.add("vm/java/sub-domain.java.vm"); - } - return templates; - } - - /** - * 获取文件名 - */ - public static String getFileName(String template, GenTable genTable) - { - // 文件名称 - String fileName = ""; - // 包路径 - String packageName = genTable.getPackageName(); - // 模块名 - String moduleName = genTable.getModuleName(); - // 大写类名 - String className = genTable.getClassName(); - // 业务名称 - String businessName = genTable.getBusinessName(); - - String javaPath = PROJECT_PATH + "/" + StringUtils.replace(packageName, ".", "/"); - String mybatisPath = MYBATIS_PATH + "/" + moduleName; - String vuePath = "vue"; - - if (template.contains("domain.java.vm")) - { - fileName = StringUtils.format("{}/domain/{}.java", javaPath, className); - } - if (template.contains("sub-domain.java.vm") && StringUtils.equals(GenConstants.TPL_SUB, genTable.getTplCategory())) - { - fileName = StringUtils.format("{}/domain/{}.java", javaPath, genTable.getSubTable().getClassName()); - } - else if (template.contains("mapper.java.vm")) - { - fileName = StringUtils.format("{}/mapper/{}Mapper.java", javaPath, className); - } - else if (template.contains("service.java.vm")) - { - fileName = StringUtils.format("{}/service/I{}Service.java", javaPath, className); - } - else if (template.contains("serviceImpl.java.vm")) - { - fileName = StringUtils.format("{}/service/impl/{}ServiceImpl.java", javaPath, className); - } - else if (template.contains("controller.java.vm")) - { - fileName = StringUtils.format("{}/controller/{}Controller.java", javaPath, className); - } - else if (template.contains("mapper.xml.vm")) - { - fileName = StringUtils.format("{}/{}Mapper.xml", mybatisPath, className); - } - else if (template.contains("sql.vm")) - { - fileName = businessName + "Menu.sql"; - } - else if (template.contains("api.js.vm")) - { - fileName = StringUtils.format("{}/api/{}/{}.js", vuePath, moduleName, businessName); - } - else if (template.contains("index.vue.vm")) - { - fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName); - } - else if (template.contains("index-tree.vue.vm")) - { - fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName); - } - return fileName; - } - - /** - * 获取包前缀 - * - * @param packageName 包名称 - * @return 包前缀名称 - */ - public static String getPackagePrefix(String packageName) - { - int lastIndex = packageName.lastIndexOf("."); - String basePackage = StringUtils.substring(packageName, 0, lastIndex); - return basePackage; - } - - /** - * 根据列类型获取导入包 - * - * @param genTable 业务表对象 - * @return 返回需要导入的包列表 - */ - public static HashSet getImportList(GenTable genTable) - { - List columns = genTable.getColumns(); - GenTable subGenTable = genTable.getSubTable(); - HashSet importList = new HashSet(); - if (StringUtils.isNotNull(subGenTable)) - { - importList.add("java.util.List"); - } - for (GenTableColumn column : columns) - { - if (!column.isSuperColumn() && GenConstants.TYPE_DATE.equals(column.getJavaType())) - { - importList.add("java.util.Date"); - importList.add("com.fasterxml.jackson.annotation.JsonFormat"); - } - else if (!column.isSuperColumn() && GenConstants.TYPE_BIGDECIMAL.equals(column.getJavaType())) - { - importList.add("java.math.BigDecimal"); - } - } - return importList; - } - - /** - * 根据列类型获取字典组 - * - * @param genTable 业务表对象 - * @return 返回字典组 - */ - public static String getDicts(GenTable genTable) - { - List columns = genTable.getColumns(); - List dicts = new ArrayList(); - for (GenTableColumn column : columns) - { - if (!column.isSuperColumn() && StringUtils.isNotEmpty(column.getDictType()) && StringUtils.equalsAny( - column.getHtmlType(), - new String[] { GenConstants.HTML_SELECT, GenConstants.HTML_RADIO, GenConstants.HTML_CHECKBOX })) - { - dicts.add("'" + column.getDictType() + "'"); - } - } - return StringUtils.join(dicts, ", "); - } - - /** - * 获取权限前缀 - * - * @param moduleName 模块名称 - * @param businessName 业务名称 - * @return 返回权限前缀 - */ - public static String getPermissionPrefix(String moduleName, String businessName) - { - return StringUtils.format("{}:{}", moduleName, businessName); - } - - /** - * 获取上级菜单ID字段 - * - * @param paramsObj 生成其他选项 - * @return 上级菜单ID字段 - */ - public static String getParentMenuId(JSONObject paramsObj) - { - if (StringUtils.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.PARENT_MENU_ID) - && StringUtils.isNotEmpty(paramsObj.getString(GenConstants.PARENT_MENU_ID))) - { - return paramsObj.getString(GenConstants.PARENT_MENU_ID); - } - return DEFAULT_PARENT_MENU_ID; - } - - /** - * 获取树编码 - * - * @param paramsObj 生成其他选项 - * @return 树编码 - */ - public static String getTreecode(JSONObject paramsObj) - { - if (paramsObj.containsKey(GenConstants.TREE_CODE)) - { - return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_CODE)); - } - return StringUtils.EMPTY; - } - - /** - * 获取树父编码 - * - * @param paramsObj 生成其他选项 - * @return 树父编码 - */ - public static String getTreeParentCode(JSONObject paramsObj) - { - if (paramsObj.containsKey(GenConstants.TREE_PARENT_CODE)) - { - return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_PARENT_CODE)); - } - return StringUtils.EMPTY; - } - - /** - * 获取树名称 - * - * @param paramsObj 生成其他选项 - * @return 树名称 - */ - public static String getTreeName(JSONObject paramsObj) - { - if (paramsObj.containsKey(GenConstants.TREE_NAME)) - { - return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_NAME)); - } - return StringUtils.EMPTY; - } - - /** - * 获取需要在哪一列上面显示展开按钮 - * - * @param genTable 业务表对象 - * @return 展开按钮列序号 - */ - public static int getExpandColumn(GenTable genTable) - { - String options = genTable.getOptions(); - JSONObject paramsObj = JSONObject.parseObject(options); - String treeName = paramsObj.getString(GenConstants.TREE_NAME); - int num = 0; - for (GenTableColumn column : genTable.getColumns()) - { - if (column.isList()) - { - num++; - String columnName = column.getColumnName(); - if (columnName.equals(treeName)) - { - break; - } - } - } - return num; - } -} diff --git a/springboot/wumei-generator/src/main/resources/generator.yml b/springboot/wumei-generator/src/main/resources/generator.yml deleted file mode 100644 index 3f2ae2e1..00000000 --- a/springboot/wumei-generator/src/main/resources/generator.yml +++ /dev/null @@ -1,10 +0,0 @@ -# 代码生成 -gen: - # 作者 - author: kerwincui - # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool - packageName: com.ruoyi.iot - # 自动去除表前缀,默认是false - autoRemovePre: true - # 表前缀(生成类名不会包含表前缀,多个用逗号分隔) - tablePrefix: iot_ \ No newline at end of file diff --git a/springboot/wumei-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml b/springboot/wumei-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml deleted file mode 100644 index 5fa790f5..00000000 --- a/springboot/wumei-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - select column_id, table_id, column_name, column_comment, column_type, java_type, java_field, is_pk, is_increment, is_required, is_insert, is_edit, is_list, is_query, query_type, html_type, dict_type, sort, create_by, create_time, update_by, update_time from gen_table_column - - - - - - - - insert into gen_table_column ( - table_id, - column_name, - column_comment, - column_type, - java_type, - java_field, - is_pk, - is_increment, - is_required, - is_insert, - is_edit, - is_list, - is_query, - query_type, - html_type, - dict_type, - sort, - create_by, - create_time - )values( - #{tableId}, - #{columnName}, - #{columnComment}, - #{columnType}, - #{javaType}, - #{javaField}, - #{isPk}, - #{isIncrement}, - #{isRequired}, - #{isInsert}, - #{isEdit}, - #{isList}, - #{isQuery}, - #{queryType}, - #{htmlType}, - #{dictType}, - #{sort}, - #{createBy}, - sysdate() - ) - - - - update gen_table_column - - column_comment = #{columnComment}, - java_type = #{javaType}, - java_field = #{javaField}, - is_insert = #{isInsert}, - is_edit = #{isEdit}, - is_list = #{isList}, - is_query = #{isQuery}, - is_required = #{isRequired}, - query_type = #{queryType}, - html_type = #{htmlType}, - dict_type = #{dictType}, - sort = #{sort}, - update_by = #{updateBy}, - update_time = sysdate() - - where column_id = #{columnId} - - - - delete from gen_table_column where table_id in - - #{tableId} - - - - - delete from gen_table_column where column_id in - - #{item.columnId} - - - - \ No newline at end of file diff --git a/springboot/wumei-generator/src/main/resources/mapper/generator/GenTableMapper.xml b/springboot/wumei-generator/src/main/resources/mapper/generator/GenTableMapper.xml deleted file mode 100644 index b605e906..00000000 --- a/springboot/wumei-generator/src/main/resources/mapper/generator/GenTableMapper.xml +++ /dev/null @@ -1,202 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - select table_id, table_name, table_comment, sub_table_name, sub_table_fk_name, class_name, tpl_category, package_name, module_name, business_name, function_name, function_author, gen_type, gen_path, options, create_by, create_time, update_by, update_time, remark from gen_table - - - - - - - - - - - - - - - - - - insert into gen_table ( - table_name, - table_comment, - class_name, - tpl_category, - package_name, - module_name, - business_name, - function_name, - function_author, - gen_type, - gen_path, - remark, - create_by, - create_time - )values( - #{tableName}, - #{tableComment}, - #{className}, - #{tplCategory}, - #{packageName}, - #{moduleName}, - #{businessName}, - #{functionName}, - #{functionAuthor}, - #{genType}, - #{genPath}, - #{remark}, - #{createBy}, - sysdate() - ) - - - - update gen_table - - table_name = #{tableName}, - table_comment = #{tableComment}, - sub_table_name = #{subTableName}, - sub_table_fk_name = #{subTableFkName}, - class_name = #{className}, - function_author = #{functionAuthor}, - gen_type = #{genType}, - gen_path = #{genPath}, - tpl_category = #{tplCategory}, - package_name = #{packageName}, - module_name = #{moduleName}, - business_name = #{businessName}, - function_name = #{functionName}, - options = #{options}, - update_by = #{updateBy}, - remark = #{remark}, - update_time = sysdate() - - where table_id = #{tableId} - - - - delete from gen_table where table_id in - - #{tableId} - - - - \ No newline at end of file diff --git a/springboot/wumei-generator/src/main/resources/vm/java/controller.java.vm b/springboot/wumei-generator/src/main/resources/vm/java/controller.java.vm deleted file mode 100644 index ab19cf51..00000000 --- a/springboot/wumei-generator/src/main/resources/vm/java/controller.java.vm +++ /dev/null @@ -1,115 +0,0 @@ -package ${packageName}.controller; - -import java.util.List; -import javax.servlet.http.HttpServletResponse; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.enums.BusinessType; -import ${packageName}.domain.${ClassName}; -import ${packageName}.service.I${ClassName}Service; -import com.ruoyi.common.utils.poi.ExcelUtil; -#if($table.crud || $table.sub) -import com.ruoyi.common.core.page.TableDataInfo; -#elseif($table.tree) -#end - -/** - * ${functionName}Controller - * - * @author ${author} - * @date ${datetime} - */ -@RestController -@RequestMapping("/${moduleName}/${businessName}") -public class ${ClassName}Controller extends BaseController -{ - @Autowired - private I${ClassName}Service ${className}Service; - - /** - * 查询${functionName}列表 - */ - @PreAuthorize("@ss.hasPermi('${permissionPrefix}:list')") - @GetMapping("/list") -#if($table.crud || $table.sub) - public TableDataInfo list(${ClassName} ${className}) - { - startPage(); - List<${ClassName}> list = ${className}Service.select${ClassName}List(${className}); - return getDataTable(list); - } -#elseif($table.tree) - public AjaxResult list(${ClassName} ${className}) - { - List<${ClassName}> list = ${className}Service.select${ClassName}List(${className}); - return AjaxResult.success(list); - } -#end - - /** - * 导出${functionName}列表 - */ - @PreAuthorize("@ss.hasPermi('${permissionPrefix}:export')") - @Log(title = "${functionName}", businessType = BusinessType.EXPORT) - @PostMapping("/export") - public void export(HttpServletResponse response, ${ClassName} ${className}) - { - List<${ClassName}> list = ${className}Service.select${ClassName}List(${className}); - ExcelUtil<${ClassName}> util = new ExcelUtil<${ClassName}>(${ClassName}.class); - util.exportExcel(response, list, "${functionName}数据"); - } - - /** - * 获取${functionName}详细信息 - */ - @PreAuthorize("@ss.hasPermi('${permissionPrefix}:query')") - @GetMapping(value = "/{${pkColumn.javaField}}") - public AjaxResult getInfo(@PathVariable("${pkColumn.javaField}") ${pkColumn.javaType} ${pkColumn.javaField}) - { - return AjaxResult.success(${className}Service.select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField})); - } - - /** - * 新增${functionName} - */ - @PreAuthorize("@ss.hasPermi('${permissionPrefix}:add')") - @Log(title = "${functionName}", businessType = BusinessType.INSERT) - @PostMapping - public AjaxResult add(@RequestBody ${ClassName} ${className}) - { - return toAjax(${className}Service.insert${ClassName}(${className})); - } - - /** - * 修改${functionName} - */ - @PreAuthorize("@ss.hasPermi('${permissionPrefix}:edit')") - @Log(title = "${functionName}", businessType = BusinessType.UPDATE) - @PutMapping - public AjaxResult edit(@RequestBody ${ClassName} ${className}) - { - return toAjax(${className}Service.update${ClassName}(${className})); - } - - /** - * 删除${functionName} - */ - @PreAuthorize("@ss.hasPermi('${permissionPrefix}:remove')") - @Log(title = "${functionName}", businessType = BusinessType.DELETE) - @DeleteMapping("/{${pkColumn.javaField}s}") - public AjaxResult remove(@PathVariable ${pkColumn.javaType}[] ${pkColumn.javaField}s) - { - return toAjax(${className}Service.delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaField}s)); - } -} diff --git a/springboot/wumei-generator/src/main/resources/vm/java/domain.java.vm b/springboot/wumei-generator/src/main/resources/vm/java/domain.java.vm deleted file mode 100644 index bd51c177..00000000 --- a/springboot/wumei-generator/src/main/resources/vm/java/domain.java.vm +++ /dev/null @@ -1,105 +0,0 @@ -package ${packageName}.domain; - -#foreach ($import in $importList) -import ${import}; -#end -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.common.annotation.Excel; -#if($table.crud || $table.sub) -import com.ruoyi.common.core.domain.BaseEntity; -#elseif($table.tree) -import com.ruoyi.common.core.domain.TreeEntity; -#end - -/** - * ${functionName}对象 ${tableName} - * - * @author ${author} - * @date ${datetime} - */ -#if($table.crud || $table.sub) -#set($Entity="BaseEntity") -#elseif($table.tree) -#set($Entity="TreeEntity") -#end -public class ${ClassName} extends ${Entity} -{ - private static final long serialVersionUID = 1L; - -#foreach ($column in $columns) -#if(!$table.isSuperColumn($column.javaField)) - /** $column.columnComment */ -#if($column.list) -#set($parentheseIndex=$column.columnComment.indexOf("(")) -#if($parentheseIndex != -1) -#set($comment=$column.columnComment.substring(0, $parentheseIndex)) -#else -#set($comment=$column.columnComment) -#end -#if($parentheseIndex != -1) - @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()") -#elseif($column.javaType == 'Date') - @JsonFormat(pattern = "yyyy-MM-dd") - @Excel(name = "${comment}", width = 30, dateFormat = "yyyy-MM-dd") -#else - @Excel(name = "${comment}") -#end -#end - private $column.javaType $column.javaField; - -#end -#end -#if($table.sub) - /** $table.subTable.functionName信息 */ - private List<${subClassName}> ${subclassName}List; - -#end -#foreach ($column in $columns) -#if(!$table.isSuperColumn($column.javaField)) -#if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]")) -#set($AttrName=$column.javaField) -#else -#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) -#end - public void set${AttrName}($column.javaType $column.javaField) - { - this.$column.javaField = $column.javaField; - } - - public $column.javaType get${AttrName}() - { - return $column.javaField; - } -#end -#end - -#if($table.sub) - public List<${subClassName}> get${subClassName}List() - { - return ${subclassName}List; - } - - public void set${subClassName}List(List<${subClassName}> ${subclassName}List) - { - this.${subclassName}List = ${subclassName}List; - } - -#end - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) -#foreach ($column in $columns) -#if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]")) -#set($AttrName=$column.javaField) -#else -#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) -#end - .append("${column.javaField}", get${AttrName}()) -#end -#if($table.sub) - .append("${subclassName}List", get${subClassName}List()) -#end - .toString(); - } -} diff --git a/springboot/wumei-generator/src/main/resources/vm/js/api.js.vm b/springboot/wumei-generator/src/main/resources/vm/js/api.js.vm deleted file mode 100644 index 9295524a..00000000 --- a/springboot/wumei-generator/src/main/resources/vm/js/api.js.vm +++ /dev/null @@ -1,44 +0,0 @@ -import request from '@/utils/request' - -// 查询${functionName}列表 -export function list${BusinessName}(query) { - return request({ - url: '/${moduleName}/${businessName}/list', - method: 'get', - params: query - }) -} - -// 查询${functionName}详细 -export function get${BusinessName}(${pkColumn.javaField}) { - return request({ - url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField}, - method: 'get' - }) -} - -// 新增${functionName} -export function add${BusinessName}(data) { - return request({ - url: '/${moduleName}/${businessName}', - method: 'post', - data: data - }) -} - -// 修改${functionName} -export function update${BusinessName}(data) { - return request({ - url: '/${moduleName}/${businessName}', - method: 'put', - data: data - }) -} - -// 删除${functionName} -export function del${BusinessName}(${pkColumn.javaField}) { - return request({ - url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField}, - method: 'delete' - }) -} diff --git a/springboot/wumei-generator/src/main/resources/vm/sql/sql.vm b/springboot/wumei-generator/src/main/resources/vm/sql/sql.vm deleted file mode 100644 index 05755835..00000000 --- a/springboot/wumei-generator/src/main/resources/vm/sql/sql.vm +++ /dev/null @@ -1,22 +0,0 @@ --- 菜单 SQL -insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) -values('${functionName}', '${parentMenuId}', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 0, 'C', '0', '0', '${permissionPrefix}:list', '#', 'admin', sysdate(), '', null, '${functionName}菜单'); - --- 按钮父菜单ID -SELECT @parentId := LAST_INSERT_ID(); - --- 按钮 SQL -insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) -values('${functionName}查询', @parentId, '1', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:query', '#', 'admin', sysdate(), '', null, ''); - -insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) -values('${functionName}新增', @parentId, '2', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:add', '#', 'admin', sysdate(), '', null, ''); - -insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) -values('${functionName}修改', @parentId, '3', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:edit', '#', 'admin', sysdate(), '', null, ''); - -insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) -values('${functionName}删除', @parentId, '4', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:remove', '#', 'admin', sysdate(), '', null, ''); - -insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) -values('${functionName}导出', @parentId, '5', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:export', '#', 'admin', sysdate(), '', null, ''); \ No newline at end of file diff --git a/springboot/wumei-generator/src/main/resources/vm/vue/index-tree.vue.vm b/springboot/wumei-generator/src/main/resources/vm/vue/index-tree.vue.vm deleted file mode 100644 index d862133d..00000000 --- a/springboot/wumei-generator/src/main/resources/vm/vue/index-tree.vue.vm +++ /dev/null @@ -1,476 +0,0 @@ - - - diff --git a/springboot/wumei-generator/src/main/resources/vm/vue/index.vue.vm b/springboot/wumei-generator/src/main/resources/vm/vue/index.vue.vm deleted file mode 100644 index 56a942ef..00000000 --- a/springboot/wumei-generator/src/main/resources/vm/vue/index.vue.vm +++ /dev/null @@ -1,567 +0,0 @@ - - - diff --git a/springboot/wumei-generator/src/main/resources/vm/xml/mapper.xml.vm b/springboot/wumei-generator/src/main/resources/vm/xml/mapper.xml.vm deleted file mode 100644 index 0ceb3d85..00000000 --- a/springboot/wumei-generator/src/main/resources/vm/xml/mapper.xml.vm +++ /dev/null @@ -1,135 +0,0 @@ - - - - - -#foreach ($column in $columns) - -#end - -#if($table.sub) - - - - - - -#foreach ($column in $subTable.columns) - -#end - -#end - - - select#foreach($column in $columns) $column.columnName#if($foreach.count != $columns.size()),#end#end from ${tableName} - - - - - - - - insert into ${tableName} - -#foreach($column in $columns) -#if($column.columnName != $pkColumn.columnName || !$pkColumn.increment) - $column.columnName, -#end -#end - - -#foreach($column in $columns) -#if($column.columnName != $pkColumn.columnName || !$pkColumn.increment) - #{$column.javaField}, -#end -#end - - - - - update ${tableName} - -#foreach($column in $columns) -#if($column.columnName != $pkColumn.columnName) - $column.columnName = #{$column.javaField}, -#end -#end - - where ${pkColumn.columnName} = #{${pkColumn.javaField}} - - - - delete from ${tableName} where ${pkColumn.columnName} = #{${pkColumn.javaField}} - - - - delete from ${tableName} where ${pkColumn.columnName} in - - #{${pkColumn.javaField}} - - -#if($table.sub) - - - delete from ${subTableName} where ${subTableFkName} in - - #{${subTableFkclassName}} - - - - - delete from ${subTableName} where ${subTableFkName} = #{${subTableFkclassName}} - - - - insert into ${subTableName}(#foreach($column in $subTable.columns) $column.columnName#if($foreach.count != $subTable.columns.size()),#end#end) values - - (#foreach($column in $subTable.columns) #{item.$column.javaField}#if($foreach.count != $subTable.columns.size()),#end#end) - - -#end - \ No newline at end of file diff --git a/springboot/wumei-iot/pom.xml b/springboot/wumei-iot/pom.xml deleted file mode 100644 index c716b72a..00000000 --- a/springboot/wumei-iot/pom.xml +++ /dev/null @@ -1,103 +0,0 @@ - - - - wumei - com.wumei - 3.8.0 - - 4.0.0 - - wumei-iot - - - 物美智能-开源生活物联网平台 - - - - - - - com.wumei - wumei-common - - - io.swagger - swagger-annotations - 1.6.2 - compile - - - org.apache.velocity - velocity-engine-core - - - com.wumei - wumei-framework - - - com.wumei - wumei-quartz - - - - org.springframework.security.oauth - spring-security-oauth2 - 2.5.1.RELEASE - - - org.springframework.boot - spring-boot-starter-thymeleaf - - - - org.springframework.boot - spring-boot-configuration-processor - true - - - org.eclipse.paho - org.eclipse.paho.client.mqttv3 - 1.2.5 - - - - - org.springframework - spring-context - 5.2.3.RELEASE - - - com.wumei - wumei-quartz - 3.8.0 - - - - - me.zhyd.oauth - JustAuth - ${justAuth.version} - - - - - com.dtflys.forest - forest-spring-boot-starter - ${forest.version} - - - - - - com.taosdata.jdbc - taos-jdbcdriver - 2.0.38 - - - - - - - \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/AlertController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/AlertController.java deleted file mode 100644 index d864eb88..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/AlertController.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.ruoyi.iot.controller; - -import java.util.List; -import javax.servlet.http.HttpServletResponse; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.iot.domain.Alert; -import com.ruoyi.iot.service.IAlertService; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.common.core.page.TableDataInfo; - -/** - * 设备告警Controller - * - * @author kerwincui - * @date 2022-01-13 - */ -@RestController -@RequestMapping("/iot/alert") -public class AlertController extends BaseController -{ - @Autowired - private IAlertService alertService; - - /** - * 查询设备告警列表 - */ - @PreAuthorize("@ss.hasPermi('iot:alert:list')") - @GetMapping("/list") - public TableDataInfo list(Alert alert) - { - startPage(); - List list = alertService.selectAlertList(alert); - return getDataTable(list); - } - - /** - * 导出设备告警列表 - */ - @PreAuthorize("@ss.hasPermi('iot:alert:export')") - @Log(title = "设备告警", businessType = BusinessType.EXPORT) - @PostMapping("/export") - public void export(HttpServletResponse response, Alert alert) - { - List list = alertService.selectAlertList(alert); - ExcelUtil util = new ExcelUtil(Alert.class); - util.exportExcel(response, list, "设备告警数据"); - } - - /** - * 获取设备告警详细信息 - */ - @PreAuthorize("@ss.hasPermi('iot:alert:query')") - @GetMapping(value = "/{alertId}") - public AjaxResult getInfo(@PathVariable("alertId") Long alertId) - { - return AjaxResult.success(alertService.selectAlertByAlertId(alertId)); - } - - /** - * 新增设备告警 - */ - @PreAuthorize("@ss.hasPermi('iot:alert:add')") - @Log(title = "设备告警", businessType = BusinessType.INSERT) - @PostMapping - public AjaxResult add(@RequestBody Alert alert) - { - return toAjax(alertService.insertAlert(alert)); - } - - /** - * 修改设备告警 - */ - @PreAuthorize("@ss.hasPermi('iot:alert:edit')") - @Log(title = "设备告警", businessType = BusinessType.UPDATE) - @PutMapping - public AjaxResult edit(@RequestBody Alert alert) - { - return toAjax(alertService.updateAlert(alert)); - } - - /** - * 删除设备告警 - */ - @PreAuthorize("@ss.hasPermi('iot:alert:remove')") - @Log(title = "设备告警", businessType = BusinessType.DELETE) - @DeleteMapping("/{alertIds}") - public AjaxResult remove(@PathVariable Long[] alertIds) - { - return toAjax(alertService.deleteAlertByAlertIds(alertIds)); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/AlertLogController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/AlertLogController.java deleted file mode 100644 index e089cae3..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/AlertLogController.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.ruoyi.iot.controller; - -import java.util.List; -import javax.servlet.http.HttpServletResponse; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.iot.domain.AlertLog; -import com.ruoyi.iot.service.IAlertLogService; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.common.core.page.TableDataInfo; - -/** - * 设备告警Controller - * - * @author kerwincui - * @date 2022-01-13 - */ -@RestController -@RequestMapping("/iot/alertLog") -public class AlertLogController extends BaseController -{ - @Autowired - private IAlertLogService alertLogService; - - /** - * 查询设备告警列表 - */ - @PreAuthorize("@ss.hasPermi('iot:alert:list')") - @GetMapping("/list") - public TableDataInfo list(AlertLog alertLog) - { - startPage(); - List list = alertLogService.selectAlertLogList(alertLog); - return getDataTable(list); - } - - /** - * 导出设备告警列表 - */ - @PreAuthorize("@ss.hasPermi('iot:alert:export')") - @Log(title = "设备告警", businessType = BusinessType.EXPORT) - @PostMapping("/export") - public void export(HttpServletResponse response, AlertLog alertLog) - { - List list = alertLogService.selectAlertLogList(alertLog); - ExcelUtil util = new ExcelUtil(AlertLog.class); - util.exportExcel(response, list, "设备告警数据"); - } - - /** - * 获取设备告警详细信息 - */ - @PreAuthorize("@ss.hasPermi('iot:alert:query')") - @GetMapping(value = "/{alertLogId}") - public AjaxResult getInfo(@PathVariable("alertLogId") Long alertLogId) - { - return AjaxResult.success(alertLogService.selectAlertLogByAlertLogId(alertLogId)); - } - - /** - * 新增设备告警 - */ - @PreAuthorize("@ss.hasPermi('iot:alert:add')") - @Log(title = "设备告警", businessType = BusinessType.INSERT) - @PostMapping - public AjaxResult add(@RequestBody AlertLog alertLog) - { - return toAjax(alertLogService.insertAlertLog(alertLog)); - } - - /** - * 修改设备告警 - */ - @PreAuthorize("@ss.hasPermi('iot:alert:edit')") - @Log(title = "设备告警", businessType = BusinessType.UPDATE) - @PutMapping - public AjaxResult edit(@RequestBody AlertLog alertLog) - { - return toAjax(alertLogService.updateAlertLog(alertLog)); - } - - /** - * 删除设备告警 - */ - @PreAuthorize("@ss.hasPermi('iot:alert:remove')") - @Log(title = "设备告警", businessType = BusinessType.DELETE) - @DeleteMapping("/{alertLogIds}") - public AjaxResult remove(@PathVariable Long[] alertLogIds) - { - return toAjax(alertLogService.deleteAlertLogByAlertLogIds(alertLogIds)); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/AuthResourceController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/AuthResourceController.java deleted file mode 100644 index c54c9cdf..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/AuthResourceController.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.ruoyi.iot.controller; - -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.page.TableDataInfo; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.iot.domain.Alert; -import com.ruoyi.iot.service.IAlertService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; - -import javax.servlet.http.HttpServletResponse; -import java.util.List; - -/** - * 设备告警Controller - * - * @author kerwincui - * @date 2022-01-13 - */ -@RestController -@RequestMapping("/oauth/resource") -public class AuthResourceController extends BaseController -{ - /** - * 查询设备告警列表 - */ - @GetMapping("/product") - public String findAll() { - return "查询产品列表成功!"; - } - - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/CategoryController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/CategoryController.java deleted file mode 100644 index da436a70..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/CategoryController.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.ruoyi.iot.controller; - -import java.util.ArrayList; -import java.util.List; -import javax.servlet.http.HttpServletResponse; - -import com.ruoyi.common.core.domain.entity.SysRole; -import com.ruoyi.common.core.domain.entity.SysUser; -import com.ruoyi.common.core.page.TableDataInfo; -import com.ruoyi.iot.model.IdAndName; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.iot.domain.Category; -import com.ruoyi.iot.service.ICategoryService; -import com.ruoyi.common.utils.poi.ExcelUtil; - -/** - * 产品分类Controller - * - * @author kerwincui - * @date 2021-12-16 - */ -@Api(tags = "产品分类") -@RestController -@RequestMapping("/iot/category") -public class CategoryController extends BaseController -{ - @Autowired - private ICategoryService categoryService; - - /** - * 查询产品分类列表 - */ - @PreAuthorize("@ss.hasPermi('iot:category:list')") - @GetMapping("/list") - @ApiOperation("分类分页列表") - public TableDataInfo list(Category category) - { - startPage(); - return getDataTable(categoryService.selectCategoryList(category)); - } - - /** - * 查询产品简短分类列表 - */ - @PreAuthorize("@ss.hasPermi('iot:category:list')") - @GetMapping("/shortlist") - @ApiOperation("分类简短列表") - public AjaxResult shortlist() - { - return AjaxResult.success(categoryService.selectCategoryShortList()); - } - - /** - * 导出产品分类列表 - */ - @PreAuthorize("@ss.hasPermi('iot:category:export')") - @Log(title = "产品分类", businessType = BusinessType.EXPORT) - @PostMapping("/export") - @ApiOperation("导出分类") - public void export(HttpServletResponse response, Category category) - { - List list = categoryService.selectCategoryList(category); - ExcelUtil util = new ExcelUtil(Category.class); - util.exportExcel(response, list, "产品分类数据"); - } - - /** - * 获取产品分类详细信息 - */ - @ApiOperation("获取分类详情") - @PreAuthorize("@ss.hasPermi('iot:category:query')") - @GetMapping(value = "/{categoryId}") - public AjaxResult getInfo(@PathVariable("categoryId") Long categoryId) - { - return AjaxResult.success(categoryService.selectCategoryByCategoryId(categoryId)); - } - - /** - * 新增产品分类 - */ - @PreAuthorize("@ss.hasPermi('iot:category:add')") - @Log(title = "产品分类", businessType = BusinessType.INSERT) - @PostMapping - @ApiOperation("添加分类") - public AjaxResult add(@RequestBody Category category) - { - return toAjax(categoryService.insertCategory(category)); - } - - /** - * 修改产品分类 - */ - @PreAuthorize("@ss.hasPermi('iot:category:edit')") - @Log(title = "产品分类", businessType = BusinessType.UPDATE) - @PutMapping - @ApiOperation("修改分类") - public AjaxResult edit(@RequestBody Category category) - { - return toAjax(categoryService.updateCategory(category)); - } - - /** - * 删除产品分类 - */ - @PreAuthorize("@ss.hasPermi('iot:category:remove')") - @Log(title = "产品分类", businessType = BusinessType.DELETE) - @DeleteMapping("/{categoryIds}") - @ApiOperation("批量删除分类") - public AjaxResult remove(@PathVariable Long[] categoryIds) - { - return categoryService.deleteCategoryByCategoryIds(categoryIds); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/DeviceController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/DeviceController.java deleted file mode 100644 index 6dc5d51d..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/DeviceController.java +++ /dev/null @@ -1,249 +0,0 @@ -package com.ruoyi.iot.controller; - -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.page.TableDataInfo; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.iot.domain.Device; -import com.ruoyi.iot.model.DeviceAllShortOutput; -import com.ruoyi.iot.model.DeviceRelateUserInput; -import com.ruoyi.iot.model.DeviceShortOutput; -import com.ruoyi.iot.mqtt.EmqxService; -import com.ruoyi.iot.service.IDeviceService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import org.quartz.SchedulerException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Lazy; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; - -import javax.servlet.http.HttpServletResponse; -import java.util.ArrayList; -import java.util.List; - -/** - * 设备Controller - * - * @author kerwincui - * @date 2021-12-16 - */ -@Api(tags = "设备管理") -@RestController -@RequestMapping("/iot/device") -public class DeviceController extends BaseController -{ - @Autowired - private IDeviceService deviceService; - - @Lazy - @Autowired - private EmqxService emqxService; - - /** - * 查询设备列表 - */ - @PreAuthorize("@ss.hasPermi('iot:device:list')") - @GetMapping("/list") - @ApiOperation("设备分页列表") - public TableDataInfo list(Device device) - { - startPage(); - return getDataTable(deviceService.selectDeviceList(device)); - } - - /** - * 查询未分配授权码设备列表 - */ - @PreAuthorize("@ss.hasPermi('iot:device:list')") - @GetMapping("/unAuthlist") - @ApiOperation("设备分页列表") - public TableDataInfo unAuthlist(Device device) - { - startPage(); - return getDataTable(deviceService.selectUnAuthDeviceList(device)); - } - - /** - * 查询分组可添加设备 - */ - @PreAuthorize("@ss.hasPermi('iot:device:list')") - @GetMapping("/listByGroup") - @ApiOperation("查询分组可添加设备分页列表") - public TableDataInfo listByGroup(Device device) - { - startPage(); - return getDataTable(deviceService.selectDeviceListByGroup(device)); - } - - /** - * 查询设备简短列表,主页列表数据 - */ - @PreAuthorize("@ss.hasPermi('iot:device:list')") - @GetMapping("/shortList") - @ApiOperation("设备分页简短列表") - public TableDataInfo shortList(Device device) - { - startPage(); - return getDataTable(deviceService.selectDeviceShortList(device)); - } - - /** - * 查询所有设备简短列表 - */ - @PreAuthorize("@ss.hasPermi('iot:device:list')") - @GetMapping("/all") - @ApiOperation("查询所有设备简短列表") - public TableDataInfo allShortList() - { - return getDataTable(deviceService.selectAllDeviceShortList()); - } - - /** - * 导出设备列表 - */ - @PreAuthorize("@ss.hasPermi('iot:device:export')") - @Log(title = "设备", businessType = BusinessType.EXPORT) - @PostMapping("/export") - @ApiOperation("导出设备") - public void export(HttpServletResponse response, Device device) - { - List list = deviceService.selectDeviceList(device); - ExcelUtil util = new ExcelUtil(Device.class); - util.exportExcel(response, list, "设备数据"); - } - - /** - * 获取设备详细信息 - */ - @PreAuthorize("@ss.hasPermi('iot:device:query')") - @GetMapping(value = "/{deviceId}") - @ApiOperation("获取设备详情") - public AjaxResult getInfo(@PathVariable("deviceId") Long deviceId) - { - return AjaxResult.success(deviceService.selectDeviceByDeviceId(deviceId)); - } - - /** - * 设备数据同步 - */ - @PreAuthorize("@ss.hasPermi('iot:device:query')") - @GetMapping(value = "/synchronization/{serialNumber}") - @ApiOperation("设备数据同步") - public AjaxResult deviceSynchronization(@PathVariable("serialNumber") String serialNumber) - { - return AjaxResult.success(emqxService.deviceSynchronization(serialNumber)); - } - - /** - * 根据设备编号详细信息 - */ - @PreAuthorize("@ss.hasPermi('iot:device:query')") - @GetMapping(value = "/getDeviceBySerialNumber/{serialNumber}") - @ApiOperation("根据设备编号获取设备详情") - public AjaxResult getInfoBySerialNumber(@PathVariable("serialNumber") String serialNumber) - { - return AjaxResult.success(deviceService.selectDeviceBySerialNumber(serialNumber)); - } - - /** - * 获取设备统计信息 - */ - @PreAuthorize("@ss.hasPermi('iot:device:query')") - @GetMapping(value = "/statistic") - @ApiOperation("获取设备统计信息") - public AjaxResult getDeviceStatistic() - { - return AjaxResult.success(deviceService.selectDeviceStatistic()); - } - - /** - * 获取设备详细信息 - */ - @PreAuthorize("@ss.hasPermi('iot:device:query')") - @GetMapping(value = "/runningStatus/{deviceId}") - @ApiOperation("获取设备详情和运行状态") - public AjaxResult getRunningStatusInfo(@PathVariable("deviceId") Long deviceId) - { - return AjaxResult.success(deviceService.selectDeviceRunningStatusByDeviceId(deviceId)); - } - - /** - * 新增设备 - */ - @PreAuthorize("@ss.hasPermi('iot:device:add')") - @Log(title = "添加设备", businessType = BusinessType.INSERT) - @PostMapping - @ApiOperation("添加设备") - public AjaxResult add(@RequestBody Device device) - { - return AjaxResult.success(deviceService.insertDevice(device)); - } - - /** - * 设备关联用户 - */ - @PreAuthorize("@ss.hasPermi('iot:device:add')") - @Log(title = "设备关联用户", businessType = BusinessType.UPDATE) - @PostMapping("/relateUser") - @ApiOperation("设备关联用户") - public AjaxResult relateUser(@RequestBody DeviceRelateUserInput deviceRelateUserInput) - { - if(deviceRelateUserInput.getUserId()==0 || deviceRelateUserInput.getUserId()==null){ - return AjaxResult.error("用户ID不能为空"); - } - if(deviceRelateUserInput.getDeviceNumberAndProductIds()==null || deviceRelateUserInput.getDeviceNumberAndProductIds().size()==0){ - return AjaxResult.error("设备编号和产品ID不能为空"); - } - return deviceService.deviceRelateUser(deviceRelateUserInput); - } - - /** - * 修改设备 - */ - @PreAuthorize("@ss.hasPermi('iot:device:edit')") - @Log(title = "修改设备", businessType = BusinessType.UPDATE) - @PutMapping - @ApiOperation("修改设备") - public AjaxResult edit(@RequestBody Device device) - { - return deviceService.updateDevice(device); - } - - /** - * 重置设备状态 - */ - @PreAuthorize("@ss.hasPermi('iot:device:edit')") - @Log(title = "重置设备状态", businessType = BusinessType.UPDATE) - @PutMapping("/reset/{serialNumber}") - @ApiOperation("重置设备状态") - public AjaxResult resetDeviceStatus(@PathVariable String serialNumber) - { - Device device=new Device(); - device.setSerialNumber(serialNumber); - return toAjax(deviceService.resetDeviceStatus(device.getSerialNumber())); - } - - /** - * 删除设备 - */ - @PreAuthorize("@ss.hasPermi('iot:device:remove')") - @Log(title = "删除设备", businessType = BusinessType.DELETE) - @DeleteMapping("/{deviceIds}") - @ApiOperation("批量删除设备") - public AjaxResult remove(@PathVariable Long[] deviceIds) throws SchedulerException { - return toAjax(deviceService.deleteDeviceByDeviceId(deviceIds[0])); - } - - /** - * 生成设备编号 - */ - @PreAuthorize("@ss.hasPermi('iot:device:edit')") - @GetMapping("/generator") - @ApiOperation("生成设备编号") - public AjaxResult generatorDeviceNum(){ - return AjaxResult.success("操作成功",deviceService.generationDeviceNum()); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/DeviceJobController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/DeviceJobController.java deleted file mode 100644 index 060ed4f1..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/DeviceJobController.java +++ /dev/null @@ -1,136 +0,0 @@ -package com.ruoyi.iot.controller; - -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.page.TableDataInfo; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.common.exception.job.TaskException; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.iot.domain.DeviceJob; -import com.ruoyi.iot.service.IDeviceJobService; -import com.ruoyi.quartz.util.CronUtils; -import org.quartz.SchedulerException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; - -import javax.servlet.http.HttpServletResponse; -import java.util.List; - -/** - * 调度任务信息操作处理 - * - * @author kerwincui - */ -@RestController -@RequestMapping("/iot/job") -public class DeviceJobController extends BaseController -{ - @Autowired - private IDeviceJobService jobService; - - /** - * 查询定时任务列表 - */ - @PreAuthorize("@ss.hasPermi('iot:device:list')") - @GetMapping("/list") - public TableDataInfo list(DeviceJob deviceJob) - { - startPage(); - List list = jobService.selectJobList(deviceJob); - return getDataTable(list); - } - - /** - * 导出定时任务列表 - */ - @PreAuthorize("@ss.hasPermi('iot:device:export')") - @Log(title = "定时任务", businessType = BusinessType.EXPORT) - @PostMapping("/export") - public void export(HttpServletResponse response, DeviceJob deviceJob) - { - List list = jobService.selectJobList(deviceJob); - ExcelUtil util = new ExcelUtil(DeviceJob.class); - util.exportExcel(response, list, "定时任务"); - } - - /** - * 获取定时任务详细信息 - */ - @PreAuthorize("@ss.hasPermi('iot:device:query')") - @GetMapping(value = "/{jobId}") - public AjaxResult getInfo(@PathVariable("jobId") Long jobId) - { - return AjaxResult.success(jobService.selectJobById(jobId)); - } - - /** - * 新增定时任务 - */ - @PreAuthorize("@ss.hasPermi('iot:device:add')") - @Log(title = "定时任务", businessType = BusinessType.INSERT) - @PostMapping - public AjaxResult add(@RequestBody DeviceJob job) throws SchedulerException, TaskException - { - if (!CronUtils.isValid(job.getCronExpression())) - { - return error("新增任务'" + job.getJobName() + "'失败,Cron表达式不正确"); - } - job.setCreateBy(getUsername()); - return toAjax(jobService.insertJob(job)); - } - - /** - * 修改定时任务 - */ - @PreAuthorize("@ss.hasPermi('iot:device:edit')") - @Log(title = "定时任务", businessType = BusinessType.UPDATE) - @PutMapping - public AjaxResult edit(@RequestBody DeviceJob job) throws SchedulerException, TaskException - { - if (!CronUtils.isValid(job.getCronExpression())) - { - return error("修改任务'" + job.getJobName() + "'失败,Cron表达式不正确"); - } - job.setUpdateBy(getUsername()); - return toAjax(jobService.updateJob(job)); - } - - /** - * 定时任务状态修改 - */ - @PreAuthorize("@ss.hasPermi('iot:device:edit')") - @Log(title = "定时任务", businessType = BusinessType.UPDATE) - @PutMapping("/changeStatus") - public AjaxResult changeStatus(@RequestBody DeviceJob job) throws SchedulerException - { - DeviceJob newJob = jobService.selectJobById(job.getJobId()); - newJob.setStatus(job.getStatus()); - return toAjax(jobService.changeStatus(newJob)); - } - - /** - * 定时任务立即执行一次 - */ - @PreAuthorize("@ss.hasPermi('iot:device:edit')") - @Log(title = "定时任务", businessType = BusinessType.UPDATE) - @PutMapping("/run") - public AjaxResult run(@RequestBody DeviceJob job) throws SchedulerException - { - jobService.run(job); - return AjaxResult.success(); - } - - /** - * 删除定时任务 - */ - @PreAuthorize("@ss.hasPermi('iot:device:remove')") - @Log(title = "定时任务", businessType = BusinessType.DELETE) - @DeleteMapping("/{jobIds}") - public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException, TaskException - { - jobService.deleteJobByIds(jobIds); - return AjaxResult.success(); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/DeviceLogController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/DeviceLogController.java deleted file mode 100644 index 85a03ce4..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/DeviceLogController.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.ruoyi.iot.controller; - -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.page.TableDataInfo; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.iot.domain.DeviceLog; -import com.ruoyi.iot.model.MonitorModel; -import com.ruoyi.iot.service.IDeviceLogService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; - -import javax.servlet.http.HttpServletResponse; -import java.util.List; - -/** - * 设备日志Controller - * - * @author kerwincui - * @date 2022-01-13 - */ -@RestController -@RequestMapping("/iot/deviceLog") -public class DeviceLogController extends BaseController -{ - @Autowired - private IDeviceLogService deviceLogService; - - /** - * 查询设备日志列表 - */ - @PreAuthorize("@ss.hasPermi('iot:device:list')") - @GetMapping("/list") - public TableDataInfo list(DeviceLog deviceLog) - { - startPage(); - List list = deviceLogService.selectDeviceLogList(deviceLog); - return getDataTable(list); - } - - /** - * 查询设备的监测数据 - */ - @PreAuthorize("@ss.hasPermi('iot:device:list')") - @GetMapping("/monitor") - public TableDataInfo monitorList(DeviceLog deviceLog) - { - List list = deviceLogService.selectMonitorList(deviceLog); - return getDataTable(list); - } - - /** - * 导出设备日志列表 - */ - @PreAuthorize("@ss.hasPermi('iot:device:export')") - @Log(title = "设备日志", businessType = BusinessType.EXPORT) - @PostMapping("/export") - public void export(HttpServletResponse response, DeviceLog deviceLog) - { - List list = deviceLogService.selectDeviceLogList(deviceLog); - ExcelUtil util = new ExcelUtil(DeviceLog.class); - util.exportExcel(response, list, "设备日志数据"); - } - - /** - * 获取设备日志详细信息 - */ - @PreAuthorize("@ss.hasPermi('iot:device:query')") - @GetMapping(value = "/{logId}") - public AjaxResult getInfo(@PathVariable("logId") Long logId) - { - return AjaxResult.success(deviceLogService.selectDeviceLogByLogId(logId)); - } - - /** - * 新增设备日志 - */ - @PreAuthorize("@ss.hasPermi('iot:device:add')") - @Log(title = "设备日志", businessType = BusinessType.INSERT) - @PostMapping - public AjaxResult add(@RequestBody DeviceLog deviceLog) - { - return toAjax(deviceLogService.insertDeviceLog(deviceLog)); - } - - /** - * 修改设备日志 - */ - @PreAuthorize("@ss.hasPermi('iot:device:edit')") - @Log(title = "设备日志", businessType = BusinessType.UPDATE) - @PutMapping - public AjaxResult edit(@RequestBody DeviceLog deviceLog) - { - return toAjax(deviceLogService.updateDeviceLog(deviceLog)); - } - - /** - * 删除设备日志 - */ - @PreAuthorize("@ss.hasPermi('iot:device:remove')") - @Log(title = "设备日志", businessType = BusinessType.DELETE) - @DeleteMapping("/{logIds}") - public AjaxResult remove(@PathVariable Long[] logIds) - { - return toAjax(deviceLogService.deleteDeviceLogByLogIds(logIds)); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/DeviceUserController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/DeviceUserController.java deleted file mode 100644 index ed17ed92..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/DeviceUserController.java +++ /dev/null @@ -1,127 +0,0 @@ -package com.ruoyi.iot.controller; - -import java.util.List; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.iot.domain.DeviceUser; -import com.ruoyi.iot.service.IDeviceUserService; -import com.ruoyi.common.core.page.TableDataInfo; - -/** - * 设备用户Controller - * - * @author kerwincui - * @date 2021-12-16 - */ -@Api(tags = "设备用户") -@RestController -@RequestMapping("/iot/deviceUser") -public class DeviceUserController extends BaseController -{ - @Autowired - private IDeviceUserService deviceUserService; - - /** - * 查询设备用户列表 - */ - @PreAuthorize("@ss.hasPermi('iot:device:list')") - @GetMapping("/list") - @ApiOperation("设备用户分页列表") - public TableDataInfo list(DeviceUser deviceUser) - { - startPage(); - List list = deviceUserService.selectDeviceUserList(deviceUser); - return getDataTable(list); - } - - /** - * 获取设备用户详细信息 根据deviceId 查询的话可能会查出多个 - */ - @PreAuthorize("@ss.hasPermi('iot:device:query')") - @GetMapping(value = "/{deviceId}") - @ApiOperation("获取设备用户详情") - public AjaxResult getInfo(@PathVariable("deviceId") Long deviceId) - { - return AjaxResult.success(deviceUserService.selectDeviceUserByDeviceId(deviceId)); - } - - /** - * 获取设备用户详细信息 双主键 device_id 和 user_id - */ - @PreAuthorize("@ss.hasPermi('iot:device:query')") - @GetMapping(value = "/{deviceId}/{userId}") - @ApiOperation("获取设备用户详情,根据用户id 和 设备id") - public AjaxResult getInfo(@PathVariable("deviceId") Long deviceId, @PathVariable("userId") Long userId) - { - return AjaxResult.success(deviceUserService.selectDeviceUserByDeviceIdAndUserId(deviceId, userId)); - } - - /** - * 新增设备用户 - */ - @PreAuthorize("@ss.hasPermi('iot:device:share')") - @Log(title = "设备用户", businessType = BusinessType.INSERT) - @PostMapping - @ApiOperation("添加设备用户") - public AjaxResult add(@RequestBody DeviceUser deviceUser) - { - return toAjax(deviceUserService.insertDeviceUser(deviceUser)); - } - - /** - * 新增多个设备用户 - */ - @PreAuthorize("@ss.hasPermi('iot:device:share')") - @Log(title = "设备用户", businessType = BusinessType.INSERT) - @PostMapping("/addDeviceUsers") - @ApiOperation("批量添加设备用户") - public AjaxResult addDeviceUsers(@RequestBody List deviceUsers) - { - return toAjax(deviceUserService.insertDeviceUserList(deviceUsers)); - } - - /** - * 修改设备用户 - */ - @ApiOperation("修改设备用户") - @PreAuthorize("@ss.hasPermi('iot:device:edit')") - @Log(title = "设备用户", businessType = BusinessType.UPDATE) - @PutMapping - public AjaxResult edit(@RequestBody DeviceUser deviceUser) - { - return toAjax(deviceUserService.updateDeviceUser(deviceUser)); - } - - - /** - * 删除设备用户 - */ - @ApiOperation("删除设备用户") - @PreAuthorize("@ss.hasPermi('iot:device:remove')") - @Log(title = "设备用户", businessType = BusinessType.DELETE) - @DeleteMapping - public AjaxResult remove(@RequestBody DeviceUser deviceUser) - { - int count=deviceUserService.deleteDeviceUser(deviceUser); - if(count==0){ - return AjaxResult.error("设备所有者不能删除"); - }else{ - return AjaxResult.success(); - } - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/FirmwareController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/FirmwareController.java deleted file mode 100644 index bd820491..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/FirmwareController.java +++ /dev/null @@ -1,136 +0,0 @@ -package com.ruoyi.iot.controller; - -import java.util.List; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import com.ruoyi.common.config.RuoYiConfig; -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.file.FileUploadUtils; -import com.ruoyi.common.utils.file.FileUtils; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.http.MediaType; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.iot.domain.Firmware; -import com.ruoyi.iot.service.IFirmwareService; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.common.core.page.TableDataInfo; -import org.springframework.web.multipart.MultipartFile; - -/** - * 产品固件Controller - * - * @author kerwincui - * @date 2021-12-16 - */ -@Api(tags = "产品固件") -@RestController -@RequestMapping("/iot/firmware") -public class FirmwareController extends BaseController -{ - private static final Logger log = LoggerFactory.getLogger(FirmwareController.class); - - @Autowired - private IFirmwareService firmwareService; - - /** - * 查询产品固件列表 - */ - @PreAuthorize("@ss.hasPermi('iot:firmware:list')") - @GetMapping("/list") - @ApiOperation("产品固件分页列表") - public TableDataInfo list(Firmware firmware) - { - startPage(); - return getDataTable(firmwareService.selectFirmwareList(firmware)); - } - - /** - * 导出产品固件列表 - */ - @PreAuthorize("@ss.hasPermi('iot:firmware:export')") - @Log(title = "产品固件", businessType = BusinessType.EXPORT) - @PostMapping("/export") - @ApiOperation("导出固件") - public void export(HttpServletResponse response, Firmware firmware) - { - List list = firmwareService.selectFirmwareList(firmware); - ExcelUtil util = new ExcelUtil(Firmware.class); - util.exportExcel(response, list, "产品固件数据"); - } - - /** - * 获取产品固件详细信息 - */ - @ApiOperation("获取固件详情") - @PreAuthorize("@ss.hasPermi('iot:firmware:query')") - @GetMapping(value = "/{firmwareId}") - public AjaxResult getInfo(@PathVariable("firmwareId") Long firmwareId) - { - return AjaxResult.success(firmwareService.selectFirmwareByFirmwareId(firmwareId)); - } - - /** - * 获取设备最新固件 - */ - @ApiOperation("获取设备最新固件") - @PreAuthorize("@ss.hasPermi('iot:firmware:query')") - @GetMapping(value = "/getLatest/{deviceId}") - public AjaxResult getLatest(@PathVariable("deviceId") Long deviceId) - { - return AjaxResult.success(firmwareService.selectLatestFirmware(deviceId)); - } - - /** - * 新增产品固件 - */ - @ApiOperation("添加产品固件") - @PreAuthorize("@ss.hasPermi('iot:firmware:add')") - @Log(title = "产品固件", businessType = BusinessType.INSERT) - @PostMapping - public AjaxResult add(@RequestBody Firmware firmware) - { - return toAjax(firmwareService.insertFirmware(firmware)); - } - - /** - * 修改产品固件 - */ - @ApiOperation("修改产品固件") - @PreAuthorize("@ss.hasPermi('iot:firmware:edit')") - @Log(title = "产品固件", businessType = BusinessType.UPDATE) - @PutMapping - public AjaxResult edit(@RequestBody Firmware firmware) - { - return toAjax(firmwareService.updateFirmware(firmware)); - } - - /** - * 删除产品固件 - */ - @ApiOperation("批量删除产品固件") - @PreAuthorize("@ss.hasPermi('iot:firmware:remove')") - @Log(title = "产品固件", businessType = BusinessType.DELETE) - @DeleteMapping("/{firmwareIds}") - public AjaxResult remove(@PathVariable Long[] firmwareIds) - { - return toAjax(firmwareService.deleteFirmwareByFirmwareIds(firmwareIds)); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/GroupController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/GroupController.java deleted file mode 100644 index c75c4201..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/GroupController.java +++ /dev/null @@ -1,140 +0,0 @@ -package com.ruoyi.iot.controller; - -import java.util.ArrayList; -import java.util.List; -import javax.servlet.http.HttpServletResponse; - -import com.ruoyi.iot.domain.DeviceGroup; -import com.ruoyi.iot.model.DeviceGroupInput; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.iot.domain.Group; -import com.ruoyi.iot.service.IGroupService; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.common.core.page.TableDataInfo; - -/** - * 设备分组Controller - * - * @author kerwincui - * @date 2021-12-16 - */ -@Api(tags = "设备分组") -@RestController -@RequestMapping("/iot/group") -public class GroupController extends BaseController -{ - @Autowired - private IGroupService groupService; - - /** - * 查询设备分组列表 - */ - @PreAuthorize("@ss.hasPermi('iot:group:list')") - @GetMapping("/list") - @ApiOperation("分组分页列表") - public TableDataInfo list(Group group) - { - startPage(); - return getDataTable(groupService.selectGroupList(group)); - } - - /** - * 导出设备分组列表 - */ - @PreAuthorize("@ss.hasPermi('iot:group:export')") - @Log(title = "分组", businessType = BusinessType.EXPORT) - @PostMapping("/export") - @ApiOperation("导出分组") - public void export(HttpServletResponse response, Group group) - { - List list = groupService.selectGroupList(group); - ExcelUtil util = new ExcelUtil(Group.class); - util.exportExcel(response, list, "设备分组数据"); - } - - /** - * 获取设备分组详细信息 - */ - @PreAuthorize("@ss.hasPermi('iot:group:query')") - @GetMapping(value = "/{groupId}") - @ApiOperation("获取分组详情") - public AjaxResult getInfo(@PathVariable("groupId") Long groupId) - { - return AjaxResult.success(groupService.selectGroupByGroupId(groupId)); - } - - /** - * 获取分组下的所有关联设备ID数组 - */ - @PreAuthorize("@ss.hasPermi('iot:group:query')") - @GetMapping(value = "/getDeviceIds/{groupId}") - @ApiOperation("获取分组下的所有关联设备ID数组") - public AjaxResult getDeviceIds(@PathVariable("groupId") Long groupId) - { - return AjaxResult.success(groupService.selectDeviceIdsByGroupId(groupId)); - } - - /** - * 新增设备分组 - */ - @PreAuthorize("@ss.hasPermi('iot:group:add')") - @Log(title = "分组", businessType = BusinessType.INSERT) - @PostMapping - @ApiOperation("添加分组") - public AjaxResult add(@RequestBody Group group) - { - return toAjax(groupService.insertGroup(group)); - } - - /** - * 更新分组下的关联设备 - * @param input - * @return - */ - @PreAuthorize("@ss.hasPermi('iot:group:edit')") - @Log(title = "设备分组", businessType = BusinessType.UPDATE) - @PutMapping("/updateDeviceGroups") - @ApiOperation("更新分组下的关联设备") - public AjaxResult updateDeviceGroups(@RequestBody DeviceGroupInput input){ - return toAjax(groupService.updateDeviceGroups(input)); - } - - /** - * 修改设备分组 - */ - @PreAuthorize("@ss.hasPermi('iot:group:edit')") - @Log(title = "分组", businessType = BusinessType.UPDATE) - @PutMapping - @ApiOperation("修改分组") - public AjaxResult edit(@RequestBody Group group) - { - return toAjax(groupService.updateGroup(group)); - } - - /** - * 删除设备分组 - */ - @PreAuthorize("@ss.hasPermi('iot:group:remove')") - @Log(title = "分组", businessType = BusinessType.DELETE) - @DeleteMapping("/{groupIds}") - @ApiOperation("批量删除设备分组") - public AjaxResult remove(@PathVariable Long[] groupIds) - { - return toAjax(groupService.deleteGroupByGroupIds(groupIds)); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/NewsCategoryController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/NewsCategoryController.java deleted file mode 100644 index 60f65e22..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/NewsCategoryController.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.ruoyi.iot.controller; - -import java.util.List; -import javax.servlet.http.HttpServletResponse; - -import com.ruoyi.iot.model.IdAndName; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.iot.domain.NewsCategory; -import com.ruoyi.iot.service.INewsCategoryService; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.common.core.page.TableDataInfo; - -/** - * 新闻分类Controller - * - * @author kerwincui - * @date 2022-04-09 - */ -@Api(tags = "新闻分类") -@RestController -@RequestMapping("/iot/newsCategory") -public class NewsCategoryController extends BaseController -{ - @Autowired - private INewsCategoryService newsCategoryService; - - /** - * 查询新闻分类列表 - */ - @PreAuthorize("@ss.hasPermi('iot:newsCategory:list')") - @GetMapping("/list") - @ApiOperation("新闻分类分页列表") - public TableDataInfo list(NewsCategory newsCategory) - { - startPage(); - List list = newsCategoryService.selectNewsCategoryList(newsCategory); - return getDataTable(list); - } - - /** - * 查询新闻分类简短列表 - */ - @PreAuthorize("@ss.hasPermi('iot:news:list')") - @GetMapping("/newsCategoryShortList") - @ApiOperation("分类简短列表") - public AjaxResult newsCategoryShortList() - { - List list = newsCategoryService.selectNewsCategoryShortList(); - return AjaxResult.success(list); - } - - /** - * 导出新闻分类列表 - */ - @PreAuthorize("@ss.hasPermi('iot:newsCategory:export')") - @Log(title = "新闻分类", businessType = BusinessType.EXPORT) - @PostMapping("/export") - public void export(HttpServletResponse response, NewsCategory newsCategory) - { - List list = newsCategoryService.selectNewsCategoryList(newsCategory); - ExcelUtil util = new ExcelUtil(NewsCategory.class); - util.exportExcel(response, list, "新闻分类数据"); - } - - /** - * 获取新闻分类详细信息 - */ - @PreAuthorize("@ss.hasPermi('iot:newsCategory:query')") - @GetMapping(value = "/{categoryId}") - @ApiOperation("新闻分类详情") - public AjaxResult getInfo(@PathVariable("categoryId") Long categoryId) - { - return AjaxResult.success(newsCategoryService.selectNewsCategoryByCategoryId(categoryId)); - } - - /** - * 新增新闻分类 - */ - @PreAuthorize("@ss.hasPermi('iot:newsCategory:add')") - @Log(title = "新闻分类", businessType = BusinessType.INSERT) - @PostMapping - @ApiOperation("添加新闻分类") - public AjaxResult add(@RequestBody NewsCategory newsCategory) - { - return toAjax(newsCategoryService.insertNewsCategory(newsCategory)); - } - - /** - * 修改新闻分类 - */ - @PreAuthorize("@ss.hasPermi('iot:newsCategory:edit')") - @Log(title = "新闻分类", businessType = BusinessType.UPDATE) - @PutMapping - @ApiOperation("修改新闻分类") - public AjaxResult edit(@RequestBody NewsCategory newsCategory) - { - return toAjax(newsCategoryService.updateNewsCategory(newsCategory)); - } - - /** - * 删除新闻分类 - */ - @PreAuthorize("@ss.hasPermi('iot:newsCategory:remove')") - @Log(title = "新闻分类", businessType = BusinessType.DELETE) - @DeleteMapping("/{categoryIds}") - @ApiOperation("删除新闻分类") - public AjaxResult remove(@PathVariable Long[] categoryIds) - { - return newsCategoryService.deleteNewsCategoryByCategoryIds(categoryIds); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/NewsController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/NewsController.java deleted file mode 100644 index 65c6c5ca..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/NewsController.java +++ /dev/null @@ -1,141 +0,0 @@ -package com.ruoyi.iot.controller; - -import java.util.List; -import javax.servlet.http.HttpServletResponse; - -import com.ruoyi.iot.model.CategoryNews; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.iot.domain.News; -import com.ruoyi.iot.service.INewsService; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.common.core.page.TableDataInfo; - -/** - * 新闻资讯Controller - * - * @author kerwincui - * @date 2022-04-09 - */ -@Api(tags = "新闻资讯") -@RestController -@RequestMapping("/iot/news") -public class NewsController extends BaseController -{ - @Autowired - private INewsService newsService; - - /** - * 查询新闻资讯列表 - */ - @PreAuthorize("@ss.hasPermi('iot:news:list')") - @GetMapping("/list") - @ApiOperation("新闻分页列表") - public TableDataInfo list(News news) - { - startPage(); - List list = newsService.selectNewsList(news); - return getDataTable(list); - } - - /** - * 查询轮播的新闻资讯 - */ - @PreAuthorize("@ss.hasPermi('iot:news:list')") - @GetMapping("/bannerList") - @ApiOperation("轮播新闻列表") - public AjaxResult bannerList() - { - News news=new News(); - news.setIsBanner(1); - news.setStatus(1); - List list = newsService.selectNewsList(news); - return AjaxResult.success(list); - } - - /** - * 查询置顶的新闻资讯 - */ - @PreAuthorize("@ss.hasPermi('iot:news:list')") - @GetMapping("/topList") - @ApiOperation("置顶新闻列表") - public AjaxResult topList() - { - List list = newsService.selectTopNewsList(); - return AjaxResult.success(list); - } - - /** - * 导出新闻资讯列表 - */ - @PreAuthorize("@ss.hasPermi('iot:news:export')") - @Log(title = "新闻资讯", businessType = BusinessType.EXPORT) - @PostMapping("/export") - public void export(HttpServletResponse response, News news) - { - List list = newsService.selectNewsList(news); - ExcelUtil util = new ExcelUtil(News.class); - util.exportExcel(response, list, "新闻资讯数据"); - } - - /** - * 获取新闻资讯详细信息 - */ - @PreAuthorize("@ss.hasPermi('iot:news:query')") - @GetMapping(value = "/{newsId}") - @ApiOperation("新闻详情") - public AjaxResult getInfo(@PathVariable("newsId") Long newsId) - { - return AjaxResult.success(newsService.selectNewsByNewsId(newsId)); - } - - /** - * 新增新闻资讯 - */ - @PreAuthorize("@ss.hasPermi('iot:news:add')") - @Log(title = "新闻资讯", businessType = BusinessType.INSERT) - @PostMapping - @ApiOperation("添加新闻资讯") - public AjaxResult add(@RequestBody News news) - { - return toAjax(newsService.insertNews(news)); - } - - /** - * 修改新闻资讯 - */ - @PreAuthorize("@ss.hasPermi('iot:news:edit')") - @Log(title = "新闻资讯", businessType = BusinessType.UPDATE) - @PutMapping - @ApiOperation("修改新闻资讯") - public AjaxResult edit(@RequestBody News news) - { - return toAjax(newsService.updateNews(news)); - } - - /** - * 删除新闻资讯 - */ - @PreAuthorize("@ss.hasPermi('iot:news:remove')") - @Log(title = "新闻资讯", businessType = BusinessType.DELETE) - @DeleteMapping("/{newsIds}") - @ApiOperation("删除新闻资讯") - public AjaxResult remove(@PathVariable Long[] newsIds) - { - return toAjax(newsService.deleteNewsByNewsIds(newsIds)); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/OauthClientDetailsController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/OauthClientDetailsController.java deleted file mode 100644 index 23984ea3..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/OauthClientDetailsController.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.ruoyi.iot.controller; - -import java.util.List; -import javax.servlet.http.HttpServletResponse; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.iot.domain.OauthClientDetails; -import com.ruoyi.iot.service.IOauthClientDetailsService; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.common.core.page.TableDataInfo; - -/** - * 云云对接Controller - * - * @author kerwincui - * @date 2022-02-07 - */ -@RestController -@RequestMapping("/iot/clientDetails") -public class OauthClientDetailsController extends BaseController -{ - @Autowired - private IOauthClientDetailsService oauthClientDetailsService; - - /** - * 查询云云对接列表 - */ - @PreAuthorize("@ss.hasPermi('iot:clientDetails:list')") - @GetMapping("/list") - public TableDataInfo list(OauthClientDetails oauthClientDetails) - { - startPage(); - List list = oauthClientDetailsService.selectOauthClientDetailsList(oauthClientDetails); - return getDataTable(list); - } - - /** - * 导出云云对接列表 - */ - @PreAuthorize("@ss.hasPermi('iot:clientDetails:export')") - @Log(title = "云云对接", businessType = BusinessType.EXPORT) - @PostMapping("/export") - public void export(HttpServletResponse response, OauthClientDetails oauthClientDetails) - { - List list = oauthClientDetailsService.selectOauthClientDetailsList(oauthClientDetails); - ExcelUtil util = new ExcelUtil(OauthClientDetails.class); - util.exportExcel(response, list, "云云对接数据"); - } - - /** - * 获取云云对接详细信息 - */ - @PreAuthorize("@ss.hasPermi('iot:clientDetails:query')") - @GetMapping(value = "/{clientId}") - public AjaxResult getInfo(@PathVariable("clientId") String clientId) - { - return AjaxResult.success(oauthClientDetailsService.selectOauthClientDetailsByClientId(clientId)); - } - - /** - * 新增云云对接 - */ - @PreAuthorize("@ss.hasPermi('iot:clientDetails:add')") - @Log(title = "云云对接", businessType = BusinessType.INSERT) - @PostMapping - public AjaxResult add(@RequestBody OauthClientDetails oauthClientDetails) - { - return toAjax(oauthClientDetailsService.insertOauthClientDetails(oauthClientDetails)); - } - - /** - * 修改云云对接 - */ - @PreAuthorize("@ss.hasPermi('iot:clientDetails:edit')") - @Log(title = "云云对接", businessType = BusinessType.UPDATE) - @PutMapping - public AjaxResult edit(@RequestBody OauthClientDetails oauthClientDetails) - { - return toAjax(oauthClientDetailsService.updateOauthClientDetails(oauthClientDetails)); - } - - /** - * 删除云云对接 - */ - @PreAuthorize("@ss.hasPermi('iot:clientDetails:remove')") - @Log(title = "云云对接", businessType = BusinessType.DELETE) - @DeleteMapping("/{clientIds}") - public AjaxResult remove(@PathVariable String[] clientIds) - { - return toAjax(oauthClientDetailsService.deleteOauthClientDetailsByClientIds(clientIds)); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/ProductAuthorizeController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/ProductAuthorizeController.java deleted file mode 100644 index afa3aaf4..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/ProductAuthorizeController.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.ruoyi.iot.controller; - -import java.util.List; -import javax.servlet.http.HttpServletResponse; - -import com.ruoyi.iot.model.ProductAuthorizeVO; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.iot.domain.ProductAuthorize; -import com.ruoyi.iot.service.IProductAuthorizeService; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.common.core.page.TableDataInfo; - -/** - * 产品授权码Controller - * - * @author kami - * @date 2022-04-11 - */ -@RestController -@RequestMapping("/iot/authorize") -public class ProductAuthorizeController extends BaseController -{ - @Autowired - private IProductAuthorizeService productAuthorizeService; - - /** - * 查询产品授权码列表 - */ - @PreAuthorize("@ss.hasPermi('iot:product:list')") - @GetMapping("/list") - public TableDataInfo list(ProductAuthorize productAuthorize) - { - startPage(); - List list = productAuthorizeService.selectProductAuthorizeList(productAuthorize); - return getDataTable(list); - } - - /** - * 导出产品授权码列表 - */ - @PreAuthorize("@ss.hasPermi('iot:authorize:export')") - @Log(title = "产品授权码", businessType = BusinessType.EXPORT) - @PostMapping("/export") - public void export(HttpServletResponse response, ProductAuthorize productAuthorize) - { - List list = productAuthorizeService.selectProductAuthorizeList(productAuthorize); - ExcelUtil util = new ExcelUtil(ProductAuthorize.class); - util.exportExcel(response, list, "产品授权码数据"); - } - - /** - * 获取产品授权码详细信息 - */ - @PreAuthorize("@ss.hasPermi('iot:authorize:query')") - @GetMapping(value = "/{authorizeId}") - public AjaxResult getInfo(@PathVariable("authorizeId") Long authorizeId) - { - return AjaxResult.success(productAuthorizeService.selectProductAuthorizeByAuthorizeId(authorizeId)); - } - - /** - * 新增产品授权码 - */ - @PreAuthorize("@ss.hasPermi('iot:authorize:add')") - @Log(title = "产品授权码", businessType = BusinessType.INSERT) - @PostMapping - public AjaxResult add(@RequestBody ProductAuthorize productAuthorize) - { - return toAjax(productAuthorizeService.insertProductAuthorize(productAuthorize)); - } - - /** - * 根据数量批量新增产品授权码 - */ - @PreAuthorize("@ss.hasPermi('iot:authorize:add')") - @Log(title = "根据数量批量新增产品授权码", businessType = BusinessType.INSERT) - @PostMapping("addProductAuthorizeByNum") - public AjaxResult addProductAuthorizeByNum(@RequestBody ProductAuthorizeVO productAuthorizeVO) - { - return toAjax(productAuthorizeService.addProductAuthorizeByNum(productAuthorizeVO)); - } - - /** - * 修改产品授权码 - */ - @PreAuthorize("@ss.hasPermi('iot:authorize:edit')") - @Log(title = "产品授权码", businessType = BusinessType.UPDATE) - @PutMapping - public AjaxResult edit(@RequestBody ProductAuthorize productAuthorize) - { - return toAjax(productAuthorizeService.updateProductAuthorize(productAuthorize)); - } - - /** - * 删除产品授权码 - */ - @PreAuthorize("@ss.hasPermi('iot:authorize:remove')") - @Log(title = "产品授权码", businessType = BusinessType.DELETE) - @DeleteMapping("/{authorizeIds}") - public AjaxResult remove(@PathVariable Long[] authorizeIds) - { - return toAjax(productAuthorizeService.deleteProductAuthorizeByAuthorizeIds(authorizeIds)); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/ProductController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/ProductController.java deleted file mode 100644 index 37cbe959..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/ProductController.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.ruoyi.iot.controller; - -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.page.TableDataInfo; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.iot.domain.Product; -import com.ruoyi.iot.model.ChangeProductStatusModel; -import com.ruoyi.iot.model.IdAndName; -import com.ruoyi.iot.service.IProductService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; - -import javax.servlet.http.HttpServletResponse; -import java.util.ArrayList; -import java.util.List; - -/** - * 产品Controller - * - * @author kerwincui - * @date 2021-12-16 - */ -@Api(tags = "产品管理") -@RestController -@RequestMapping("/iot/product") -public class ProductController extends BaseController -{ - @Autowired - private IProductService productService; - - /** - * 查询产品列表 - */ - @GetMapping("/list") - @ApiOperation("产品分页列表") - public TableDataInfo list(Product product) - { - startPage(); - return getDataTable(productService.selectProductList(product)); - } - - /** - * 查询产品简短列表 - */ - @PreAuthorize("@ss.hasPermi('iot:product:list')") - @GetMapping("/shortList") - @ApiOperation("产品简短列表") - public AjaxResult shortList(Product product) - { - - List list = productService.selectProductShortList(); - return AjaxResult.success(list); - } - - /** - * 导出产品列表 - */ - @PreAuthorize("@ss.hasPermi('iot:product:export')") - @Log(title = "产品", businessType = BusinessType.EXPORT) - @PostMapping("/export") - @ApiOperation("导出产品") - public void export(HttpServletResponse response, Product product) - { - List list = productService.selectProductList(product); - ExcelUtil util = new ExcelUtil(Product.class); - util.exportExcel(response, list, "产品数据"); - } - - /** - * 获取产品详细信息 - */ - @PreAuthorize("@ss.hasPermi('iot:product:query')") - @GetMapping(value = "/{productId}") - @ApiOperation("获取产品详情") - public AjaxResult getInfo(@PathVariable("productId") Long productId) - { - return AjaxResult.success(productService.selectProductByProductId(productId)); - } - - /** - * 新增产品 - */ - @PreAuthorize("@ss.hasPermi('iot:product:add')") - @Log(title = "产品", businessType = BusinessType.INSERT) - @PostMapping - @ApiOperation("添加产品") - public AjaxResult add(@RequestBody Product product) - { - return AjaxResult.success(productService.insertProduct(product)); - } - - /** - * 修改产品 - */ - @PreAuthorize("@ss.hasPermi('iot:product:edit')") - @Log(title = "产品", businessType = BusinessType.UPDATE) - @PutMapping - @ApiOperation("修改产品") - public AjaxResult edit(@RequestBody Product product) - { - return toAjax(productService.updateProduct(product)); - } - - /** - * 发布产品 - */ - @PreAuthorize("@ss.hasPermi('iot:product:edit')") - @Log(title = "更新产品状态", businessType = BusinessType.UPDATE) - @PutMapping("/status") - @ApiOperation("更新产品状态") - public AjaxResult changeProductStatus(@RequestBody ChangeProductStatusModel model) - { - return productService.changeProductStatus(model); - } - - /** - * 删除产品 - */ - @PreAuthorize("@ss.hasPermi('iot:product:remove')") - @Log(title = "产品", businessType = BusinessType.DELETE) - @DeleteMapping("/{productIds}") - @ApiOperation("批量删除产品") - public AjaxResult remove(@PathVariable Long[] productIds) - { - return productService.deleteProductByProductIds(productIds); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/SceneController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/SceneController.java deleted file mode 100644 index 944e033f..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/SceneController.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.ruoyi.iot.controller; - -import java.util.List; -import javax.servlet.http.HttpServletResponse; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.iot.domain.Scene; -import com.ruoyi.iot.service.ISceneService; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.common.core.page.TableDataInfo; - -/** - * 场景联动Controller - * - * @author kerwincui - * @date 2022-01-13 - */ -@RestController -@RequestMapping("/iot/scene") -public class SceneController extends BaseController -{ - @Autowired - private ISceneService sceneService; - - /** - * 查询场景联动列表 - */ - @PreAuthorize("@ss.hasPermi('iot:scene:list')") - @GetMapping("/list") - public TableDataInfo list(Scene scene) - { - startPage(); - List list = sceneService.selectSceneList(scene); - return getDataTable(list); - } - - /** - * 导出场景联动列表 - */ - @PreAuthorize("@ss.hasPermi('iot:scene:export')") - @Log(title = "场景联动", businessType = BusinessType.EXPORT) - @PostMapping("/export") - public void export(HttpServletResponse response, Scene scene) - { - List list = sceneService.selectSceneList(scene); - ExcelUtil util = new ExcelUtil(Scene.class); - util.exportExcel(response, list, "场景联动数据"); - } - - /** - * 获取场景联动详细信息 - */ - @PreAuthorize("@ss.hasPermi('iot:scene:query')") - @GetMapping(value = "/{sceneId}") - public AjaxResult getInfo(@PathVariable("sceneId") Long sceneId) - { - return AjaxResult.success(sceneService.selectSceneBySceneId(sceneId)); - } - - /** - * 新增场景联动 - */ - @PreAuthorize("@ss.hasPermi('iot:scene:add')") - @Log(title = "场景联动", businessType = BusinessType.INSERT) - @PostMapping - public AjaxResult add(@RequestBody Scene scene) - { - return toAjax(sceneService.insertScene(scene)); - } - - /** - * 修改场景联动 - */ - @PreAuthorize("@ss.hasPermi('iot:scene:edit')") - @Log(title = "场景联动", businessType = BusinessType.UPDATE) - @PutMapping - public AjaxResult edit(@RequestBody Scene scene) - { - return toAjax(sceneService.updateScene(scene)); - } - - /** - * 删除场景联动 - */ - @PreAuthorize("@ss.hasPermi('iot:scene:remove')") - @Log(title = "场景联动", businessType = BusinessType.DELETE) - @DeleteMapping("/{sceneIds}") - public AjaxResult remove(@PathVariable Long[] sceneIds) - { - return toAjax(sceneService.deleteSceneBySceneIds(sceneIds)); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/SocialLoginController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/SocialLoginController.java deleted file mode 100644 index 32d5a5c8..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/SocialLoginController.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.ruoyi.iot.controller; - -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.domain.model.BindLoginBody; -import com.ruoyi.common.core.domain.model.BindRegisterBody; -import com.ruoyi.iot.service.ISocialLoginService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiImplicitParam; -import io.swagger.annotations.ApiOperation; -import me.zhyd.oauth.model.AuthCallback; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * 第三方登录接口Controller - * - * @author json - * @date 2022-04-12 - */ -@Api(tags = "第三方登录接口") -@RestController -@RequestMapping("/auth") -public class SocialLoginController { - - @Autowired - private ISocialLoginService iSocialLoginService; - - - @GetMapping("/render/{source}") - @ApiOperation("跳转api") - @ApiImplicitParam(name = "source", value = "登录类型", required = true, dataType = "String", paramType = "path", dataTypeClass = String.class) - public void renderAuth(HttpServletResponse httpServletResponse, HttpServletRequest httpServletRequest, @PathVariable String source) throws IOException { - // 生成授权页面 - httpServletResponse.sendRedirect(iSocialLoginService.renderAuth(source, httpServletRequest)); - } - - @GetMapping("/callback/{source}") - @ApiOperation("回调api") - @ApiImplicitParam(name = "source", value = "平台来源", required = true, dataType = "String", paramType = "path", dataTypeClass = String.class) - public void login(@PathVariable("source") String source, AuthCallback authCallback, HttpServletResponse httpServletResponse, HttpServletRequest httpServletRequest) throws IOException { - //回调接口 - httpServletResponse.sendRedirect(iSocialLoginService.callback(source, authCallback, httpServletRequest)); - } - - @GetMapping("/checkBindId/{bindId}") - @ApiOperation("检查bindId") - @ApiImplicitParam(name = "bindId", value = "绑定ID", required = true, dataType = "String", paramType = "path", dataTypeClass = String.class) - public AjaxResult checkBindId(HttpServletResponse httpServletResponse, @PathVariable String bindId) { - return iSocialLoginService.checkBindId(bindId); - } - - @GetMapping("/getErrorMsg/{errorId}") - @ApiOperation("获取errorMsg") - @ApiImplicitParam(name = "errorId", value = "错误提示ID", required = true, dataType = "String", paramType = "path", dataTypeClass = String.class) - public AjaxResult getErrorMsg(HttpServletResponse httpServletResponse, @PathVariable String errorId) { - return iSocialLoginService.getErrorMsg(errorId); - } - - /** - * 已经绑定账户,跳转登录接口 - * - * @param loginId - * @return - */ - @GetMapping("/login/{loginId}") - @ApiOperation("跳转登录api") - @ApiImplicitParam(name = "loginId", value = "登录Id", required = true, dataType = "String", paramType = "path", dataTypeClass = String.class) - public AjaxResult socialLogin(@PathVariable String loginId) { - // 生成授权页面 - return iSocialLoginService.socialLogin(loginId); - } - - /** - * 登录方法 - * - * @param bindLoginBody 绑定登录信息 - * @return 结果 - */ - @PostMapping("/bind/login") - public AjaxResult bindLogin(@RequestBody BindLoginBody bindLoginBody) { - return iSocialLoginService.bindLogin(bindLoginBody); - } - - /** - * 注册绑定接口 - * - * @param bindRegisterBody 注册信息 - * @return - */ - @PostMapping("/bind/register") - public AjaxResult bindRegister(@RequestBody BindRegisterBody bindRegisterBody) { - return iSocialLoginService.bindRegister(bindRegisterBody); - } - - -} - - - diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/SocialPlatformController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/SocialPlatformController.java deleted file mode 100644 index 4a6e3ffb..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/SocialPlatformController.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.ruoyi.iot.controller; - -import java.util.List; -import javax.servlet.http.HttpServletResponse; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.iot.domain.SocialPlatform; -import com.ruoyi.iot.service.ISocialPlatformService; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.common.core.page.TableDataInfo; - -/** - * 第三方登录平台控制Controller - * - * @author kerwincui - * @date 2022-04-11 - */ -@Api(tags = "第三方登录平台") -@RestController -@RequestMapping("/iot/platform") -public class SocialPlatformController extends BaseController { - @Autowired - private ISocialPlatformService socialPlatformService; - - /** - * 查询第三方登录平台控制列表 - */ - @PreAuthorize("@ss.hasPermi('iot:platform:list')") - @GetMapping("/list") - @ApiOperation("第三方登录平台分页列表") - public TableDataInfo list(SocialPlatform socialPlatform) { - startPage(); - List list = socialPlatformService.selectSocialPlatformList(socialPlatform); - return getDataTable(list); - } - - /** - * 导出第三方登录平台控制列表 - */ - @PreAuthorize("@ss.hasPermi('iot:platform:export')") - @Log(title = "第三方登录平台控制", businessType = BusinessType.EXPORT) - @PostMapping("/export") - public void export(HttpServletResponse response, SocialPlatform socialPlatform) { - List list = socialPlatformService.selectSocialPlatformList(socialPlatform); - ExcelUtil util = new ExcelUtil(SocialPlatform.class); - util.exportExcel(response, list, "第三方登录平台控制数据"); - } - - /** - * 获取第三方登录平台控制详细信息 - */ - @PreAuthorize("@ss.hasPermi('iot:platform:query')") - @GetMapping(value = "/{socialPlatformId}") - public AjaxResult getInfo(@PathVariable("socialPlatformId") Long socialPlatformId) { - return AjaxResult.success(socialPlatformService.selectSocialPlatformBySocialPlatformId(socialPlatformId)); - } - - /** - * 新增第三方登录平台控制 - */ - @PreAuthorize("@ss.hasPermi('iot:platform:add')") - @Log(title = "第三方登录平台控制", businessType = BusinessType.INSERT) - @PostMapping - public AjaxResult add(@RequestBody SocialPlatform socialPlatform) { - socialPlatform.setCreateBy(getUsername()); - return toAjax(socialPlatformService.insertSocialPlatform(socialPlatform)); - } - - /** - * 修改第三方登录平台控制 - */ - @PreAuthorize("@ss.hasPermi('iot:platform:edit')") - @Log(title = "第三方登录平台控制", businessType = BusinessType.UPDATE) - @PutMapping - public AjaxResult edit(@RequestBody SocialPlatform socialPlatform) { - socialPlatform.setUpdateBy(getUsername()); - return toAjax(socialPlatformService.updateSocialPlatform(socialPlatform)); - } - - /** - * 删除第三方登录平台控制 - */ - @PreAuthorize("@ss.hasPermi('iot:platform:remove')") - @Log(title = "第三方登录平台控制", businessType = BusinessType.DELETE) - @DeleteMapping("/{socialPlatformIds}") - public AjaxResult remove(@PathVariable Long[] socialPlatformIds) { - return toAjax(socialPlatformService.deleteSocialPlatformBySocialPlatformIds(socialPlatformIds)); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/ThingsModelController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/ThingsModelController.java deleted file mode 100644 index e1fe3117..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/ThingsModelController.java +++ /dev/null @@ -1,138 +0,0 @@ -package com.ruoyi.iot.controller; - -import java.util.List; -import javax.servlet.http.HttpServletResponse; - -import com.ruoyi.iot.model.ImportThingsModelInput; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.iot.domain.ThingsModel; -import com.ruoyi.iot.service.IThingsModelService; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.common.core.page.TableDataInfo; - -/** - * 物模型Controller - * - * @author kerwincui - * @date 2021-12-16 - */ -@RestController -@RequestMapping("/iot/model") -@Api(tags="产品物模型") -public class ThingsModelController extends BaseController -{ - @Autowired - private IThingsModelService thingsModelService; - - /** - * 查询物模型列表 - */ - @PreAuthorize("@ss.hasPermi('iot:device:list')") - @GetMapping("/list") - @ApiOperation("产品物模型分页列表") - public TableDataInfo list(ThingsModel thingsModel) - { - startPage(); - List list = thingsModelService.selectThingsModelList(thingsModel); - return getDataTable(list); - } - - /** - * 获取物模型详细信息 - */ - @PreAuthorize("@ss.hasPermi('iot:device:query')") - @GetMapping(value = "/{modelId}") - @ApiOperation("获取产品物模型详情") - public AjaxResult getInfo(@PathVariable("modelId") Long modelId) - { - return AjaxResult.success(thingsModelService.selectThingsModelByModelId(modelId)); - } - - /** - * 新增物模型 - */ - @PreAuthorize("@ss.hasPermi('iot:device:add')") - @Log(title = "物模型", businessType = BusinessType.INSERT) - @PostMapping - @ApiOperation("添加产品物模型") - public AjaxResult add(@RequestBody ThingsModel thingsModel) - { - int result=thingsModelService.insertThingsModel(thingsModel); - if(result==1){ - return AjaxResult.success(); - }else if(result==2){ - return AjaxResult.error("产品下的标识符不能重复"); - }else{ - return AjaxResult.error(); - } - } - - @Log(title = "导入物模型",businessType = BusinessType.INSERT) - @PostMapping("/import") - @ApiOperation("导入通用物模型") - public AjaxResult ImportByTemplateIds(@RequestBody ImportThingsModelInput input){ - int repeatCount=thingsModelService.importByTemplateIds(input); - if(repeatCount==0){ - return AjaxResult.success("数据导入成功"); - }else{ - return AjaxResult.success(repeatCount+"条数据未导入,标识符重复"); - } - } - - /** - * 修改物模型 - */ - @PreAuthorize("@ss.hasPermi('iot:device:edit')") - @Log(title = "物模型", businessType = BusinessType.UPDATE) - @PutMapping - @ApiOperation("修改产品物模型") - public AjaxResult edit(@RequestBody ThingsModel thingsModel) - { - int result=thingsModelService.updateThingsModel(thingsModel); - if(result==1){ - return AjaxResult.success(); - }else if(result==2){ - return AjaxResult.error("产品下的标识符不能重复"); - }else{ - return AjaxResult.error(); - } - } - - /** - * 删除物模型 - */ - @PreAuthorize("@ss.hasPermi('iot:device:remove')") - @Log(title = "物模型", businessType = BusinessType.DELETE) - @DeleteMapping("/{modelIds}") - @ApiOperation("批量删除产品物模型") - public AjaxResult remove(@PathVariable Long[] modelIds) - { - return toAjax(thingsModelService.deleteThingsModelByModelIds(modelIds)); - } - - /** - * 获取缓存的JSON物模型 - */ - @PreAuthorize("@ss.hasPermi('iot:device:query')") - @GetMapping(value = "/cache/{productId}") - @ApiOperation("获取缓存的JSON物模型") - public AjaxResult getCacheThingsModelByProductId(@PathVariable("productId") Long productId) - { - return AjaxResult.success("操作成功",thingsModelService.getCacheThingsModelByProductId(productId)); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/ThingsModelTemplateController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/ThingsModelTemplateController.java deleted file mode 100644 index 910fc0e4..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/ThingsModelTemplateController.java +++ /dev/null @@ -1,118 +0,0 @@ -package com.ruoyi.iot.controller; - -import java.util.ArrayList; -import java.util.List; -import javax.servlet.http.HttpServletResponse; - -import com.ruoyi.common.core.domain.entity.SysRole; -import com.ruoyi.common.core.domain.entity.SysUser; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.iot.domain.ThingsModelTemplate; -import com.ruoyi.iot.service.IThingsModelTemplateService; -import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.common.core.page.TableDataInfo; - -import static com.ruoyi.common.utils.SecurityUtils.getLoginUser; - -/** - * 通用物模型Controller - * - * @author kerwincui - * @date 2021-12-16 - */ -@RestController -@RequestMapping("/iot/template") -@Api(tags = "通用物模型") -public class ThingsModelTemplateController extends BaseController -{ - @Autowired - private IThingsModelTemplateService thingsModelTemplateService; - - /** - * 查询通用物模型列表 - */ - @PreAuthorize("@ss.hasPermi('iot:template:list')") - @GetMapping("/list") - @ApiOperation("通用物模型分页列表") - public TableDataInfo list(ThingsModelTemplate thingsModelTemplate) - { - startPage(); - return getDataTable(thingsModelTemplateService.selectThingsModelTemplateList(thingsModelTemplate)); - } - - /** - * 导出通用物模型列表 - */ - @PreAuthorize("@ss.hasPermi('iot:template:export')") - @Log(title = "通用物模型", businessType = BusinessType.EXPORT) - @PostMapping("/export") - @ApiOperation("导出通用物模型") - public void export(HttpServletResponse response, ThingsModelTemplate thingsModelTemplate) - { - List list = thingsModelTemplateService.selectThingsModelTemplateList(thingsModelTemplate); - ExcelUtil util = new ExcelUtil(ThingsModelTemplate.class); - util.exportExcel(response, list, "通用物模型数据"); - } - - /** - * 获取通用物模型详细信息 - */ - @PreAuthorize("@ss.hasPermi('iot:template:query')") - @GetMapping(value = "/{templateId}") - @ApiOperation("获取通用物模型详情") - public AjaxResult getInfo(@PathVariable("templateId") Long templateId) - { - return AjaxResult.success(thingsModelTemplateService.selectThingsModelTemplateByTemplateId(templateId)); - } - - /** - * 新增通用物模型 - */ - @PreAuthorize("@ss.hasPermi('iot:template:add')") - @Log(title = "通用物模型", businessType = BusinessType.INSERT) - @PostMapping - @ApiOperation("添加通用物模型") - public AjaxResult add(@RequestBody ThingsModelTemplate thingsModelTemplate) - { - return toAjax(thingsModelTemplateService.insertThingsModelTemplate(thingsModelTemplate)); - } - - /** - * 修改通用物模型 - */ - @PreAuthorize("@ss.hasPermi('iot:template:edit')") - @Log(title = "通用物模型", businessType = BusinessType.UPDATE) - @PutMapping - @ApiOperation("修改通用物模型") - public AjaxResult edit(@RequestBody ThingsModelTemplate thingsModelTemplate) - { - return toAjax(thingsModelTemplateService.updateThingsModelTemplate(thingsModelTemplate)); - } - - /** - * 删除通用物模型 - */ - @PreAuthorize("@ss.hasPermi('iot:template:remove')") - @Log(title = "通用物模型", businessType = BusinessType.DELETE) - @DeleteMapping("/{templateIds}") - @ApiOperation("批量删除通用物模型") - public AjaxResult remove(@PathVariable Long[] templateIds) - { - return toAjax(thingsModelTemplateService.deleteThingsModelTemplateByTemplateIds(templateIds)); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/ToolController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/ToolController.java deleted file mode 100644 index 5e60b22d..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/ToolController.java +++ /dev/null @@ -1,365 +0,0 @@ -package com.ruoyi.iot.controller; - -import com.alibaba.fastjson.JSONObject; -import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.config.RuoYiConfig; -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.domain.entity.SysUser; -import com.ruoyi.common.core.page.TableDataInfo; -import com.ruoyi.common.core.redis.RedisCache; -import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.common.exception.file.FileNameLengthLimitExceededException; -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.file.FileUploadUtils; -import com.ruoyi.common.utils.file.FileUtils; -import com.ruoyi.iot.domain.Device; -import com.ruoyi.iot.domain.ProductAuthorize; -import com.ruoyi.iot.mapper.ProductAuthorizeMapper; -import com.ruoyi.iot.model.*; -import com.ruoyi.iot.model.ThingsModels.ThingsModelShadow; -import com.ruoyi.iot.mqtt.EmqxService; -import com.ruoyi.iot.mqtt.MqttConfig; -import com.ruoyi.iot.service.IDeviceService; -import com.ruoyi.iot.service.IProductAuthorizeService; -import com.ruoyi.iot.service.IToolService; -import com.ruoyi.iot.service.impl.ThingsModelServiceImpl; -import com.ruoyi.iot.util.AESUtils; -import com.ruoyi.iot.util.VelocityInitializer; -import com.ruoyi.iot.util.VelocityUtils; -import com.ruoyi.system.service.ISysUserService; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jwts; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import org.apache.commons.io.IOUtils; -import org.apache.velocity.Template; -import org.apache.velocity.VelocityContext; -import org.apache.velocity.app.Velocity; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Lazy; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.StringWriter; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.List; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -import static com.ruoyi.common.utils.file.FileUploadUtils.getExtension; - -/** - * 产品分类Controller - * - * @author kerwincui - * @date 2021-12-16 - */ -@Api(tags = "工具相关") -@RestController -@RequestMapping("/iot/tool") -public class ToolController extends BaseController { - private static final Logger log = LoggerFactory.getLogger(ToolController.class); - - @Autowired - private IDeviceService deviceService; - - @Lazy - @Autowired - private EmqxService emqxService; - - @Autowired - private MqttConfig mqttConfig; - - @Autowired - private IToolService toolService; - - // 令牌秘钥 - @Value("${token.secret}") - private String secret; - - @Autowired - private RedisCache redisCache; - - /** - * 用户注册 - */ - @ApiOperation("用户注册") - @PostMapping("/register") - public AjaxResult register(@RequestBody RegisterUserInput user) { - String msg = toolService.register(user); - return StringUtils.isEmpty(msg) ? success() : error(msg); - } - - /** - * 获取用户列表 - */ - @GetMapping("/userList") - public TableDataInfo list(SysUser user) - { - startPage(); - List list = toolService.selectUserList(user); - return getDataTable(list); - } - - @ApiOperation("mqtt认证") - @PostMapping("/mqtt/auth") - public ResponseEntity mqttAuth(@RequestParam String clientid, @RequestParam String username, @RequestParam String password) throws Exception { - if (clientid.startsWith("server")) { - // 服务端认证:配置的账号密码认证 - if (mqttConfig.getusername().equals(username) && mqttConfig.getpassword().equals(password)) { - log.info("-----------服务端mqtt认证成功,clientId:" + clientid + "---------------"); - return ResponseEntity.ok().body("ok"); - } else { - return toolService.returnUnauthorized(new MqttAuthenticationModel(clientid, username, password), "mqtt账号和密码与认证服务器配置不匹配"); - } - } else if (clientid.startsWith("web") || clientid.startsWith("phone")) { - // web端和移动端认证:token认证 - String token = password; - if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX)) { - token = token.replace(Constants.TOKEN_PREFIX, ""); - } - try { - Claims claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody(); - log.info("-----------移动端/Web端mqtt认证成功,clientId:" + clientid + "---------------"); - return ResponseEntity.ok().body("ok"); - } catch (Exception ex) { - return toolService.returnUnauthorized(new MqttAuthenticationModel(clientid, username, password), ex.getMessage()); - } - } else { - // 设备端认证:加密认证(E)和简单认证(S,配置的账号密码认证) - String[] clientArray = clientid.split("&"); - if(clientArray.length != 4 || clientArray[0].equals("") || clientArray[1].equals("") || clientArray[2].equals("") || clientArray[3].equals("")){ - return toolService.returnUnauthorized(new MqttAuthenticationModel(clientid, username, password), "设备mqtt客户端Id格式为:认证类型 & 设备编号 & 产品ID & 用户ID"); - } - String authType = clientArray[0]; - String deviceNumber = clientArray[1]; - Long productId = Long.valueOf(clientArray[2]); - Long userId = Long.valueOf(clientArray[3]); - // 产品认证信息 - ProductAuthenticateModel model = deviceService.selectProductAuthenticate(new AuthenticateInputModel(deviceNumber, productId)); - if (model == null) { - return toolService.returnUnauthorized(new MqttAuthenticationModel(clientid, username, password), "设备认证,通过产品ID查询不到信息"); - } - if (model.getProductStatus() != 2) { - // 产品必须为发布状态:1-未发布,2-已发布 - return toolService.returnUnauthorized(new MqttAuthenticationModel(clientid, username, password), "设备认证,设备对应产品还未发布"); - } - - if (authType.equals("S")) { - // 设备简单认证 - return toolService.simpleMqttAuthentication(new MqttAuthenticationModel(clientid, username, password, deviceNumber, productId, userId), model); - - } else if (authType.equals("E")) { - // 设备加密认证 - return toolService.encryptAuthentication(new MqttAuthenticationModel(clientid, username, password, deviceNumber, productId, userId), model); - } else { - return toolService.returnUnauthorized(new MqttAuthenticationModel(clientid, username, password), "设备认证,认证类型有误"); - } - } - } - - - @ApiOperation("mqtt钩子处理") - @PostMapping("/mqtt/webhook") - public void webHookProcess(@RequestBody MqttClientConnectModel model) { - try { - System.out.println("webhook:" + model.getAction()); - // 过滤服务端、web端和手机端 - if (model.getClientid().startsWith("server") || model.getClientid().startsWith("web") || model.getClientid().startsWith("phone")) { - return; - } - // 设备端认证:加密认证(E)和简单认证(S,配置的账号密码认证) - String[] clientArray = model.getClientid().split("&"); - String authType = clientArray[0]; - String deviceNumber = clientArray[1]; - Long productId = Long.valueOf(clientArray[2]); - Long userId = Long.valueOf(clientArray[3]); - - Device device = deviceService.selectShortDeviceBySerialNumber(deviceNumber); - // 设备状态(1-未激活,2-禁用,3-在线,4-离线) - if (model.getAction().equals("client_disconnected")) { - device.setStatus(4); - deviceService.updateDeviceStatusAndLocation(device, ""); - // 设备掉线后发布设备状态 - emqxService.publishStatus(device.getProductId(), device.getSerialNumber(), 4, device.getIsShadow(),device.getRssi()); - // 清空保留消息,上线后发布新的属性功能保留消息 - emqxService.publishProperty(device.getProductId(), device.getSerialNumber(), null); - emqxService.publishFunction(device.getProductId(), device.getSerialNumber(), null); - } else if (model.getAction().equals("client_connected")) { - device.setStatus(3); - deviceService.updateDeviceStatusAndLocation(device, model.getIpaddress()); - // 影子模式,发布属性和功能 - if (device.getIsShadow() == 1) { - ThingsModelShadow shadow = deviceService.getDeviceShadowThingsModel(device); - if (shadow.getProperties().size() > 0) { - emqxService.publishProperty(device.getProductId(), device.getSerialNumber(), shadow.getProperties()); - } - if (shadow.getFunctions().size() > 0) { - emqxService.publishFunction(device.getProductId(), device.getSerialNumber(), shadow.getFunctions()); - } - } - } - } catch (Exception ex) { - ex.printStackTrace(); - log.error("发生错误:" + ex.getMessage()); - } - } - - - @ApiOperation("获取NTP时间") - @GetMapping("/ntp") - public JSONObject ntp(@RequestParam Long deviceSendTime) { - JSONObject ntpJson = new JSONObject(); - ntpJson.put("deviceSendTime", deviceSendTime); - ntpJson.put("serverRecvTime", System.currentTimeMillis()); - ntpJson.put("serverSendTime", System.currentTimeMillis()); - return ntpJson; - } - - /** - * 文件上传 - */ - @PostMapping("/upload") - @ApiOperation("文件上传") - public AjaxResult uploadFile(MultipartFile file) throws Exception { - try { - String filePath = RuoYiConfig.getProfile(); - // 文件名长度限制 - int fileNamelength = file.getOriginalFilename().length(); - if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) { - throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH); - } - // 文件类型限制 - // assertAllowed(file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION); - - // 获取文件名和文件类型 - String fileName = file.getOriginalFilename(); - String extension = getExtension(file); - //设置日期格式 - SimpleDateFormat df = new SimpleDateFormat("yyyy-MMdd-HHmmss"); - fileName = "/iot/" + getLoginUser().getUserId().toString() + "/" + df.format(new Date()) + "." + extension; - //创建目录 - File desc = new File(filePath + File.separator + fileName); - if (!desc.exists()) { - if (!desc.getParentFile().exists()) { - desc.getParentFile().mkdirs(); - } - } - // 存储文件 - file.transferTo(desc); - - String url = "/profile" + fileName; - AjaxResult ajax = AjaxResult.success(); - ajax.put("fileName", url); - ajax.put("url", url); - return ajax; - } catch (Exception e) { - return AjaxResult.error(e.getMessage()); - } - } - - /** - * 下载文件 - */ - @ApiOperation("文件下载") - @GetMapping("/download") - public void download(String fileName, HttpServletResponse response, HttpServletRequest request) { - try { -// if (!FileUtils.checkAllowDownload(fileName)) { -// throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName)); -// } - String filePath = RuoYiConfig.getProfile(); - // 资源地址 - String downloadPath = filePath + fileName.replace("/profile", ""); - // 下载名称 - String downloadName = StringUtils.substringAfterLast(downloadPath, "/"); - response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); - FileUtils.setAttachmentResponseHeader(response, downloadName); - FileUtils.writeBytes(downloadPath, response.getOutputStream()); - } catch (Exception e) { - log.error("下载文件失败", e); - } - } - - /** - * 批量生成代码 - */ - @Log(title = "SDK生成", businessType = BusinessType.GENCODE) - @GetMapping("/genSdk") - @ApiOperation("生成SDK") - public void genSdk(HttpServletResponse response, int deviceChip) throws IOException { - byte[] data = downloadCode(deviceChip); - genSdk(response, data); - } - - /** - * 生成zip文件 - */ - private void genSdk(HttpServletResponse response, byte[] data) throws IOException { - response.reset(); - response.addHeader("Access-Control-Allow-Origin", "*"); - response.addHeader("Access-Control-Expose-Headers", "Content-Disposition"); - response.setHeader("Content-Disposition", "attachment; filename=\"ruoyi.zip\""); - response.addHeader("Content-Length", "" + data.length); - response.setContentType("application/octet-stream; charset=UTF-8"); - IOUtils.write(data, response.getOutputStream()); - } - - /** - * 批量生成代码(下载方式) - * - * @param deviceChip - * @return 数据 - */ - public byte[] downloadCode(int deviceChip) { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - ZipOutputStream zip = new ZipOutputStream(outputStream); -// generatorCode(deviceChip, zip); - IOUtils.closeQuietly(zip); - return outputStream.toByteArray(); - } - - /** - * 查询表信息并生成代码 - */ - private void generatorCode(int deviceChip, ZipOutputStream zip) { - VelocityInitializer.initVelocity(); - - VelocityContext context = VelocityUtils.prepareContext(deviceChip); - - // 获取模板列表 - List templates = VelocityUtils.getTemplateList(""); - for (String template : templates) { - // 渲染模板 - StringWriter sw = new StringWriter(); - Template tpl = Velocity.getTemplate(template, Constants.UTF8); - tpl.merge(context, sw); - try { - // 添加到zip - zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template))); - IOUtils.write(sw.toString(), zip, Constants.UTF8); - IOUtils.closeQuietly(sw); - zip.flush(); - zip.closeEntry(); - } catch (IOException e) { - System.out.println("渲染模板失败"); - } - } - } - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/UserSocialController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/UserSocialController.java deleted file mode 100644 index a761a9f0..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/UserSocialController.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.ruoyi.iot.controller; - -import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.iot.service.IUserSocialProfileService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiImplicitParam; -import io.swagger.annotations.ApiOperation; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -/** - * 第三方登录平台控制Controller - * - * @author json - * @date 2022-04-24 - */ -@Api(tags = "用户社交账户api") -@RestController -@RequestMapping("/iot/social/") -public class UserSocialController extends BaseController { - - @Autowired - private IUserSocialProfileService iUserSocialProfileService; - - - /** - * 绑定 - * - * @param bindId 绑定id - * @return - */ - @GetMapping("/bindId/{bindId}") - @ApiOperation("绑定api") - @ApiImplicitParam(name = "bindId", value = "绑定bindId", required = true, dataType = "String", paramType = "path", dataTypeClass = String.class) - public AjaxResult bindUser(@PathVariable String bindId) { - return iUserSocialProfileService.bindUser(bindId, getUserId()); - } - - - /** - * 绑定 - * - * @param platform 绑定类型 - * @return - */ - @GetMapping("/bind/{platform}") - @ApiOperation("绑定跳转api") - @ApiImplicitParam(name = "platform", value = "绑定platform", required = true, dataType = "String", paramType = "path", dataTypeClass = String.class) - public AjaxResult bind(@PathVariable String platform) { - return iUserSocialProfileService.bindSocialAccount(platform); - } - - /** - * 解绑 - * - * @param socialUserId 用户社交平台Id - * @return - */ - @GetMapping("/unbind/{socialUserId}") - @ApiOperation("解绑api") - @ApiImplicitParam(name = "socialUserId", value = "绑定socialId", required = true, dataType = "Long", paramType = "path", dataTypeClass = Long.class) - public AjaxResult unbind(@PathVariable Long socialUserId) { - return iUserSocialProfileService.unbindSocialAccount(socialUserId, getUserId()); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/Alert.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/Alert.java deleted file mode 100644 index f0c12d91..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/Alert.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.ruoyi.iot.domain; - -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.common.annotation.Excel; -import com.ruoyi.common.core.domain.BaseEntity; - -/** - * 设备告警对象 iot_alert - * - * @author kerwincui - * @date 2022-01-13 - */ -public class Alert extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 告警ID */ - private Long alertId; - - /** 告警名称 */ - @Excel(name = "告警名称") - private String alertName; - - /** 告警级别(1=提醒通知,2=轻微问题,3=严重警告) */ - @Excel(name = "告警级别", readConverterExp = "1==提醒通知,2=轻微问题,3=严重警告") - private Long alertLevel; - - /** 产品ID */ - @Excel(name = "产品ID") - private Long productId; - - /** 产品名称 */ - @Excel(name = "产品名称") - private String productName; - - /** 触发器 */ - @Excel(name = "触发器") - private String triggers; - - /** 执行动作 */ - @Excel(name = "执行动作") - private String actions; - - /** 告警状态 (1-启动,2-停止)**/ - private Integer status; - - public Integer getStatus() { - return status; - } - - public void setStatus(Integer status) { - this.status = status; - } - - public void setAlertId(Long alertId) - { - this.alertId = alertId; - } - - public Long getAlertId() - { - return alertId; - } - public void setAlertName(String alertName) - { - this.alertName = alertName; - } - - public String getAlertName() - { - return alertName; - } - public void setAlertLevel(Long alertLevel) - { - this.alertLevel = alertLevel; - } - - public Long getAlertLevel() - { - return alertLevel; - } - public void setProductId(Long productId) - { - this.productId = productId; - } - - public Long getProductId() - { - return productId; - } - public void setProductName(String productName) - { - this.productName = productName; - } - - public String getProductName() - { - return productName; - } - public void setTriggers(String triggers) - { - this.triggers = triggers; - } - - public String getTriggers() - { - return triggers; - } - public void setActions(String actions) - { - this.actions = actions; - } - - public String getActions() - { - return actions; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("alertId", getAlertId()) - .append("alertName", getAlertName()) - .append("alertLevel", getAlertLevel()) - .append("productId", getProductId()) - .append("productName", getProductName()) - .append("triggers", getTriggers()) - .append("actions", getActions()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("remark", getRemark()) - .toString(); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/AlertLog.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/AlertLog.java deleted file mode 100644 index 09368061..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/AlertLog.java +++ /dev/null @@ -1,188 +0,0 @@ -package com.ruoyi.iot.domain; - -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.common.annotation.Excel; -import com.ruoyi.common.core.domain.BaseEntity; - -/** - * 设备告警对象 iot_alert_log - * - * @author kerwincui - * @date 2022-01-13 - */ -public class AlertLog extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 告警ID */ - private Long alertLogId; - - /** 告警名称 */ - @Excel(name = "告警名称") - private String alertName; - - /** 告警级别(1=提醒通知,2=轻微问题,3=严重警告,4=场景联动) */ - @Excel(name = "告警级别", readConverterExp = "1==提醒通知,2=轻微问题,3=严重警告,4=场景联动") - private Long alertLevel; - - /** 处理状态(0=不需要处理,1=未处理,2=已处理) */ - @Excel(name = "处理状态(0=不需要处理,1=未处理,2=已处理)") - private Long status; - - /** 产品ID */ - @Excel(name = "产品ID") - private Long productId; - - /** 产品名称 */ - @Excel(name = "产品名称") - private String productName; - - /** 设备ID */ - @Excel(name = "设备ID") - private Long deviceId; - - /** 设备名称 */ - @Excel(name = "设备名称") - private String deviceName; - - /** 用户ID */ - @Excel(name = "用户ID") - private Long userId; - - /** 用户昵称 */ - @Excel(name = "用户昵称") - private String userName; - - /** 租户ID */ - @Excel(name = "租户ID") - private Long tenantId; - - /** 租户名称 */ - @Excel(name = "租户名称") - private String tenantName; - - public Long getUserId() { - return userId; - } - - public void setUserId(Long userId) { - this.userId = userId; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public Long getTenantId() { - return tenantId; - } - - public void setTenantId(Long tenantId) { - this.tenantId = tenantId; - } - - public String getTenantName() { - return tenantName; - } - - public void setTenantName(String tenantName) { - this.tenantName = tenantName; - } - - public void setAlertLogId(Long alertLogId) - { - this.alertLogId = alertLogId; - } - - public Long getAlertLogId() - { - return alertLogId; - } - public void setAlertName(String alertLogName) - { - this.alertName = alertLogName; - } - - public String getAlertName() - { - return alertName; - } - public void setAlertLevel(Long alertLevel) - { - this.alertLevel = alertLevel; - } - - public Long getAlertLevel() - { - return alertLevel; - } - public void setStatus(Long status) - { - this.status = status; - } - - public Long getStatus() - { - return status; - } - public void setProductId(Long productId) - { - this.productId = productId; - } - - public Long getProductId() - { - return productId; - } - public void setProductName(String productName) - { - this.productName = productName; - } - - public String getProductName() - { - return productName; - } - public void setDeviceId(Long deviceId) - { - this.deviceId = deviceId; - } - - public Long getDeviceId() - { - return deviceId; - } - public void setDeviceName(String deviceName) - { - this.deviceName = deviceName; - } - - public String getDeviceName() - { - return deviceName; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("alertLogId", getAlertLogId()) - .append("alertName", getAlertName()) - .append("alertLevel", getAlertLevel()) - .append("status", getStatus()) - .append("productId", getProductId()) - .append("productName", getProductName()) - .append("deviceId", getDeviceId()) - .append("deviceName", getDeviceName()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("remark", getRemark()) - .toString(); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/Category.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/Category.java deleted file mode 100644 index c5c9de6c..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/Category.java +++ /dev/null @@ -1,124 +0,0 @@ -package com.ruoyi.iot.domain; - -import com.ruoyi.common.core.domain.BaseEntity; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.common.annotation.Excel; - -/** - * 产品分类对象 iot_category - * - * @author kerwincui - * @date 2021-12-16 - */ -public class Category extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 产品分类ID */ - private Long categoryId; - - /** 产品分类名称 */ - @Excel(name = "产品分类名称") - private String categoryName; - - /** 租户ID */ - @Excel(name = "租户ID") - private Long tenantId; - - /** 租户名称 */ - @Excel(name = "租户名称") - private String tenantName; - - /** 是否系统通用(0-否,1-是) */ - @Excel(name = "是否系统通用", readConverterExp = "0=-否,1-是") - private Integer isSys; - - /** 显示顺序 */ - @Excel(name = "显示顺序") - private Integer orderNum; - - /** 删除标志(0代表存在 2代表删除) */ - private String delFlag; - - public void setCategoryId(Long categoryId) - { - this.categoryId = categoryId; - } - - public Long getCategoryId() - { - return categoryId; - } - public void setCategoryName(String categoryName) - { - this.categoryName = categoryName; - } - - public String getCategoryName() - { - return categoryName; - } - public void setTenantId(Long tenantId) - { - this.tenantId = tenantId; - } - - public Long getTenantId() - { - return tenantId; - } - public void setTenantName(String tenantName) - { - this.tenantName = tenantName; - } - - public String getTenantName() - { - return tenantName; - } - public void setIsSys(Integer isSys) - { - this.isSys = isSys; - } - public Integer getIsSys() - { - return isSys; - } - - public void setOrderNum(Integer orderNum) - { - this.orderNum = orderNum; - } - public Integer getOrderNum() - { - return orderNum; - } - public void setDelFlag(String delFlag) - { - this.delFlag = delFlag; - } - - public String getDelFlag() - { - return delFlag; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("categoryId", getCategoryId()) - .append("categoryName", getCategoryName()) - .append("tenantId", getTenantId()) - .append("tenantName", getTenantName()) - .append("isSys", getIsSys()) - .append("orderNum", getOrderNum()) - .append("delFlag", getDelFlag()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("remark", getRemark()) - .toString(); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/Device.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/Device.java deleted file mode 100644 index c88d0a86..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/Device.java +++ /dev/null @@ -1,364 +0,0 @@ -package com.ruoyi.iot.domain; - -import com.fasterxml.jackson.annotation.JsonFormat; -import com.ruoyi.common.annotation.Excel; -import com.ruoyi.common.core.domain.BaseEntity; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; - -import java.math.BigDecimal; -import java.util.Date; - -/** - * 设备对象 iot_device - * - * @author kerwincui - * @date 2021-12-16 - */ -public class Device extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 产品分类ID */ - private Long deviceId; - - /** 产品分类名称 */ - @Excel(name = "设备名称") - private String deviceName; - - /** 产品ID */ - @Excel(name = "产品ID") - private Long productId; - - /** 产品名称 */ - @Excel(name = "产品名称") - private String productName; - - /** 用户ID */ - @Excel(name = "用户ID") - private Long userId; - - /** 用户昵称 */ - @Excel(name = "用户昵称") - private String userName; - - /** 租户ID */ - @Excel(name = "租户ID") - private Long tenantId; - - /** 租户名称 */ - @Excel(name = "租户名称") - private String tenantName; - - /** 设备编号 */ - @Excel(name = "设备编号") - private String serialNumber; - - /** 固件版本 */ - @Excel(name = "固件版本") - private BigDecimal firmwareVersion; - - /** 设备状态(1-未激活,2-禁用,3-在线,4-离线) */ - @Excel(name = "设备状态") - private Integer status; - - /** wifi信号强度(信号极好4格[-55— 0],信号好3格[-70— -55],信号一般2格[-85— -70],信号差1格[-100— -85]) */ - @Excel(name = "wifi信号强度") - private Integer rssi; - - /** 设备影子 */ - private Integer isShadow; - - /** 设备所在地址 */ - @Excel(name = "设备所在地址") - private String networkAddress; - - /** 设备入网IP */ - @Excel(name = "设备入网IP") - private String networkIp; - - /** 设备经度 */ - @Excel(name = "设备经度") - private BigDecimal longitude; - - /** 设备纬度 */ - @Excel(name = "设备纬度") - private BigDecimal latitude; - - /** 激活时间 */ - @JsonFormat(pattern = "yyyy-MM-dd") - @Excel(name = "激活时间", width = 30, dateFormat = "yyyy-MM-dd") - private Date activeTime; - - @Excel(name = "物模型") - private String thingsModelValue; - - /** 图片地址 */ - private String imgUrl; - - /** 是否自定义位置 **/ - private Integer locationWay; - - /** 设备摘要 **/ - private String summary; - - /** 分组ID,用于分组查询 **/ - private Long groupId; - - /** 是否设备所有者,用于查询 **/ - private Integer isOwner; - - public Integer getLocationWay() { - return locationWay; - } - - public void setLocationWay(Integer locationWay) { - this.locationWay = locationWay; - } - - public Integer getIsOwner() { - return isOwner; - } - - public void setIsOwner(Integer isOwner) { - this.isOwner = isOwner; - } - - /** 删除标志(0代表存在 2代表删除) */ - private String delFlag; - - public Long getGroupId() { - return groupId; - } - - public void setGroupId(Long groupId) { - this.groupId = groupId; - } - - public String getSummary() { - return summary; - } - - public void setSummary(String summary) { - this.summary = summary; - } - - public String getImgUrl() { - return imgUrl; - } - - public void setImgUrl(String imgUrl) { - this.imgUrl = imgUrl; - } - - public Integer getIsShadow() { - return isShadow; - } - - public void setIsShadow(Integer isShadow) { - this.isShadow = isShadow; - } - - public static long getSerialVersionUID() { - return serialVersionUID; - } - - public String getDelFlag() { - return delFlag; - } - - public void setDelFlag(String delFlag) { - this.delFlag = delFlag; - } - - public void setDeviceId(Long deviceId) - { - this.deviceId = deviceId; - } - - public Long getDeviceId() - { - return deviceId; - } - public void setDeviceName(String deviceName) - { - this.deviceName = deviceName; - } - - public String getDeviceName() - { - return deviceName; - } - public void setProductId(Long productId) - { - this.productId = productId; - } - - public Long getProductId() - { - return productId; - } - public void setProductName(String productName) - { - this.productName = productName; - } - - public String getProductName() - { - return productName; - } - public void setUserId(Long userId) - { - this.userId = userId; - } - - public Long getUserId() - { - return userId; - } - public void setUserName(String userName) - { - this.userName = userName; - } - - public String getUserName() - { - return userName; - } - public void setTenantId(Long tenantId) - { - this.tenantId = tenantId; - } - - public Long getTenantId() - { - return tenantId; - } - public void setTenantName(String tenantName) - { - this.tenantName = tenantName; - } - - public String getTenantName() - { - return tenantName; - } - public void setSerialNumber(String serialNumber) - { - this.serialNumber = serialNumber; - } - - public String getSerialNumber() - { - return serialNumber; - } - public void setFirmwareVersion(BigDecimal firmwareVersion) - { - this.firmwareVersion = firmwareVersion; - } - - public BigDecimal getFirmwareVersion() - { - return firmwareVersion; - } - public void setStatus(Integer status) - { - this.status = status; - } - - public Integer getStatus() - { - return status; - } - public void setRssi(Integer rssi) - { - this.rssi = rssi; - } - - public Integer getRssi() - { - return rssi; - } - public void setThingsModelValue(String thingsModelValue) - { - this.thingsModelValue = thingsModelValue; - } - - public String getThingsModelValue() - { - return thingsModelValue; - } - public void setNetworkAddress(String networkAddress) - { - this.networkAddress = networkAddress; - } - - public String getNetworkAddress() - { - return networkAddress; - } - public void setNetworkIp(String networkIp) - { - this.networkIp = networkIp; - } - - public String getNetworkIp() - { - return networkIp; - } - public void setLongitude(BigDecimal longitude) - { - this.longitude = longitude; - } - - public BigDecimal getLongitude() - { - return longitude; - } - public void setLatitude(BigDecimal latitude) - { - this.latitude = latitude; - } - - public BigDecimal getLatitude() - { - return latitude; - } - public void setActiveTime(Date activeTime) - { - this.activeTime = activeTime; - } - - public Date getActiveTime() - { - return activeTime; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("deviceId", getDeviceId()) - .append("deviceName", getDeviceName()) - .append("productId", getProductId()) - .append("productName", getProductName()) - .append("userId", getUserId()) - .append("userName", getUserName()) - .append("tenantId", getTenantId()) - .append("tenantName", getTenantName()) - .append("serialNumber", getSerialNumber()) - .append("firmwareVersion", getFirmwareVersion()) - .append("status", getStatus()) - .append("rssi", getRssi()) - .append("networkAddress", getNetworkAddress()) - .append("networkIp", getNetworkIp()) - .append("longitude", getLongitude()) - .append("latitude", getLatitude()) - .append("activeTime", getActiveTime()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("remark", getRemark()) - .toString(); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/DeviceGroup.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/DeviceGroup.java deleted file mode 100644 index 7eb49c26..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/DeviceGroup.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.ruoyi.iot.domain; - -import com.ruoyi.common.annotation.Excel; -import com.ruoyi.common.core.domain.BaseEntity; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; - -/** - * 设备分组对象 iot_device_group - * - * @author kerwincui - * @date 2021-12-16 - */ -public class DeviceGroup -{ - private static final long serialVersionUID = 1L; - - /** 分组ID */ - private Long groupId; - - /** 设备ID */ - private Long deviceId; - - public Long getGroupId() { - return groupId; - } - - public void setGroupId(Long groupId) { - this.groupId = groupId; - } - - public Long getDeviceId() { - return deviceId; - } - - public void setDeviceId(Long deviceId) { - this.deviceId = deviceId; - } - - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/DeviceJob.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/DeviceJob.java deleted file mode 100644 index fad8af4a..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/DeviceJob.java +++ /dev/null @@ -1,276 +0,0 @@ -package com.ruoyi.iot.domain; - -import com.fasterxml.jackson.annotation.JsonFormat; -import com.ruoyi.common.annotation.Excel; -import com.ruoyi.common.annotation.Excel.ColumnType; -import com.ruoyi.common.constant.ScheduleConstants; -import com.ruoyi.common.core.domain.BaseEntity; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.quartz.util.CronUtils; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Size; -import java.util.Date; - -/** - * 设备定时任务 - * - * @author kerwincui - */ -public class DeviceJob extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 任务ID */ - @Excel(name = "任务序号", cellType = ColumnType.NUMERIC) - private Long jobId; - - /** 任务名称 */ - @Excel(name = "任务名称") - private String jobName; - - /** 设备编号 */ - @Excel(name = "设备编号") - private String serialNumber; - - /** 设备id */ - private Long deviceId; - - /** 设备名称 */ - private String deviceName; - - /** 执行动作 */ - private String actions; - - /** 任务组名 */ - @Excel(name = "任务组名") - private String jobGroup; - - /** cron执行表达式 */ - @Excel(name = "执行表达式 ") - private String cronExpression; - - /** cron计划策略 */ - @Excel(name = "计划策略 ", readConverterExp = "0=默认,1=立即触发执行,2=触发一次执行,3=不触发立即执行") - private String misfirePolicy = ScheduleConstants.MISFIRE_DEFAULT; - - /** 是否并发执行(0允许 1禁止) */ - @Excel(name = "并发执行", readConverterExp = "0=允许,1=禁止") - private String concurrent; - - /** 任务状态(0正常 1暂停) */ - @Excel(name = "任务状态", readConverterExp = "0=正常,1=暂停") - private String status; - - /** 是否详细corn表达式 */ - private Integer isAdvance; - - /** 定时类型(1=设备定时,2=设备告警,3=场景联动) */ - @Excel(name = "定时类型", readConverterExp = "1==设备定时,2=设备告警,3=场景联动") - private Integer jobType; - - /** 产品ID */ - @Excel(name = "产品ID") - private Long productId; - - /** 产品名称 */ - @Excel(name = "产品名称") - private String productName; - - /** 场景联动ID */ - @Excel(name = "场景联动ID") - private Long sceneId; - - /** 告警ID */ - @Excel(name = "告警ID") - private Long alertId; - - public static long getSerialVersionUID() { - return serialVersionUID; - } - - public String getSerialNumber() { - return serialNumber; - } - - public void setSerialNumber(String serialNumber) { - this.serialNumber = serialNumber; - } - - public Integer getIsAdvance() { - return isAdvance; - } - - public void setIsAdvance(Integer isAdvance) { - this.isAdvance = isAdvance; - } - - public Integer getJobType() { - return jobType; - } - - public void setJobType(Integer jobType) { - this.jobType = jobType; - } - - public Long getProductId() { - return productId; - } - - public void setProductId(Long productId) { - this.productId = productId; - } - - public String getProductName() { - return productName; - } - - public void setProductName(String productName) { - this.productName = productName; - } - - public Long getSceneId() { - return sceneId; - } - - public void setSceneId(Long sceneId) { - this.sceneId = sceneId; - } - - public Long getAlertId() { - return alertId; - } - - public void setAlertId(Long alertId) { - this.alertId = alertId; - } - - public Long getJobId() - { - return jobId; - } - - public void setJobId(Long jobId) - { - this.jobId = jobId; - } - - @NotBlank(message = "任务名称不能为空") - @Size(min = 0, max = 64, message = "任务名称不能超过64个字符") - public String getJobName() - { - return jobName; - } - - public void setJobName(String jobName) - { - this.jobName = jobName; - } - - public String getJobGroup() - { - return jobGroup; - } - - public void setJobGroup(String jobGroup) - { - this.jobGroup = jobGroup; - } - - public Long getDeviceId() { - return deviceId; - } - - public void setDeviceId(Long deviceId) { - this.deviceId = deviceId; - } - - public String getDeviceName() { - return deviceName; - } - - public void setDeviceName(String deviceName) { - this.deviceName = deviceName; - } - - public String getActions() { - return actions; - } - - public void setActions(String actions) { - this.actions = actions; - } - - @NotBlank(message = "Cron执行表达式不能为空") - @Size(min = 0, max = 255, message = "Cron执行表达式不能超过255个字符") - public String getCronExpression() - { - return cronExpression; - } - - public void setCronExpression(String cronExpression) - { - this.cronExpression = cronExpression; - } - - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - public Date getNextValidTime() - { - if (StringUtils.isNotEmpty(cronExpression)) - { - return CronUtils.getNextExecution(cronExpression); - } - return null; - } - - public String getMisfirePolicy() - { - return misfirePolicy; - } - - public void setMisfirePolicy(String misfirePolicy) - { - this.misfirePolicy = misfirePolicy; - } - - public String getConcurrent() - { - return concurrent; - } - - public void setConcurrent(String concurrent) - { - this.concurrent = concurrent; - } - - public String getStatus() - { - return status; - } - - public void setStatus(String status) - { - this.status = status; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("jobId", getJobId()) - .append("jobName", getJobName()) - .append("jobGroup", getJobGroup()) - .append("cronExpression", getCronExpression()) - .append("nextValidTime", getNextValidTime()) - .append("misfirePolicy", getMisfirePolicy()) - .append("concurrent", getConcurrent()) - .append("status", getStatus()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("remark", getRemark()) - .toString(); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/DeviceLog.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/DeviceLog.java deleted file mode 100644 index b079e105..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/DeviceLog.java +++ /dev/null @@ -1,242 +0,0 @@ -package com.ruoyi.iot.domain; - -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.common.annotation.Excel; -import com.ruoyi.common.core.domain.BaseEntity; - -import java.util.Date; - -/** - * 设备日志对象 iot_device_log - * - * @author kerwincui - * @date 2022-01-13 - */ -public class DeviceLog extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - @Excel(name = "时间戳") - private Date ts; - /** 设备日志ID */ - private Long logId; - - /** 类型(1=属性上报,2=事件上报,3=调用功能,4=设备升级,5=设备上线,6=设备离线) */ - @Excel(name = "类型", readConverterExp = "1==属性上报,2=事件上报,3=调用功能,4=设备升级,5=设备上线,6=设备离线") - private Integer logType; - - /** 日志值 */ - @Excel(name = "日志值") - private String logValue; - - /** 设备ID */ - @Excel(name = "设备ID") - private Long deviceId; - - /** 设备名称 */ - @Excel(name = "设备名称") - private String deviceName; - - /** 设备编号 */ - @Excel(name = "设备编号") - private String serialNumber; - - /** 标识符 */ - @Excel(name = "标识符") - private String identity; - - /** 是否监测数据(1=是,0=否) */ - @Excel(name = "是否监测数据", readConverterExp = "1=是,0=否") - private Integer isMonitor; - - /** 模式 */ - @Excel(name = "模式", readConverterExp = "1=影子模式,2=在线模式,3=其他") - private Integer mode; - - /** 用户ID */ - @Excel(name = "用户ID") - private Long userId; - - /** 用户昵称 */ - @Excel(name = "用户昵称") - private String userName; - - /** 租户ID */ - @Excel(name = "租户ID") - private Long tenantId; - - /** 租户名称 */ - @Excel(name = "租户名称") - private String tenantName; - - /** 查询用的开始时间 */ - private String beginTime; - - /** 查询用的结束时间 */ - private String endTime; - - /** 查询的总数 */ - private int total; - - public int getTotal() { - return total; - } - - public void setTotal(int total) { - this.total = total; - } - - public String getBeginTime() { - return beginTime; - } - - public void setBeginTime(String beginTime) { - this.beginTime = beginTime; - } - - public String getEndTime() { - return endTime; - } - - public void setEndTime(String endTime) { - this.endTime = endTime; - } - - public Integer getMode() { - return mode; - } - - public void setMode(Integer mode) { - this.mode = mode; - } - - public Long getUserId() { - return userId; - } - - public void setUserId(Long userId) { - this.userId = userId; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public Long getTenantId() { - return tenantId; - } - - public void setTenantId(Long tenantId) { - this.tenantId = tenantId; - } - - public String getTenantName() { - return tenantName; - } - - public void setTenantName(String tenantName) { - this.tenantName = tenantName; - } - - public Date getTs() { - return ts; - } - - public void setTs(Date ts) { - this.ts = ts; - } - - public String getSerialNumber() { - return serialNumber; - } - - public void setSerialNumber(String serialNumber) { - this.serialNumber = serialNumber; - } - - public void setLogId(Long logId) - { - this.logId = logId; - } - - public Long getLogId() - { - return logId; - } - - public void setLogType(Integer logType) - { - this.logType = logType; - } - - public Integer getLogType() - { - return logType; - } - public void setLogValue(String logValue) - { - this.logValue = logValue; - } - - public String getLogValue() - { - return logValue; - } - public void setDeviceId(Long deviceId) - { - this.deviceId = deviceId; - } - - public Long getDeviceId() - { - return deviceId; - } - public void setDeviceName(String deviceName) - { - this.deviceName = deviceName; - } - - public String getDeviceName() - { - return deviceName; - } - public void setIdentity(String identity) - { - this.identity = identity; - } - - public String getIdentity() - { - return identity; - } - public void setIsMonitor(Integer isMonitor) - { - this.isMonitor = isMonitor; - } - - public Integer getIsMonitor() - { - return isMonitor; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("logId", getLogId()) - .append("logType", getLogType()) - .append("logValue", getLogValue()) - .append("deviceId", getDeviceId()) - .append("deviceName", getDeviceName()) - .append("identity", getIdentity()) - .append("createBy", getCreateBy()) - .append("isMonitor", getIsMonitor()) - .append("createTime", getCreateTime()) - .append("remark", getRemark()) - .toString(); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/DeviceUser.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/DeviceUser.java deleted file mode 100644 index daf4987e..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/DeviceUser.java +++ /dev/null @@ -1,143 +0,0 @@ -package com.ruoyi.iot.domain; - -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.common.annotation.Excel; -import com.ruoyi.common.core.domain.BaseEntity; - -/** - * 设备用户对象 iot_device_user - * - * @author kerwincui - * @date 2021-12-16 - */ -public class DeviceUser extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 固件ID */ - private Long deviceId; - - /** 用户ID */ - private Long userId; - - /** 设备名称 */ - @Excel(name = "设备名称") - private String deviceName; - - /** 用户昵称 */ - @Excel(name = "用户昵称") - private String userName; - - /** 是否为设备所有者 */ - @Excel(name = "是否为设备所有者") - private Integer isOwner; - - /** 租户ID */ - private Long tenantId; - - /** 租户名称 */ - private String tenantName; - - /** 手机号码 */ - private String phonenumber; - - /** 删除标志(0代表存在 2代表删除) */ - private String delFlag; - - public String getPhonenumber() { - return phonenumber; - } - - public void setPhonenumber(String phonenumber) { - this.phonenumber = phonenumber; - } - - public Long getTenantId() { - return tenantId; - } - - public void setTenantId(Long tenantId) { - this.tenantId = tenantId; - } - - public String getTenantName() { - return tenantName; - } - - public void setTenantName(String tenantName) { - this.tenantName = tenantName; - } - - public void setDeviceId(Long deviceId) - { - this.deviceId = deviceId; - } - - public Long getDeviceId() - { - return deviceId; - } - public void setUserId(Long userId) - { - this.userId = userId; - } - - public Long getUserId() - { - return userId; - } - public void setDeviceName(String deviceName) - { - this.deviceName = deviceName; - } - - public String getDeviceName() - { - return deviceName; - } - public void setUserName(String userName) - { - this.userName = userName; - } - - public String getUserName() - { - return userName; - } - public void setIsOwner(Integer isOwner) - { - this.isOwner = isOwner; - } - - public Integer getIsOwner() - { - return isOwner; - } - public void setDelFlag(String delFlag) - { - this.delFlag = delFlag; - } - - public String getDelFlag() - { - return delFlag; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("deviceId", getDeviceId()) - .append("userId", getUserId()) - .append("deviceName", getDeviceName()) - .append("userName", getUserName()) - .append("isOwner", getIsOwner()) - .append("delFlag", getDelFlag()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("remark", getRemark()) - .toString(); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/Firmware.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/Firmware.java deleted file mode 100644 index e3fbb126..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/Firmware.java +++ /dev/null @@ -1,180 +0,0 @@ -package com.ruoyi.iot.domain; - -import java.math.BigDecimal; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.common.annotation.Excel; -import com.ruoyi.common.core.domain.BaseEntity; - -/** - * 产品固件对象 iot_firmware - * - * @author kerwincui - * @date 2021-12-16 - */ -public class Firmware extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 固件ID */ - private Long firmwareId; - - /** 固件名称 */ - @Excel(name = "固件名称") - private String firmwareName; - - /** 产品ID */ - @Excel(name = "产品ID") - private Long productId; - - /** 产品名称 */ - @Excel(name = "产品名称") - private String productName; - - /** 租户ID */ - @Excel(name = "租户ID") - private Long tenantId; - - /** 租户名称 */ - @Excel(name = "租户名称") - private String tenantName; - - /** 是否系统通用(0-否,1-是) */ - @Excel(name = "是否系统通用", readConverterExp = "0=-否,1-是") - private Integer isSys; - - /** 是否最新版(0-否,1-是) */ - @Excel(name = "是否系统通用", readConverterExp = "0=-否,1-是") - private Integer isLatest; - - /** 固件版本 */ - @Excel(name = "固件版本") - private BigDecimal version; - - /** 文件路径 */ - @Excel(name = "文件路径") - private String filePath; - - /** 删除标志(0代表存在 2代表删除) */ - private String delFlag; - - public Integer getIsLatest() { - return isLatest; - } - - public void setIsLatest(Integer isLatest) { - this.isLatest = isLatest; - } - - public void setFirmwareId(Long firmwareId) - { - this.firmwareId = firmwareId; - } - - public Long getFirmwareId() - { - return firmwareId; - } - public void setFirmwareName(String firmwareName) - { - this.firmwareName = firmwareName; - } - - public String getFirmwareName() - { - return firmwareName; - } - public void setProductId(Long productId) - { - this.productId = productId; - } - - public Long getProductId() - { - return productId; - } - public void setProductName(String productName) - { - this.productName = productName; - } - - public String getProductName() - { - return productName; - } - public void setTenantId(Long tenantId) - { - this.tenantId = tenantId; - } - - public Long getTenantId() - { - return tenantId; - } - public void setTenantName(String tenantName) - { - this.tenantName = tenantName; - } - - public String getTenantName() - { - return tenantName; - } - public void setIsSys(Integer isSys) - { - this.isSys = isSys; - } - - public Integer getIsSys() - { - return isSys; - } - public void setVersion(BigDecimal version) - { - this.version = version; - } - - public BigDecimal getVersion() - { - return version; - } - public void setFilePath(String filePath) - { - this.filePath = filePath; - } - - public String getFilePath() - { - return filePath; - } - public void setDelFlag(String delFlag) - { - this.delFlag = delFlag; - } - - public String getDelFlag() - { - return delFlag; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("firmwareId", getFirmwareId()) - .append("firmwareName", getFirmwareName()) - .append("productId", getProductId()) - .append("productName", getProductName()) - .append("tenantId", getTenantId()) - .append("tenantName", getTenantName()) - .append("isSys", getIsSys()) - .append("version", getVersion()) - .append("filePath", getFilePath()) - .append("delFlag", getDelFlag()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("remark", getRemark()) - .toString(); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/Group.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/Group.java deleted file mode 100644 index 31045953..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/Group.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.ruoyi.iot.domain; - -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.common.annotation.Excel; -import com.ruoyi.common.core.domain.BaseEntity; - -/** - * 设备分组对象 iot_group - * - * @author kerwincui - * @date 2021-12-16 - */ -public class Group extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 分组ID */ - private Long groupId; - - /** 分组名称 */ - @Excel(name = "分组名称") - private String groupName; - - /** 分组排序 */ - @Excel(name = "分组排序") - private Long groupOrder; - - /** 用户ID */ - @Excel(name = "用户ID") - private Long userId; - - /** 用户昵称 */ - @Excel(name = "用户昵称") - private String userName; - - /** 删除标志(0代表存在 2代表删除) */ - private String delFlag; - - public void setGroupId(Long groupId) - { - this.groupId = groupId; - } - - public Long getGroupId() - { - return groupId; - } - public void setGroupName(String groupName) - { - this.groupName = groupName; - } - - public String getGroupName() - { - return groupName; - } - public void setGroupOrder(Long groupOrder) - { - this.groupOrder = groupOrder; - } - - public Long getGroupOrder() - { - return groupOrder; - } - public void setUserId(Long userId) - { - this.userId = userId; - } - - public Long getUserId() - { - return userId; - } - public void setUserName(String userName) - { - this.userName = userName; - } - - public String getUserName() - { - return userName; - } - public void setDelFlag(String delFlag) - { - this.delFlag = delFlag; - } - - public String getDelFlag() - { - return delFlag; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("groupId", getGroupId()) - .append("groupName", getGroupName()) - .append("groupOrder", getGroupOrder()) - .append("userId", getUserId()) - .append("userName", getUserName()) - .append("delFlag", getDelFlag()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("remark", getRemark()) - .toString(); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/News.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/News.java deleted file mode 100644 index a552988a..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/News.java +++ /dev/null @@ -1,181 +0,0 @@ -package com.ruoyi.iot.domain; - -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.common.annotation.Excel; -import com.ruoyi.common.core.domain.BaseEntity; - -/** - * 新闻资讯对象 news - * - * @author kerwincui - * @date 2022-04-09 - */ -public class News extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 新闻ID */ - private Long newsId; - - /** 标题 */ - @Excel(name = "标题") - private String title; - - /** 内容 */ - @Excel(name = "内容") - private String content; - - /** 图片 */ - @Excel(name = "图片") - private String imgUrl; - - /** 置顶 */ - @Excel(name = "置顶") - private Integer isTop; - - /** 广告 */ - @Excel(name = "广告") - private Integer isBanner; - - /** 分类ID */ - @Excel(name = "分类ID") - private Long categoryId; - - /** 分类名称 */ - @Excel(name = "分类名称") - private String categoryName; - - /** 发布 */ - @Excel(name = "发布") - private Integer status; - - /** 作者 */ - @Excel(name = "作者") - private String author; - - /** 删除标志(0代表存在 2代表删除) */ - private String delFlag; - - public void setNewsId(Long newsId) - { - this.newsId = newsId; - } - - public Long getNewsId() - { - return newsId; - } - public void setTitle(String title) - { - this.title = title; - } - - public String getTitle() - { - return title; - } - public void setContent(String content) - { - this.content = content; - } - - public String getContent() - { - return content; - } - public void setImgUrl(String imgUrl) - { - this.imgUrl = imgUrl; - } - - public String getImgUrl() - { - return imgUrl; - } - public void setIsTop(Integer isTop) - { - this.isTop = isTop; - } - - public Integer getIsTop() - { - return isTop; - } - public void setIsBanner(Integer isBanner) - { - this.isBanner = isBanner; - } - - public Integer getIsBanner() - { - return isBanner; - } - public void setCategoryId(Long categoryId) - { - this.categoryId = categoryId; - } - - public Long getCategoryId() - { - return categoryId; - } - public void setCategoryName(String categoryName) - { - this.categoryName = categoryName; - } - - public String getCategoryName() - { - return categoryName; - } - public void setStatus(Integer status) - { - this.status = status; - } - - public Integer getStatus() - { - return status; - } - public void setAuthor(String author) - { - this.author = author; - } - - public String getAuthor() - { - return author; - } - public void setDelFlag(String delFlag) - { - this.delFlag = delFlag; - } - - public String getDelFlag() - { - return delFlag; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("newsId", getNewsId()) - .append("title", getTitle()) - .append("content", getContent()) - .append("imgUrl", getImgUrl()) - .append("isTop", getIsTop()) - .append("isBanner", getIsBanner()) - .append("categoryId", getCategoryId()) - .append("categoryName", getCategoryName()) - .append("status", getStatus()) - .append("author", getAuthor()) - .append("delFlag", getDelFlag()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("remark", getRemark()) - .toString(); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/NewsCategory.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/NewsCategory.java deleted file mode 100644 index b50ff04a..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/NewsCategory.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.ruoyi.iot.domain; - -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.common.annotation.Excel; -import com.ruoyi.common.core.domain.BaseEntity; - -/** - * 新闻分类对象 news_category - * - * @author kerwincui - * @date 2022-04-09 - */ -public class NewsCategory extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 分类ID */ - @Excel(name = "分类ID") - private Long categoryId; - - /** 分类名字 */ - @Excel(name = "分类名字") - private String categoryName; - - /** 显示顺序 */ - @Excel(name = "显示顺序") - private Integer orderNum; - - /** 删除标志(0代表存在 2代表删除) */ - private String delFlag; - - public void setCategoryId(Long categoryId) - { - this.categoryId = categoryId; - } - - public Long getCategoryId() - { - return categoryId; - } - public void setCategoryName(String categoryName) - { - this.categoryName = categoryName; - } - - public String getCategoryName() - { - return categoryName; - } - public void setOrderNum(Integer orderNum) - { - this.orderNum = orderNum; - } - - public Integer getOrderNum() - { - return orderNum; - } - public void setDelFlag(String delFlag) - { - this.delFlag = delFlag; - } - - public String getDelFlag() - { - return delFlag; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("categoryId", getCategoryId()) - .append("categoryName", getCategoryName()) - .append("orderNum", getOrderNum()) - .append("delFlag", getDelFlag()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("remark", getRemark()) - .toString(); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/OauthClientDetails.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/OauthClientDetails.java deleted file mode 100644 index f0abe17e..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/OauthClientDetails.java +++ /dev/null @@ -1,191 +0,0 @@ -package com.ruoyi.iot.domain; - -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.common.annotation.Excel; -import com.ruoyi.common.core.domain.BaseEntity; - -/** - * 云云对接对象 oauth_client_details - * - * @author kerwincui - * @date 2022-02-07 - */ -public class OauthClientDetails extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 客户端ID */ - @Excel(name = "客户端ID") - private String clientId; - - /** 资源 */ - @Excel(name = "资源") - private String resourceIds; - - /** 客户端秘钥 */ - private String clientSecret; - - /** 权限范围 */ - @Excel(name = "权限范围") - private String scope; - - /** 授权模式 */ - @Excel(name = "授权模式") - private String authorizedGrantTypes; - - /** 回调地址 */ - @Excel(name = "回调地址") - private String webServerRedirectUri; - - /** 权限 */ - @Excel(name = "权限") - private String authorities; - - /** access token有效时间 */ - @Excel(name = "access token有效时间") - private Long accessTokenValidity; - - /** refresh token有效时间 */ - @Excel(name = "refresh token有效时间") - private Long refreshTokenValidity; - - /** 预留的字段 */ - @Excel(name = "预留的字段") - private String additionalInformation; - - /** 自动授权 */ - @Excel(name = "自动授权") - private String autoapprove; - - /** 平台 */ - @Excel(name = "平台") - private Integer type; - - public void setClientId(String clientId) - { - this.clientId = clientId; - } - - public String getClientId() - { - return clientId; - } - public void setResourceIds(String resourceIds) - { - this.resourceIds = resourceIds; - } - - public String getResourceIds() - { - return resourceIds; - } - public void setClientSecret(String clientSecret) - { - this.clientSecret = clientSecret; - } - - public String getClientSecret() - { - return clientSecret; - } - public void setScope(String scope) - { - this.scope = scope; - } - - public String getScope() - { - return scope; - } - public void setAuthorizedGrantTypes(String authorizedGrantTypes) - { - this.authorizedGrantTypes = authorizedGrantTypes; - } - - public String getAuthorizedGrantTypes() - { - return authorizedGrantTypes; - } - public void setWebServerRedirectUri(String webServerRedirectUri) - { - this.webServerRedirectUri = webServerRedirectUri; - } - - public String getWebServerRedirectUri() - { - return webServerRedirectUri; - } - public void setAuthorities(String authorities) - { - this.authorities = authorities; - } - - public String getAuthorities() - { - return authorities; - } - public void setAccessTokenValidity(Long accessTokenValidity) - { - this.accessTokenValidity = accessTokenValidity; - } - - public Long getAccessTokenValidity() - { - return accessTokenValidity; - } - public void setRefreshTokenValidity(Long refreshTokenValidity) - { - this.refreshTokenValidity = refreshTokenValidity; - } - - public Long getRefreshTokenValidity() - { - return refreshTokenValidity; - } - public void setAdditionalInformation(String additionalInformation) - { - this.additionalInformation = additionalInformation; - } - - public String getAdditionalInformation() - { - return additionalInformation; - } - public void setAutoapprove(String autoapprove) - { - this.autoapprove = autoapprove; - } - - public String getAutoapprove() - { - return autoapprove; - } - public void setType(Integer type) - { - this.type = type; - } - - public Integer getType() - { - return type; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("clientId", getClientId()) - .append("resourceIds", getResourceIds()) - .append("clientSecret", getClientSecret()) - .append("scope", getScope()) - .append("authorizedGrantTypes", getAuthorizedGrantTypes()) - .append("webServerRedirectUri", getWebServerRedirectUri()) - .append("authorities", getAuthorities()) - .append("accessTokenValidity", getAccessTokenValidity()) - .append("refreshTokenValidity", getRefreshTokenValidity()) - .append("additionalInformation", getAdditionalInformation()) - .append("autoapprove", getAutoapprove()) - .append("type", getType()) - .toString(); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/Product.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/Product.java deleted file mode 100644 index 7a319b5b..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/Product.java +++ /dev/null @@ -1,261 +0,0 @@ -package com.ruoyi.iot.domain; - -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.common.annotation.Excel; -import com.ruoyi.common.core.domain.BaseEntity; - -/** - * 产品对象 iot_product - * - * @author kerwincui - * @date 2021-12-16 - */ -public class Product extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 产品ID */ - private Long productId; - - /** 产品名称 */ - @Excel(name = "产品名称") - private String productName; - - /** 产品分类ID */ - @Excel(name = "产品分类ID") - private Long categoryId; - - /** 产品分类名称 */ - @Excel(name = "产品分类名称") - private String categoryName; - - /** 租户ID */ - @Excel(name = "租户ID") - private Long tenantId; - - /** 租户名称 */ - @Excel(name = "租户名称") - private String tenantName; - - /** 是否系统通用(0-否,1-是) */ - @Excel(name = "是否系统通用", readConverterExp = "0=-否,1-是") - private Integer isSys; - - /** 是否启用授权码(0-否,1-是) */ - @Excel(name = "是否启用授权码", readConverterExp = "0=-否,1-是") - private Integer isAuthorize; - - /** mqtt账号 */ - private String mqttAccount; - - /** mqtt密码 */ - private String mqttPassword; - - /** 产品秘钥 */ - private String mqttSecret; - - public String getMqttSecret() { - return mqttSecret; - } - - public void setMqttSecret(String mqttSecret) { - this.mqttSecret = mqttSecret; - } - - /** 状态(1-未发布,2-已发布,不能修改) */ - @Excel(name = "状态", readConverterExp = "1==未发布,2=已发布,不能修改") - private Integer status; - - /** 设备类型(1-直连设备、2-网关子设备、3-网关设备) */ - @Excel(name = "设备类型", readConverterExp = "1=直连设备、2=网关子设备、3=网关设备") - private Integer deviceType; - - /** 联网方式(1=-wifi、2-蜂窝(2G/3G/4G/5G)、3-以太网、4-其他) */ - @Excel(name = "联网方式", readConverterExp = "1=-wifi、2=蜂窝(2G/3G/4G/5G)、3=以太网、4=其他") - private Integer networkMethod; - - /** 认证方式(1-账号密码、2-证书、3-Http) */ - @Excel(name = "认证方式", readConverterExp = "1=账号密码、2=证书、3=Http") - private Integer vertificateMethod; - - /** 图片地址 */ - private String imgUrl; - - /** 删除标志(0代表存在 2代表删除) */ - private String delFlag; - - /** 物模型Json **/ - private String thingsModelsJson; - - public String getThingsModelsJson() { - return thingsModelsJson; - } - - public void setThingsModelsJson(String thingsModelsJson) { - this.thingsModelsJson = thingsModelsJson; - } - - public String getImgUrl() { - return imgUrl; - } - - public void setImgUrl(String imgUrl) { - this.imgUrl = imgUrl; - } - - public void setProductId(Long productId) - { - this.productId = productId; - } - - public Long getProductId() - { - return productId; - } - public void setProductName(String productName) - { - this.productName = productName; - } - - public String getProductName() - { - return productName; - } - public void setCategoryId(Long categoryId) - { - this.categoryId = categoryId; - } - - public Long getCategoryId() - { - return categoryId; - } - public void setCategoryName(String categoryName) - { - this.categoryName = categoryName; - } - - public String getCategoryName() - { - return categoryName; - } - public void setTenantId(Long tenantId) - { - this.tenantId = tenantId; - } - - public Long getTenantId() - { - return tenantId; - } - - public void setTenantName(String tenantName) - { - this.tenantName = tenantName; - } - public String getTenantName() - { - return tenantName; - } - - public void setIsSys(Integer isSys) - { - this.isSys = isSys; - } - public Integer getIsSys() - { - return isSys; - } - - public void setIsAuthorize(Integer isAuthorize) {this.isAuthorize = isAuthorize;} - public Integer getIsAuthorize() {return isAuthorize;} - - public void setMqttAccount(String mqttAccount) - { - this.mqttAccount = mqttAccount; - } - public String getMqttAccount() - { - return mqttAccount; - } - - public void setMqttPassword(String mqttPassword) - { - this.mqttPassword = mqttPassword; - } - public String getMqttPassword() - { - return mqttPassword; - } - - public void setStatus(Integer status) - { - this.status = status; - } - - public Integer getStatus() - { - return status; - } - public void setDeviceType(Integer deviceType) - { - this.deviceType = deviceType; - } - - public Integer getDeviceType() - { - return deviceType; - } - public void setNetworkMethod(Integer networkMethod) - { - this.networkMethod = networkMethod; - } - - public Integer getNetworkMethod() - { - return networkMethod; - } - public void setVertificateMethod(Integer vertificateMethod) - { - this.vertificateMethod = vertificateMethod; - } - - public Integer getVertificateMethod() - { - return vertificateMethod; - } - public void setDelFlag(String delFlag) - { - this.delFlag = delFlag; - } - - public String getDelFlag() - { - return delFlag; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("productId", getProductId()) - .append("productName", getProductName()) - .append("categoryId", getCategoryId()) - .append("categoryName", getCategoryName()) - .append("tenantId", getTenantId()) - .append("tenantName", getTenantName()) - .append("isSys", getIsSys()) - .append("isAuthorize", getIsAuthorize()) - .append("status", getStatus()) - .append("deviceType", getDeviceType()) - .append("networkMethod", getNetworkMethod()) - .append("vertificateMethod", getVertificateMethod()) - .append("delFlag", getDelFlag()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("remark", getRemark()) - .toString(); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/ProductAuthorize.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/ProductAuthorize.java deleted file mode 100644 index 613473fe..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/ProductAuthorize.java +++ /dev/null @@ -1,159 +0,0 @@ -package com.ruoyi.iot.domain; - -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.common.annotation.Excel; -import com.ruoyi.common.core.domain.BaseEntity; - -/** - * 产品授权码对象 iot_product_authorize - * - * @author kami - * @date 2022-04-11 - */ -public class ProductAuthorize extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 授权码ID */ - private Long authorizeId; - - /** 授权码 */ - @Excel(name = "授权码") - private String authorizeCode; - - /** 产品ID */ - @Excel(name = "产品ID") - private Long productId; - - /** 设备ID */ - @Excel(name = "设备ID") - private Long deviceId; - - /** 设备编号 */ - @Excel(name = "设备编号") - private String serialNumber; - - /** 用户ID */ - @Excel(name = "用户ID") - private Long userId; - - /** 用户名称 */ - @Excel(name = "用户名称") - private String userName; - - /** 状态(1-未发布,2-已发布,不能修改) */ - @Excel(name = "状态", readConverterExp = "1=未使用,2=已使用") - private Integer status; - - /** 删除标志(0代表存在 2代表删除) */ - private String delFlag; - - public ProductAuthorize() { - } - - public ProductAuthorize(String authorizeCode, Long productId) { - this.authorizeCode = authorizeCode; - this.productId = productId; - } - - public void setStatus(Integer status) - { - this.status = status; - } - public Integer getStatus() - { - return status; - } - public void setAuthorizeId(Long authorizeId) - { - this.authorizeId = authorizeId; - } - - public Long getAuthorizeId() - { - return authorizeId; - } - public void setAuthorizeCode(String authorizeCode) - { - this.authorizeCode = authorizeCode; - } - - public String getAuthorizeCode() - { - return authorizeCode; - } - public void setProductId(Long productId) - { - this.productId = productId; - } - - public Long getProductId() - { - return productId; - } - public void setDeviceId(Long deviceId) - { - this.deviceId = deviceId; - } - - public Long getDeviceId() - { - return deviceId; - } - public void setSerialNumber(String serialNumber) - { - this.serialNumber = serialNumber; - } - - public String getSerialNumber() - { - return serialNumber; - } - public void setUserId(Long userId) - { - this.userId = userId; - } - - public Long getUserId() - { - return userId; - } - public void setUserName(String userName) - { - this.userName = userName; - } - - public String getUserName() - { - return userName; - } - public void setDelFlag(String delFlag) - { - this.delFlag = delFlag; - } - - public String getDelFlag() - { - return delFlag; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("authorizeId", getAuthorizeId()) - .append("authorizeCode", getAuthorizeCode()) - .append("productId", getProductId()) - .append("deviceId", getDeviceId()) - .append("serialNumber", getSerialNumber()) - .append("userId", getUserId()) - .append("userName", getUserName()) - .append("delFlag", getDelFlag()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("remark", getRemark()) - .toString(); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/Scene.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/Scene.java deleted file mode 100644 index 9ef55d18..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/Scene.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.ruoyi.iot.domain; - -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.common.annotation.Excel; -import com.ruoyi.common.core.domain.BaseEntity; - -/** - * 场景联动对象 iot_scene - * - * @author kerwincui - * @date 2022-01-13 - */ -public class Scene extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 场景ID */ - private Long sceneId; - - /** 场景名称 */ - @Excel(name = "场景名称") - private String sceneName; - - /** 用户ID */ - @Excel(name = "用户ID") - private Long userId; - - /** 用户名称 */ - @Excel(name = "用户名称") - private String userName; - - /** 触发器 */ - @Excel(name = "触发器") - private String triggers; - - /** 执行动作 */ - @Excel(name = "执行动作") - private String actions; - - public void setSceneId(Long sceneId) - { - this.sceneId = sceneId; - } - - public Long getSceneId() - { - return sceneId; - } - public void setSceneName(String sceneName) - { - this.sceneName = sceneName; - } - - public String getSceneName() - { - return sceneName; - } - public void setUserId(Long userId) - { - this.userId = userId; - } - - public Long getUserId() - { - return userId; - } - public void setUserName(String userName) - { - this.userName = userName; - } - - public String getUserName() - { - return userName; - } - public void setTriggers(String triggers) - { - this.triggers = triggers; - } - - public String getTriggers() - { - return triggers; - } - public void setActions(String actions) - { - this.actions = actions; - } - - public String getActions() - { - return actions; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("sceneId", getSceneId()) - .append("sceneName", getSceneName()) - .append("userId", getUserId()) - .append("userName", getUserName()) - .append("triggers", getTriggers()) - .append("actions", getActions()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("remark", getRemark()) - .toString(); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/SocialPlatform.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/SocialPlatform.java deleted file mode 100644 index 5bb9f0b5..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/SocialPlatform.java +++ /dev/null @@ -1,176 +0,0 @@ -package com.ruoyi.iot.domain; - -import com.ruoyi.common.annotation.Excel; -import com.ruoyi.common.core.domain.BaseEntity; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; - -/** - * 第三方登录平台控制对象 iot_social_platform - * - * @author kerwincui - * @date 2022-04-11 - */ -public class SocialPlatform extends BaseEntity { - private static final long serialVersionUID = 1L; - - /** - * 第三方登录平台主键 - */ - private Long socialPlatformId; - - /** - * 第三方登录平台 - */ - @Excel(name = "第三方登录平台") - private String platform; - - /** - * 0、内部上线 1、上线 2、下线 - */ - @Excel(name = "0、内部上线 1、上线 2、下线") - private String status; - - /** - * 第三方平台申请Id - */ - @Excel(name = "第三方平台申请Id") - private String clientId; - - /** - * 第三方平台密钥 - */ - @Excel(name = "第三方平台密钥") - private String secretKey; - - /** - * 用户认证后跳转地址 - */ - @Excel(name = "用户认证后跳转地址") - private String redirectUri; - - /** - * 删除标记位(0代表存在,2代表删除) - */ - private String delFlag; - - /** - * 绑定注册登录uri - */ - @Excel(name = "绑定注册登录uri") - private String bindUri; - - /** - * 跳转登录uri - */ - @Excel(name = "跳转登录uri") - private String redirectLoginUri; - - /** - * 错误提示uri - */ - @Excel(name = "错误提示uri") - private String errorMsgUri; - - public Long getSocialPlatformId() { - return socialPlatformId; - } - - public void setSocialPlatformId(Long socialPlatformId) { - this.socialPlatformId = socialPlatformId; - } - - public String getPlatform() { - return platform; - } - - public void setPlatform(String platform) { - this.platform = platform; - } - - public String getStatus() { - return status; - } - - public void setStatus(String status) { - this.status = status; - } - - public String getClientId() { - return clientId; - } - - public void setClientId(String clientId) { - this.clientId = clientId; - } - - public String getSecretKey() { - return secretKey; - } - - public void setSecretKey(String secretKey) { - this.secretKey = secretKey; - } - - public String getRedirectUri() { - return redirectUri; - } - - public void setRedirectUri(String redirectUri) { - this.redirectUri = redirectUri; - } - - public String getDelFlag() { - return delFlag; - } - - public void setDelFlag(String delFlag) { - this.delFlag = delFlag; - } - - public String getBindUri() { - return bindUri; - } - - public void setBindUri(String bindUri) { - this.bindUri = bindUri; - } - - public String getRedirectLoginUri() { - return redirectLoginUri; - } - - public void setRedirectLoginUri(String redirectLoginUri) { - this.redirectLoginUri = redirectLoginUri; - } - - public String getErrorMsgUri() { - return errorMsgUri; - } - - public void setErrorMsgUri(String errorMsgUri) { - this.errorMsgUri = errorMsgUri; - } - - @Override - public String toString() { - return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) - .append("socialPlatformId", getSocialPlatformId()) - .append("platform", getPlatform()) - .append("status", getStatus()) - .append("clientId", getClientId()) - .append("secretKey", getSecretKey()) - .append("redirectUri", getRedirectUri()) - .append("delFlag", getDelFlag()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateTime", getUpdateTime()) - .append("updateBy", getUpdateBy()) - .append("remark", getRemark()) - .append("bindUri", getBindUri()) - .append("redirectLoginUri", getRedirectLoginUri()) - .append("errorMsgUri", getErrorMsgUri()) - .toString(); - } - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/SocialUser.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/SocialUser.java deleted file mode 100644 index f0680e9e..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/SocialUser.java +++ /dev/null @@ -1,376 +0,0 @@ -package com.ruoyi.iot.domain; - -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.common.annotation.Excel; -import com.ruoyi.common.core.domain.BaseEntity; - -/** - * 用户第三方用户信息对象 iot_social_user - * - * @author json - * @date 2022-04-18 - */ -public class SocialUser extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 第三方系统用户表主键 */ - private Long socialUserId; - - /** 第三方系统的唯一ID */ - @Excel(name = "第三方系统的唯一ID") - private String uuid; - - /** 第三方用户来源 */ - @Excel(name = "第三方用户来源") - private String source; - - /** 用户的授权令牌 */ - @Excel(name = "用户的授权令牌") - private String accessToken; - - /** 第三方用户的授权令牌的有效期(部分平台可能没有) */ - @Excel(name = "第三方用户的授权令牌的有效期", readConverterExp = "部=分平台可能没有") - private Long expireIn; - - /** 刷新令牌(部分平台可能没有) */ - @Excel(name = "刷新令牌(部分平台可能没有)") - private String refreshToken; - - /** 第三方用户的 open id(部分平台可能没有) */ - @Excel(name = "第三方用户的 open id", readConverterExp = "部=分平台可能没有") - private String openId; - - /** 第三方用户的 ID(部分平台可能没有) */ - @Excel(name = "第三方用户的 ID(部分平台可能没有)") - private String uid; - - /** 个别平台的授权信息(部分平台可能没有) */ - @Excel(name = "个别平台的授权信息", readConverterExp = "部=分平台可能没有") - private String accessCode; - - /** 第三方用户的 union id(部分平台可能没有) */ - @Excel(name = "第三方用户的 union id(部分平台可能没有)") - private String unionId; - - /** 第三方用户授予的权限(部分平台可能没有) */ - @Excel(name = "第三方用户授予的权限(部分平台可能没有)") - private String scope; - - /** 个别平台的授权信息(部分平台可能没有) */ - @Excel(name = "个别平台的授权信息", readConverterExp = "部=分平台可能没有") - private String tokenType; - - /** id token(部分平台可能没有) */ - @Excel(name = "id token", readConverterExp = "部=分平台可能没有") - private String idToken; - - /** 小米平台用户的附带属性(部分平台可能没有) */ - @Excel(name = "小米平台用户的附带属性", readConverterExp = "部=分平台可能没有") - private String macAlgorithm; - - /** 小米平台用户的附带属性(部分平台可能没有) */ - @Excel(name = "小米平台用户的附带属性(部分平台可能没有)") - private String macKey; - - /** 用户的授权code(部分平台可能没有) */ - @Excel(name = "用户的授权code", readConverterExp = "部=分平台可能没有") - private String code; - - /** Twitter平台用户的附带属性(部分平台可能没有) */ - @Excel(name = "Twitter平台用户的附带属性(部分平台可能没有)") - private String oauthToken; - - /** Twitter平台用户的附带属性(部分平台可能没有) */ - @Excel(name = "Twitter平台用户的附带属性(部分平台可能没有)") - private String oauthTokenSecret; - - /** 删除标记位(0代表存在,2代表删除) */ - private String delFlag; - - /** 绑定状态(0:未绑定,1:绑定) */ - @Excel(name = "绑定状态(0:未绑定,1:绑定)") - private String status; - - /** 用户ID */ - @Excel(name = "用户ID") - private Long sysUserId; - - /** 用户名 */ - @Excel(name = "用户名") - private String username; - - /** 用户昵称 */ - @Excel(name = "用户昵称") - private String nickname; - - /** 用户头像 */ - @Excel(name = "用户头像") - private String avatar; - - /** 用户性别 */ - @Excel(name = "用户性别") - private Integer gender; - - public void setSocialUserId(Long socialUserId) - { - this.socialUserId = socialUserId; - } - - public Long getSocialUserId() - { - return socialUserId; - } - public void setUuid(String uuid) - { - this.uuid = uuid; - } - - public String getUuid() - { - return uuid; - } - public void setSource(String source) - { - this.source = source; - } - - public String getSource() - { - return source; - } - public void setAccessToken(String accessToken) - { - this.accessToken = accessToken; - } - - public String getAccessToken() - { - return accessToken; - } - public void setExpireIn(Long expireIn) - { - this.expireIn = expireIn; - } - - public Long getExpireIn() - { - return expireIn; - } - public void setRefreshToken(String refreshToken) - { - this.refreshToken = refreshToken; - } - - public String getRefreshToken() - { - return refreshToken; - } - public void setOpenId(String openId) - { - this.openId = openId; - } - - public String getOpenId() - { - return openId; - } - public void setUid(String uid) - { - this.uid = uid; - } - - public String getUid() - { - return uid; - } - public void setAccessCode(String accessCode) - { - this.accessCode = accessCode; - } - - public String getAccessCode() - { - return accessCode; - } - public void setUnionId(String unionId) - { - this.unionId = unionId; - } - - public String getUnionId() - { - return unionId; - } - public void setScope(String scope) - { - this.scope = scope; - } - - public String getScope() - { - return scope; - } - public void setTokenType(String tokenType) - { - this.tokenType = tokenType; - } - - public String getTokenType() - { - return tokenType; - } - public void setIdToken(String idToken) - { - this.idToken = idToken; - } - - public String getIdToken() - { - return idToken; - } - public void setMacAlgorithm(String macAlgorithm) - { - this.macAlgorithm = macAlgorithm; - } - - public String getMacAlgorithm() - { - return macAlgorithm; - } - public void setMacKey(String macKey) - { - this.macKey = macKey; - } - - public String getMacKey() - { - return macKey; - } - public void setCode(String code) - { - this.code = code; - } - - public String getCode() - { - return code; - } - public void setOauthToken(String oauthToken) - { - this.oauthToken = oauthToken; - } - - public String getOauthToken() - { - return oauthToken; - } - public void setOauthTokenSecret(String oauthTokenSecret) - { - this.oauthTokenSecret = oauthTokenSecret; - } - - public String getOauthTokenSecret() - { - return oauthTokenSecret; - } - public void setDelFlag(String delFlag) - { - this.delFlag = delFlag; - } - - public String getDelFlag() - { - return delFlag; - } - public void setStatus(String status) - { - this.status = status; - } - - public String getStatus() - { - return status; - } - public void setSysUserId(Long sysUserId) - { - this.sysUserId = sysUserId; - } - - public Long getSysUserId() - { - return sysUserId; - } - public void setUsername(String username) - { - this.username = username; - } - - public String getUsername() - { - return username; - } - public void setNickname(String nickname) - { - this.nickname = nickname; - } - - public String getNickname() - { - return nickname; - } - public void setAvatar(String avatar) - { - this.avatar = avatar; - } - - public String getAvatar() - { - return avatar; - } - public void setGender(Integer gender) - { - this.gender = gender; - } - - public Integer getGender() - { - return gender; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("socialUserId", getSocialUserId()) - .append("uuid", getUuid()) - .append("source", getSource()) - .append("accessToken", getAccessToken()) - .append("expireIn", getExpireIn()) - .append("refreshToken", getRefreshToken()) - .append("openId", getOpenId()) - .append("uid", getUid()) - .append("accessCode", getAccessCode()) - .append("unionId", getUnionId()) - .append("scope", getScope()) - .append("tokenType", getTokenType()) - .append("idToken", getIdToken()) - .append("macAlgorithm", getMacAlgorithm()) - .append("macKey", getMacKey()) - .append("code", getCode()) - .append("oauthToken", getOauthToken()) - .append("oauthTokenSecret", getOauthTokenSecret()) - .append("createTime", getCreateTime()) - .append("createBy", getCreateBy()) - .append("updateTime", getUpdateTime()) - .append("updateBy", getUpdateBy()) - .append("delFlag", getDelFlag()) - .append("status", getStatus()) - .append("sysUserId", getSysUserId()) - .append("username", getUsername()) - .append("nickname", getNickname()) - .append("avatar", getAvatar()) - .append("gender", getGender()) - .toString(); - } -} \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/ThingsModel.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/ThingsModel.java deleted file mode 100644 index 0c02c8bb..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/ThingsModel.java +++ /dev/null @@ -1,196 +0,0 @@ -package com.ruoyi.iot.domain; - -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.common.annotation.Excel; -import com.ruoyi.common.core.domain.BaseEntity; - -/** - * 物模型对象 iot_things_model - * - * @author kerwincui - * @date 2021-12-16 - */ -public class ThingsModel extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 物模型ID */ - private Long modelId; - - /** 物模型名称 */ - @Excel(name = "物模型名称") - private String modelName; - - /** 产品ID */ - @Excel(name = "产品ID") - private Long productId; - - /** 产品名称 */ - @Excel(name = "产品名称") - private String productName; - - /** 租户ID */ - @Excel(name = "租户ID") - private Long tenantId; - - /** 租户名称 */ - @Excel(name = "租户名称") - private String tenantName; - - /** 标识符,产品下唯一 */ - @Excel(name = "标识符,产品下唯一") - private String identifier; - - /** 模型类别(1-属性,2-功能,3-事件) */ - @Excel(name = "模型类别", readConverterExp = "1=-属性,2-功能,3-事件,4-属性和功能") - private Integer type; - - /** 数据类型(integer、decimal、string、bool、array、enum) */ - @Excel(name = "数据类型", readConverterExp = "i=nteger、decimal、string、bool、array、enum") - private String datatype; - - /** 数据定义 */ - @Excel(name = "数据定义") - private String specs; - - /** 是否首页显示(0-否,1-是) */ - @Excel(name = "是否首页显示", readConverterExp = "0=-否,1-是") - private Integer isTop; - - /** 是否实时监测(0-否,1-是) */ - @Excel(name = "是否实时监测", readConverterExp = "0=-否,1-是") - private Integer isMonitor; - - public void setModelId(Long modelId) - { - this.modelId = modelId; - } - - public Long getModelId() - { - return modelId; - } - public void setModelName(String modelName) - { - this.modelName = modelName; - } - - public String getModelName() - { - return modelName; - } - public void setProductId(Long productId) - { - this.productId = productId; - } - - public Long getProductId() - { - return productId; - } - public void setProductName(String productName) - { - this.productName = productName; - } - - public String getProductName() - { - return productName; - } - public void setTenantId(Long tenantId) - { - this.tenantId = tenantId; - } - - public Long getTenantId() - { - return tenantId; - } - public void setTenantName(String tenantName) - { - this.tenantName = tenantName; - } - - public String getTenantName() - { - return tenantName; - } - public void setIdentifier(String identifier) - { - this.identifier = identifier; - } - - public String getIdentifier() - { - return identifier; - } - public void setType(Integer type) - { - this.type = type; - } - - public Integer getType() - { - return type; - } - public void setDatatype(String datatype) - { - this.datatype = datatype; - } - - public String getDatatype() - { - return datatype; - } - public void setSpecs(String specs) - { - this.specs = specs; - } - - public String getSpecs() - { - return specs; - } - public void setIsTop(Integer isTop) - { - this.isTop = isTop; - } - - public Integer getIsTop() - { - return isTop; - } - public void setIsMonitor(Integer isMonitor) - { - this.isMonitor = isMonitor; - } - - public Integer getIsMonitor() - { - return isMonitor; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("modelId", getModelId()) - .append("modelName", getModelName()) - .append("productId", getProductId()) - .append("productName", getProductName()) - .append("tenantId", getTenantId()) - .append("tenantName", getTenantName()) - .append("identifier", getIdentifier()) - .append("type", getType()) - .append("datatype", getDatatype()) - .append("specs", getSpecs()) - .append("isTop", getIsTop()) - .append("isMonitor", getIsMonitor()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("remark", getRemark()) - .toString(); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/ThingsModelTemplate.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/ThingsModelTemplate.java deleted file mode 100644 index 49ab9521..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/ThingsModelTemplate.java +++ /dev/null @@ -1,195 +0,0 @@ -package com.ruoyi.iot.domain; - -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import com.ruoyi.common.annotation.Excel; -import com.ruoyi.common.core.domain.BaseEntity; - -/** - * 通用物模型对象 iot_things_model_template - * - * @author kerwincui - * @date 2021-12-16 - */ -public class ThingsModelTemplate extends BaseEntity -{ - private static final long serialVersionUID = 1L; - - /** 物模型ID */ - private Long templateId; - - /** 物模型名称 */ - @Excel(name = "物模型名称") - private String templateName; - - /** 租户ID */ - @Excel(name = "租户ID") - private Long tenantId; - - /** 租户名称 */ - @Excel(name = "租户名称") - private String tenantName; - - /** 标识符,产品下唯一 */ - @Excel(name = "标识符") - private String identifier; - - /** 模型类别(1-属性,2-功能,3-事件) */ - @Excel(name = "模型类别", dictType = "iot_things_type") - private Integer type; - - /** 数据类型(integer、decimal、string、bool、array、enum) */ - @Excel(name = "数据类型") - private String datatype; - - /** 数据定义 */ - @Excel(name = "数据定义") - private String specs; - - /** 是否系统通用(0-否,1-是) */ - @Excel(name = "是否系统通用", dictType = "iot_yes_no") - private Integer isSys; - - /** 是否首页显示(0-否,1-是) */ - @Excel(name = "是否首页显示", dictType = "iot_yes_no") - private Integer isTop; - - /** 是否实时监测(0-否,1-是) */ - @Excel(name = "是否实时监测", dictType = "iot_yes_no") - private Integer isMonitor; - - /** 删除标志(0代表存在 2代表删除) */ - private String delFlag; - - public void setTemplateId(Long templateId) - { - this.templateId = templateId; - } - - public Long getTemplateId() - { - return templateId; - } - public void setTemplateName(String templateName) - { - this.templateName = templateName; - } - - public String getTemplateName() - { - return templateName; - } - public void setTenantId(Long tenantId) - { - this.tenantId = tenantId; - } - - public Long getTenantId() - { - return tenantId; - } - public void setTenantName(String tenantName) - { - this.tenantName = tenantName; - } - - public String getTenantName() - { - return tenantName; - } - public void setIdentifier(String identifier) - { - this.identifier = identifier; - } - - public String getIdentifier() - { - return identifier; - } - public void setType(Integer type) - { - this.type = type; - } - - public Integer getType() - { - return type; - } - public void setDatatype(String datatype) - { - this.datatype = datatype; - } - - public String getDatatype() - { - return datatype; - } - public void setSpecs(String specs) - { - this.specs = specs; - } - - public String getSpecs() - { - return specs; - } - public void setIsSys(Integer isSys) - { - this.isSys = isSys; - } - - public Integer getIsSys() - { - return isSys; - } - public void setIsTop(Integer isTop) - { - this.isTop = isTop; - } - - public Integer getIsTop() - { - return isTop; - } - public void setIsMonitor(Integer isMonitor) - { - this.isMonitor = isMonitor; - } - - public Integer getIsMonitor() - { - return isMonitor; - } - public void setDelFlag(String delFlag) - { - this.delFlag = delFlag; - } - - public String getDelFlag() - { - return delFlag; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("templateId", getTemplateId()) - .append("templateName", getTemplateName()) - .append("tenantId", getTenantId()) - .append("tenantName", getTenantName()) - .append("identifier", getIdentifier()) - .append("type", getType()) - .append("datatype", getDatatype()) - .append("specs", getSpecs()) - .append("isSys", getIsSys()) - .append("isTop", getIsTop()) - .append("isMonitor", getIsMonitor()) - .append("delFlag", getDelFlag()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("remark", getRemark()) - .toString(); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/UserSocialProfile.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/UserSocialProfile.java deleted file mode 100644 index 081eec3b..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/UserSocialProfile.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.ruoyi.iot.domain; - -import com.ruoyi.common.annotation.Excel; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; - -public class UserSocialProfile { - /** - * 第三方系统用户表主键 - */ - private Long socialUserId; - - /** - * 第三方用户来源 - */ - @Excel(name = "第三方用户来源") - private String source; - - /** - * 用户名 - */ - @Excel(name = "用户名") - private String username; - - /** - * 用户昵称 - */ - @Excel(name = "用户昵称") - private String nickname; - - /** - * 用户头像 - */ - @Excel(name = "用户头像") - private String avatar; - - /** - * 绑定状态(0:未绑定,1:绑定) - */ - @Excel(name = "绑定状态(0:未绑定,1:绑定)") - private String status; - - public Long getSocialUserId() { - return socialUserId; - } - - public void setSocialUserId(Long socialUserId) { - this.socialUserId = socialUserId; - } - - public String getSource() { - return source; - } - - public void setSource(String source) { - this.source = source; - } - - public String getStatus() { - return status; - } - - public void setStatus(String status) { - this.status = status; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getNickname() { - return nickname; - } - - public void setNickname(String nickname) { - this.nickname = nickname; - } - - public String getAvatar() { - return avatar; - } - - public void setAvatar(String avatar) { - this.avatar = avatar; - } - - @Override - public String toString() { - return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) - .append("socialUserId", getSocialUserId()) - .append("source", getSource()) - .append("status", getStatus()) - .append("username", getUsername()) - .append("nickname", getNickname()) - .append("avatar", getAvatar()) - .toString(); - } - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/AlertLogMapper.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/AlertLogMapper.java deleted file mode 100644 index 72ceaf00..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/AlertLogMapper.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.ruoyi.iot.mapper; - -import com.ruoyi.iot.domain.AlertLog; -import org.springframework.stereotype.Repository; - -import java.util.List; - -/** - * 设备告警Mapper接口 - * - * @author kerwincui - * @date 2022-01-13 - */ -@Repository -public interface AlertLogMapper -{ - /** - * 查询设备告警 - * - * @param alertLogId 设备告警主键 - * @return 设备告警 - */ - public AlertLog selectAlertLogByAlertLogId(Long alertLogId); - - /** - * 查询设备告警列表 - * - * @param alertLog 设备告警 - * @return 设备告警集合 - */ - public List selectAlertLogList(AlertLog alertLog); - - /** - * 新增设备告警 - * - * @param alertLog 设备告警 - * @return 结果 - */ - public int insertAlertLog(AlertLog alertLog); - - /** - * 修改设备告警 - * - * @param alertLog 设备告警 - * @return 结果 - */ - public int updateAlertLog(AlertLog alertLog); - - /** - * 删除设备告警 - * - * @param alertLogId 设备告警主键 - * @return 结果 - */ - public int deleteAlertLogByAlertLogId(Long alertLogId); - - /** - * 批量删除设备告警 - * - * @param alertLogIds 需要删除的数据主键集合 - * @return 结果 - */ - public int deleteAlertLogByAlertLogIds(Long[] alertLogIds); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/AlertMapper.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/AlertMapper.java deleted file mode 100644 index a4f48c7f..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/AlertMapper.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.ruoyi.iot.mapper; - -import java.util.List; -import com.ruoyi.iot.domain.Alert; -import org.springframework.stereotype.Repository; - -/** - * 设备告警Mapper接口 - * - * @author kerwincui - * @date 2022-01-13 - */ -@Repository -public interface AlertMapper -{ - /** - * 查询设备告警 - * - * @param alertId 设备告警主键 - * @return 设备告警 - */ - public Alert selectAlertByAlertId(Long alertId); - - /** - * 查询设备告警列表 - * - * @param alert 设备告警 - * @return 设备告警集合 - */ - public List selectAlertList(Alert alert); - - /** - * 新增设备告警 - * - * @param alert 设备告警 - * @return 结果 - */ - public int insertAlert(Alert alert); - - /** - * 修改设备告警 - * - * @param alert 设备告警 - * @return 结果 - */ - public int updateAlert(Alert alert); - - /** - * 删除设备告警 - * - * @param alertId 设备告警主键 - * @return 结果 - */ - public int deleteAlertByAlertId(Long alertId); - - /** - * 批量删除设备告警 - * - * @param alertIds 需要删除的数据主键集合 - * @return 结果 - */ - public int deleteAlertByAlertIds(Long[] alertIds); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/CategoryMapper.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/CategoryMapper.java deleted file mode 100644 index 3c9ee4ad..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/CategoryMapper.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.ruoyi.iot.mapper; - -import com.ruoyi.iot.domain.Category; -import com.ruoyi.iot.model.IdAndName; -import org.springframework.stereotype.Repository; - -import java.util.List; - -/** - * 产品分类Mapper接口 - * - * @author kerwincui - * @date 2021-12-16 - */ -@Repository -public interface CategoryMapper -{ - /** - * 查询产品分类 - * - * @param categoryId 产品分类主键 - * @return 产品分类 - */ - public Category selectCategoryByCategoryId(Long categoryId); - - /** - * 查询产品分类列表 - * - * @param category 产品分类 - * @return 产品分类集合 - */ - public List selectCategoryList(Category category); - - /** - * 查询产品简短分类列表 - * - * @return 产品分类集合 - */ - public List selectCategoryShortList(Category category); - - /** - * 新增产品分类 - * - * @param category 产品分类 - * @return 结果 - */ - public int insertCategory(Category category); - - /** - * 修改产品分类 - * - * @param category 产品分类 - * @return 结果 - */ - public int updateCategory(Category category); - - /** - * 删除产品分类 - * - * @param categoryId 产品分类主键 - * @return 结果 - */ - public int deleteCategoryByCategoryId(Long categoryId); - - /** - * 批量删除产品分类 - * - * @param categoryIds 需要删除的数据主键集合 - * @return 结果 - */ - public int deleteCategoryByCategoryIds(Long[] categoryIds); - - /** - * 分类下的产品数量 - * - * @param categoryIds 需要删除的数据主键集合 - * @return 结果 - */ - public int productCountInCategorys(Long[] categoryIds); - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/DeviceJobMapper.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/DeviceJobMapper.java deleted file mode 100644 index 3e9da07a..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/DeviceJobMapper.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.ruoyi.iot.mapper; - -import com.ruoyi.iot.domain.DeviceJob; -import org.springframework.stereotype.Repository; - -import java.util.List; - -/** - * 调度任务信息 数据层 - * - * @author kerwincui - */ -@Repository -public interface DeviceJobMapper -{ - /** - * 查询调度任务日志集合 - * - * @param job 调度信息 - * @return 操作日志集合 - */ - public List selectJobList(DeviceJob job); - - /** - * 根据设备Ids查询调度任务日志集合 - * - * @param deviceIds 设备ID数组 - * @return 操作日志集合 - */ - public List selectShortJobListByDeviceIds(Long[] deviceIds); - - /** - * 查询所有调度任务 - * - * @return 调度任务列表 - */ - public List selectJobAll(); - - /** - * 通过调度ID查询调度任务信息 - * - * @param jobId 调度ID - * @return 角色对象信息 - */ - public DeviceJob selectJobById(Long jobId); - - /** - * 通过调度ID删除调度任务信息 - * - * @param jobId 调度ID - * @return 结果 - */ - public int deleteJobById(Long jobId); - - /** - * 批量删除调度任务信息 - * - * @param ids 需要删除的数据ID - * @return 结果 - */ - public int deleteJobByIds(Long[] ids); - - /** - * 根据设备Ids批量删除调度任务信息 - * - * @param deviceIds 需要删除的数据ID - * @return 结果 - */ - public int deleteJobByDeviceIds(Long[] deviceIds); - - /** - * 修改调度任务信息 - * - * @param job 调度任务信息 - * @return 结果 - */ - public int updateJob(DeviceJob job); - - /** - * 新增调度任务信息 - * - * @param job 调度任务信息 - * @return 结果 - */ - public int insertJob(DeviceJob job); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/DeviceLogMapper.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/DeviceLogMapper.java deleted file mode 100644 index 06a44482..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/DeviceLogMapper.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.ruoyi.iot.mapper; - -import com.ruoyi.iot.domain.Device; -import com.ruoyi.iot.domain.DeviceLog; -import com.ruoyi.iot.model.DeviceStatistic; -import com.ruoyi.iot.model.MonitorModel; -import org.springframework.stereotype.Repository; - -import java.util.Date; -import java.util.List; - -/** - * 设备日志Mapper接口 - * - * @author kerwincui - * @date 2022-01-13 - */ -@Repository -public interface DeviceLogMapper -{ - /** - * 查询设备日志 - * - * @param logId 设备日志主键 - * @return 设备日志 - */ - public DeviceLog selectDeviceLogByLogId(Long logId); - - /** - * 查询日志分类总数 - * - * @return 设备日志 - */ - public DeviceStatistic selectCategoryLogCount(Device device); - - /** - * 查询设备日志列表 - * - * @param deviceLog 设备日志 - * @return 设备日志集合 - */ - public List selectDeviceLogList(DeviceLog deviceLog); - - /** - * 查询设备监测数据 - * - * @param deviceLog 设备日志 - * @return 设备日志集合 - */ - public List selectMonitorList(DeviceLog deviceLog); - - /** - * 新增设备日志 - * - * @param deviceLog 设备日志 - * @return 结果 - */ - public int insertDeviceLog(DeviceLog deviceLog); - - /** - * 修改设备日志 - * - * @param deviceLog 设备日志 - * @return 结果 - */ - public int updateDeviceLog(DeviceLog deviceLog); - - /** - * 删除设备日志 - * - * @param logId 设备日志主键 - * @return 结果 - */ - public int deleteDeviceLogByLogId(Long logId); - - /** - * 批量删除设备日志 - * - * @param logIds 需要删除的数据主键集合 - * @return 结果 - */ - public int deleteDeviceLogByLogIds(Long[] logIds); - - /** - * 根据设备Ids批量删除设备日志 - * - * @param deviceNumber 需要删除的数据设备Id - * @return 结果 - */ - public int deleteDeviceLogByDeviceNumber(String deviceNumber); - - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/DeviceMapper.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/DeviceMapper.java deleted file mode 100644 index 48f6632a..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/DeviceMapper.java +++ /dev/null @@ -1,200 +0,0 @@ -package com.ruoyi.iot.mapper; - -import com.ruoyi.iot.domain.Device; -import com.ruoyi.iot.model.*; -import com.ruoyi.iot.model.ThingsModels.ThingsModelValuesInput; -import com.ruoyi.iot.model.ThingsModels.ThingsModelValuesOutput; -import org.springframework.stereotype.Repository; - -import java.util.List; - -/** - * 设备Mapper接口 - * - * @author kerwincui - * @date 2021-12-16 - */ -@Repository -public interface DeviceMapper -{ - /** - * 查询设备 - * - * @param deviceId 设备主键 - * @return 设备 - */ - public Device selectDeviceByDeviceId(Long deviceId); - - /** - * 查询设备和产品总数 - * - * @return 设备 - */ - public DeviceStatistic selectDeviceProductAlertCount(Device device); - - /** - * 根据设备编号查询设备 - * - * @param serialNumber 设备主键 - * @return 设备 - */ - public Device selectDeviceBySerialNumber(String serialNumber); - - - /** - * 根据设备编号查询设备数量 - * - * @param serialNumber 设备主键 - * @return 设备 - */ - public int selectDeviceCountBySerialNumber(String serialNumber); - - /** - * 根据设备编号查询简介设备 - * - * @param serialNumber 设备主键 - * @return 设备 - */ - public Device selectShortDeviceBySerialNumber(String serialNumber); - - /** - * 根据设备编号查询设备认证信息 - * - * @param model 设备编号和产品ID - * @return 设备 - */ - public ProductAuthenticateModel selectProductAuthenticate(AuthenticateInputModel model); - - /** - * 查询设备和运行状态 - * - * @param deviceId 设备主键 - * @return 设备 - */ - public DeviceShortOutput selectDeviceRunningStatusByDeviceId(Long deviceId); - - /** - * 查询设备的物模型值 - * - * @param serialNumber 设备编号 - * @return 设备 - */ - public ThingsModelValuesOutput selectDeviceThingsModelValueBySerialNumber(String serialNumber); - - /** - * 修改设备的物模型值 - * - * @param input 设备ID和物模型值 - * @return 结果 - */ - public int updateDeviceThingsModelValue(ThingsModelValuesInput input); - - - /** - * 查询设备列表 - * - * @param device 设备 - * @return 设备集合 - */ - public List selectDeviceList(Device device); - - /** - * 查询未分配授权码设备列表 - * - * @param device 设备 - * @return 设备集合 - */ - public List selectUnAuthDeviceList(Device device); - - /** - * 查询分组可添加设备分页列表 - * - * @param device 设备 - * @return 设备集合 - */ - public List selectDeviceListByGroup(Device device); - - /** - * 查询设备简短列表 - * - * @param device 设备 - * @return 设备集合 - */ - public List selectDeviceShortList(Device device); - - /** - * 查询所有设备简短列表 - * - * @return 设备集合 - */ - public List selectAllDeviceShortList(Device device); - - /** - * 新增设备 - * - * @param device 设备 - * @return 结果 - */ - public int insertDevice(Device device); - - /** - * 修改设备 - * - * @param device 设备 - * @return 结果 - */ - public int updateDevice(Device device); - - /** - * 更新设备状态 - * - * @param device 设备 - * @return 结果 - */ - public int updateDeviceStatus(Device device); - - /** - * 通过设备编号修改设备 - * - * @param device 设备 - * @return 结果 - */ - public int updateDeviceBySerialNumber(Device device); - - /** - * 删除设备 - * - * @param deviceId 设备主键 - * @return 结果 - */ - public int deleteDeviceByDeviceId(Long deviceId); - - /** - * 批量删除设备 - * - * @param deviceIds 需要删除的数据主键集合 - * @return 结果 - */ - public int deleteDeviceByDeviceIds(Long[] deviceIds); - - /** - * 查询设备序列号的数量 - * @param deviceNum - * @return - */ - public int getDeviceNumCount(String deviceNum); - - /** - * 根据设备IDS删除设备分组 - * @param deviceIds - * @return - */ - public int deleteDeviceGroupByDeviceId(UserIdDeviceIdModel userDeviceGroupIdModel); - - /** - * 重置设备状态 - * @return 结果 - */ - public int resetDeviceStatus(String deviceNum); - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/DeviceUserMapper.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/DeviceUserMapper.java deleted file mode 100644 index 5e6b8c66..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/DeviceUserMapper.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.ruoyi.iot.mapper; - -import java.util.List; -import com.ruoyi.iot.domain.DeviceUser; -import com.ruoyi.iot.model.UserIdDeviceIdModel; -import org.apache.ibatis.annotations.Param; -import org.springframework.stereotype.Repository; - -/** - * 设备用户Mapper接口 - * - * @author kerwincui - * @date 2021-12-16 - */ -@Repository -public interface DeviceUserMapper -{ - /** - * 查询设备用户 - * - * @param deviceId 设备用户主键 - * @return 设备用户 - */ - public List selectDeviceUserByDeviceId(Long deviceId); - - /** - * 查询设备用户列表 - * - * @param deviceUser 设备用户 - * @return 设备用户集合 - */ - public List selectDeviceUserList(DeviceUser deviceUser); - - /** - * 新增设备用户 - * - * @param deviceUser 设备用户 - * @return 结果 - */ - public int insertDeviceUser(DeviceUser deviceUser); - - /** - * 修改设备用户 - * - * @param deviceUser 设备用户 - * @return 结果 - */ - public int updateDeviceUser(DeviceUser deviceUser); - - /** - * 删除设备用户 - * - * @param UserIdDeviceIdModel 用户ID和设备ID - * @return 结果 - */ - public int deleteDeviceUserByDeviceId(UserIdDeviceIdModel UserIdDeviceIdModel); - - /** - * 批量删除设备用户 - * - * @param deviceIds 需要删除的数据主键集合 - * @return 结果 - */ - public int deleteDeviceUserByDeviceIds(Long[] deviceIds); - - /** - * 批量添加设备用户 - * @param deviceUsers 设备用户 - * @return 结果 - */ - public int insertDeviceUserList(List deviceUsers); - - /** - * 根据deviceId 和 userId 查询 - * @param deviceId 设备id - * @param userId 用户id - * @return 结果 - */ - public DeviceUser selectDeviceUserByDeviceIdAndUserId(@Param("deviceId") Long deviceId, @Param("userId") Long userId); - - /** - * 根据deviceId 和 userId 删除设备用户,不包含设备所有者 - */ - public int deleteDeviceUser(DeviceUser deviceUser); - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/FirmwareMapper.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/FirmwareMapper.java deleted file mode 100644 index 2dab4aea..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/FirmwareMapper.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.ruoyi.iot.mapper; - -import java.util.List; -import com.ruoyi.iot.domain.Firmware; -import org.springframework.stereotype.Repository; - -/** - * 产品固件Mapper接口 - * - * @author kerwincui - * @date 2021-12-16 - */ -@Repository -public interface FirmwareMapper -{ - /** - * 查询产品固件 - * - * @param firmwareId 产品固件主键 - * @return 产品固件 - */ - public Firmware selectFirmwareByFirmwareId(Long firmwareId); - - /** - * 查询设备最新固件 - * - * @param deviceId 产品固件主键 - * @return 产品固件 - */ - public Firmware selectLatestFirmware(Long deviceId); - - /** - * 查询产品固件列表 - * - * @param firmware 产品固件 - * @return 产品固件集合 - */ - public List selectFirmwareList(Firmware firmware); - - /** - * 新增产品固件 - * - * @param firmware 产品固件 - * @return 结果 - */ - public int insertFirmware(Firmware firmware); - - /** - * 修改产品固件 - * - * @param firmware 产品固件 - * @return 结果 - */ - public int updateFirmware(Firmware firmware); - - /** - * 删除产品固件 - * - * @param firmwareId 产品固件主键 - * @return 结果 - */ - public int deleteFirmwareByFirmwareId(Long firmwareId); - - /** - * 批量删除产品固件 - * - * @param firmwareIds 需要删除的数据主键集合 - * @return 结果 - */ - public int deleteFirmwareByFirmwareIds(Long[] firmwareIds); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/GroupMapper.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/GroupMapper.java deleted file mode 100644 index 59bc22b7..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/GroupMapper.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.ruoyi.iot.mapper; - -import java.util.List; -import com.ruoyi.iot.domain.Group; -import com.ruoyi.iot.model.DeviceGroupInput; -import com.ruoyi.iot.model.IdOutput; -import org.springframework.stereotype.Repository; - -/** - * 设备分组Mapper接口 - * - * @author kerwincui - * @date 2021-12-16 - */ -@Repository -public interface GroupMapper -{ - /** - * 查询设备分组 - * - * @param groupId 设备分组主键 - * @return 设备分组 - */ - public Group selectGroupByGroupId(Long groupId); - - /** - * 通过分组ID查询关联的设备ID数组 - * @param groupId - * @return - */ - public List selectDeviceIdsByGroupId(Long groupId); - - /** - * 查询设备分组列表 - * - * @param group 设备分组 - * @return 设备分组集合 - */ - public List selectGroupList(Group group); - - /** - * 新增设备分组 - * - * @param group 设备分组 - * @return 结果 - */ - public int insertGroup(Group group); - - /** - * 分组下批量增加设备分组 - * @param input - * @return - */ - public int insertDeviceGroups(DeviceGroupInput input); - - /** - * 修改设备分组 - * - * @param group 设备分组 - * @return 结果 - */ - public int updateGroup(Group group); - - /** - * 删除设备分组 - * - * @param groupId 设备分组主键 - * @return 结果 - */ - public int deleteGroupByGroupId(Long groupId); - - /** - * 批量删除分组 - * - * @param groupIds 需要删除的数据主键集合 - * @return 结果 - */ - public int deleteGroupByGroupIds(Long[] groupIds); - - /** - * 批量删除设备分组 - * @param groupIds - * @return - */ - public int deleteDeviceGroupByGroupIds(Long[] groupIds); - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/NewsCategoryMapper.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/NewsCategoryMapper.java deleted file mode 100644 index d44a595a..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/NewsCategoryMapper.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.ruoyi.iot.mapper; - -import java.util.List; -import com.ruoyi.iot.domain.NewsCategory; -import com.ruoyi.iot.model.IdAndName; - -/** - * 新闻分类Mapper接口 - * - * @author kerwincui - * @date 2022-04-09 - */ -public interface NewsCategoryMapper -{ - /** - * 查询新闻分类 - * - * @param categoryId 新闻分类主键 - * @return 新闻分类 - */ - public NewsCategory selectNewsCategoryByCategoryId(Long categoryId); - - /** - * 查询新闻分类列表 - * - * @param newsCategory 新闻分类 - * @return 新闻分类集合 - */ - public List selectNewsCategoryList(NewsCategory newsCategory); - - /** - * 查询新闻分类简短列表 - * - * @return 新闻分类集合 - */ - public List selectNewsCategoryShortList(); - - /** - * 新增新闻分类 - * - * @param newsCategory 新闻分类 - * @return 结果 - */ - public int insertNewsCategory(NewsCategory newsCategory); - - /** - * 修改新闻分类 - * - * @param newsCategory 新闻分类 - * @return 结果 - */ - public int updateNewsCategory(NewsCategory newsCategory); - - /** - * 删除新闻分类 - * - * @param categoryId 新闻分类主键 - * @return 结果 - */ - public int deleteNewsCategoryByCategoryId(Long categoryId); - - /** - * 批量删除新闻分类 - * - * @param categoryIds 需要删除的数据主键集合 - * @return 结果 - */ - public int deleteNewsCategoryByCategoryIds(Long[] categoryIds); - - /** - * 分类下的新闻数量 - * - * @param categoryIds 需要删除的数据主键集合 - * @return 结果 - */ - public int newsCountInCategorys(Long[] categoryIds); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/NewsMapper.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/NewsMapper.java deleted file mode 100644 index 2e0f6229..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/NewsMapper.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.ruoyi.iot.mapper; - -import java.util.List; -import com.ruoyi.iot.domain.News; - -/** - * 新闻资讯Mapper接口 - * - * @author kerwincui - * @date 2022-04-09 - */ -public interface NewsMapper -{ - /** - * 查询新闻资讯 - * - * @param newsId 新闻资讯主键 - * @return 新闻资讯 - */ - public News selectNewsByNewsId(Long newsId); - - /** - * 查询新闻资讯列表 - * - * @param news 新闻资讯 - * @return 新闻资讯集合 - */ - public List selectNewsList(News news); - - /** - * 查询置顶新闻资讯列表 - * - * @return 新闻资讯集合 - */ - public List selectTopNewsList(); - - /** - * 新增新闻资讯 - * - * @param news 新闻资讯 - * @return 结果 - */ - public int insertNews(News news); - - /** - * 修改新闻资讯 - * - * @param news 新闻资讯 - * @return 结果 - */ - public int updateNews(News news); - - /** - * 删除新闻资讯 - * - * @param newsId 新闻资讯主键 - * @return 结果 - */ - public int deleteNewsByNewsId(Long newsId); - - /** - * 批量删除新闻资讯 - * - * @param newsIds 需要删除的数据主键集合 - * @return 结果 - */ - public int deleteNewsByNewsIds(Long[] newsIds); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/OauthClientDetailsMapper.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/OauthClientDetailsMapper.java deleted file mode 100644 index e6f14266..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/OauthClientDetailsMapper.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.ruoyi.iot.mapper; - -import java.util.List; -import com.ruoyi.iot.domain.OauthClientDetails; -import org.springframework.stereotype.Repository; - -/** - * 云云对接Mapper接口 - * - * @author kerwincui - * @date 2022-02-07 - */ -@Repository -public interface OauthClientDetailsMapper -{ - /** - * 查询云云对接 - * - * @param clientId 云云对接主键 - * @return 云云对接 - */ - public OauthClientDetails selectOauthClientDetailsByClientId(String clientId); - - /** - * 查询云云对接列表 - * - * @param oauthClientDetails 云云对接 - * @return 云云对接集合 - */ - public List selectOauthClientDetailsList(OauthClientDetails oauthClientDetails); - - /** - * 新增云云对接 - * - * @param oauthClientDetails 云云对接 - * @return 结果 - */ - public int insertOauthClientDetails(OauthClientDetails oauthClientDetails); - - /** - * 修改云云对接 - * - * @param oauthClientDetails 云云对接 - * @return 结果 - */ - public int updateOauthClientDetails(OauthClientDetails oauthClientDetails); - - /** - * 删除云云对接 - * - * @param clientId 云云对接主键 - * @return 结果 - */ - public int deleteOauthClientDetailsByClientId(String clientId); - - /** - * 批量删除云云对接 - * - * @param clientIds 需要删除的数据主键集合 - * @return 结果 - */ - public int deleteOauthClientDetailsByClientIds(String[] clientIds); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/ProductAuthorizeMapper.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/ProductAuthorizeMapper.java deleted file mode 100644 index 413e5712..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/ProductAuthorizeMapper.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.ruoyi.iot.mapper; - -import java.util.List; -import com.ruoyi.iot.domain.ProductAuthorize; -import org.springframework.stereotype.Repository; - -/** - * 产品授权码Mapper接口 - * - * @author kami - * @date 2022-04-11 - */ -@Repository -public interface ProductAuthorizeMapper -{ - /** - * 查询产品授权码 - * - * @param authorizeId 产品授权码主键 - * @return 产品授权码 - */ - public ProductAuthorize selectProductAuthorizeByAuthorizeId(Long authorizeId); - - /** - * 查询产品授权码列表 - * - * @param productAuthorize 产品授权码 - * @return 产品授权码集合 - */ - public List selectProductAuthorizeList(ProductAuthorize productAuthorize); - - /** - * 新增产品授权码 - * - * @param productAuthorize 产品授权码 - * @return 结果 - */ - public int insertProductAuthorize(ProductAuthorize productAuthorize); - - /** - * 修改产品授权码 - * - * @param productAuthorize 产品授权码 - * @return 结果 - */ - public int updateProductAuthorize(ProductAuthorize productAuthorize); - - /** - * 删除产品授权码 - * - * @param authorizeId 产品授权码主键 - * @return 结果 - */ - public int deleteProductAuthorizeByAuthorizeId(Long authorizeId); - - /** - * 批量删除产品授权码 - * - * @param authorizeIds 需要删除的数据主键集合 - * @return 结果 - */ - public int deleteProductAuthorizeByAuthorizeIds(Long[] authorizeIds); - - /** - * 通过产品ID批量删除产品授权码 - * - * @param productIds 产品ID数组 - * @return 结果 - */ - public int deleteProductAuthorizeByProductIds(Long[] productIds); - - /** - * 批量新增产品授权码 - * @param list - * @return - */ - public int insertBatchAuthorize(List list); - - /** - * 根据授权码查询一条未绑定的授权码 - * @param authorize - * @return - */ - ProductAuthorize selectFirstAuthorizeByAuthorizeCode(ProductAuthorize authorize); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/ProductMapper.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/ProductMapper.java deleted file mode 100644 index 2afe2c2a..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/ProductMapper.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.ruoyi.iot.mapper; - -import com.ruoyi.iot.domain.Product; -import com.ruoyi.iot.model.ChangeProductStatusModel; -import com.ruoyi.iot.model.IdAndName; -import org.springframework.stereotype.Repository; - -import java.util.List; - -/** - * 产品Mapper接口 - * - * @author kerwincui - * @date 2021-12-16 - */ -@Repository -public interface ProductMapper -{ - /** - * 查询产品 - * - * @param productId 产品主键 - * @return 产品 - */ - public Product selectProductByProductId(Long productId); - - /** - * 查询产品列表 - * - * @param product 产品 - * @return 产品集合 - */ - public List selectProductList(Product product); - - /** - * 查询产品简短列表 - * - * @param product 产品 - * @return 产品集合 - */ - public List selectProductShortList(Product product); - - /** - * 新增产品 - * - * @param product 产品 - * @return 结果 - */ - public int insertProduct(Product product); - - /** - * 修改产品 - * - * @param product 产品 - * @return 结果 - */ - public int updateProduct(Product product); - - /** - * 更新产品状态,1-未发布,2-已发布 - * - * @param model - * @return 结果 - */ - public int changeProductStatus(ChangeProductStatusModel model); - - /** - * 修改物模型JSON - * - * @param product 产品 - * @return 结果 - */ - public int updateThingsModelJson(Product product); - - /** - * 删除产品 - * - * @param productId 产品主键 - * @return 结果 - */ - public int deleteProductByProductId(Long productId); - - /** - * 批量删除产品 - * - * @param productIds 需要删除的数据主键集合 - * @return 结果 - */ - public int deleteProductByProductIds(Long[] productIds); - - /** - * 批量删除产品物模型 - * - * @param productIds 需要删除的数据主键集合 - * @return 结果 - */ - public int deleteProductThingsModelByProductIds(Long[] productIds); - - /** - * 产品下的固件数量 - * @param productIds 需要删除的数据主键集合 - * @return 结果 - */ - public int firmwareCountInProducts(Long[] productIds); - - /** - * 产品下的设备数量 - * @param productIds 需要删除的数据主键集合 - * @return 结果 - */ - public int deviceCountInProducts(Long[] productIds); - - /** - * 产品下的物模型数量 - * @param productId 需要删除的数据主键集合 - * @return 结果 - */ - public int thingsCountInProduct(Long productId); - - /** - * 产品下的物模型标识符重复数 - * @param productId 需要删除的数据主键集合 - * @return 结果 - */ - public int thingsRepeatCountInProduct(Long productId); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/SceneMapper.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/SceneMapper.java deleted file mode 100644 index f7ba778c..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/SceneMapper.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.ruoyi.iot.mapper; - -import java.util.List; -import com.ruoyi.iot.domain.Scene; -import org.springframework.stereotype.Repository; - -/** - * 场景联动Mapper接口 - * - * @author kerwincui - * @date 2022-01-13 - */ -@Repository -public interface SceneMapper -{ - /** - * 查询场景联动 - * - * @param sceneId 场景联动主键 - * @return 场景联动 - */ - public Scene selectSceneBySceneId(Long sceneId); - - /** - * 查询场景联动列表 - * - * @param scene 场景联动 - * @return 场景联动集合 - */ - public List selectSceneList(Scene scene); - - /** - * 新增场景联动 - * - * @param scene 场景联动 - * @return 结果 - */ - public int insertScene(Scene scene); - - /** - * 修改场景联动 - * - * @param scene 场景联动 - * @return 结果 - */ - public int updateScene(Scene scene); - - /** - * 删除场景联动 - * - * @param sceneId 场景联动主键 - * @return 结果 - */ - public int deleteSceneBySceneId(Long sceneId); - - /** - * 批量删除场景联动 - * - * @param sceneIds 需要删除的数据主键集合 - * @return 结果 - */ - public int deleteSceneBySceneIds(Long[] sceneIds); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/SocialPlatformMapper.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/SocialPlatformMapper.java deleted file mode 100644 index eb0049cc..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/SocialPlatformMapper.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.ruoyi.iot.mapper; - -import java.util.List; -import com.ruoyi.iot.domain.SocialPlatform; - -/** - * 第三方登录平台控制Mapper接口 - * - * @author kerwincui - * @date 2022-04-11 - */ -public interface SocialPlatformMapper -{ - /** - * 查询第三方登录平台控制 - * - * @param socialPlatformId 第三方登录平台控制主键 - * @return 第三方登录平台控制 - */ - public SocialPlatform selectSocialPlatformBySocialPlatformId(Long socialPlatformId); - - /** - * 查询第三方登录平台控制 - * - * @param platform 第三方登录平台名称 - * @return 第三方登录平台控制 - */ - public SocialPlatform selectSocialPlatformByPlatform(String platform); - - /** - * 查询第三方登录平台控制列表 - * - * @param socialPlatform 第三方登录平台控制 - * @return 第三方登录平台控制集合 - */ - public List selectSocialPlatformList(SocialPlatform socialPlatform); - - /** - * 新增第三方登录平台控制 - * - * @param socialPlatform 第三方登录平台控制 - * @return 结果 - */ - public int insertSocialPlatform(SocialPlatform socialPlatform); - - /** - * 修改第三方登录平台控制 - * - * @param socialPlatform 第三方登录平台控制 - * @return 结果 - */ - public int updateSocialPlatform(SocialPlatform socialPlatform); - - /** - * 删除第三方登录平台控制 - * - * @param socialPlatformId 第三方登录平台控制主键 - * @return 结果 - */ - public int deleteSocialPlatformBySocialPlatformId(Long socialPlatformId); - - /** - * 批量删除第三方登录平台控制 - * - * @param socialPlatformIds 需要删除的数据主键集合 - * @return 结果 - */ - public int deleteSocialPlatformBySocialPlatformIds(Long[] socialPlatformIds); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/SocialUserMapper.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/SocialUserMapper.java deleted file mode 100644 index 56d3b8e6..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/SocialUserMapper.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.ruoyi.iot.mapper; - -import java.util.List; -import com.ruoyi.iot.domain.SocialUser; - -/** - * 用户第三方用户信息Mapper接口 - * - * @author json - * @date 2022-04-18 - */ -public interface SocialUserMapper -{ - /** - * 查询用户第三方用户信息 - * - * @param socialUserId 用户第三方用户信息主键 - * @return 用户第三方用户信息 - */ - public SocialUser selectSocialUserBySocialUserId(Long socialUserId); - - /** - * 查询用户第三方用户信息列表 - * - * @param socialUser 用户第三方用户信息 - * @return 用户第三方用户信息集合 - */ - public List selectSocialUserList(SocialUser socialUser); - - /** - * 新增用户第三方用户信息 - * - * @param socialUser 用户第三方用户信息 - * @return 结果 - */ - public int insertSocialUser(SocialUser socialUser); - - /** - * 修改用户第三方用户信息 - * - * @param socialUser 用户第三方用户信息 - * @return 结果 - */ - public int updateSocialUser(SocialUser socialUser); - - /** - * 删除用户第三方用户信息 - * - * @param socialUserId 用户第三方用户信息主键 - * @return 结果 - */ - public int deleteSocialUserBySocialUserId(Long socialUserId); - - /** - * 批量删除用户第三方用户信息 - * - * @param socialUserIds 需要删除的数据主键集合 - * @return 结果 - */ - public int deleteSocialUserBySocialUserIds(Long[] socialUserIds); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/ThingsModelMapper.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/ThingsModelMapper.java deleted file mode 100644 index ca8ebb48..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/ThingsModelMapper.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.ruoyi.iot.mapper; - -import com.ruoyi.iot.domain.ThingsModel; -import org.springframework.stereotype.Repository; - -import java.util.List; - -/** - * 物模型Mapper接口 - * - * @author kerwincui - * @date 2021-12-16 - */ -@Repository -public interface ThingsModelMapper -{ - /** - * 查询物模型 - * - * @param modelId 物模型主键 - * @return 物模型 - */ - public ThingsModel selectThingsModelByModelId(Long modelId); - - /** - * 查询物模型列表 - * - * @param thingsModel 物模型 - * @return 物模型集合 - */ - public List selectThingsModelList(ThingsModel thingsModel); - - /** - * 根据产品ID数组获取物模型列表 - * @param modelIds - * @return - */ - public List selectThingsModelListByProductIds(Long[] modelIds); - - /** - * 新增物模型 - * - * @param thingsModel 物模型 - * @return 结果 - */ - public int insertThingsModel(ThingsModel thingsModel); - - /** - * 批量新增物模型 - * @param thingsModels - * @return - */ - public int insertBatchThingsModel(List thingsModels); - - /** - * 修改物模型 - * - * @param thingsModel 物模型 - * @return 结果 - */ - public int updateThingsModel(ThingsModel thingsModel); - - /** - * 删除物模型 - * - * @param modelId 物模型主键 - * @return 结果 - */ - public int deleteThingsModelByModelId(Long modelId); - - /** - * 批量删除物模型 - * - * @param modelIds 需要删除的数据主键集合 - * @return 结果 - */ - public int deleteThingsModelByModelIds(Long[] modelIds); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/ThingsModelTemplateMapper.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/ThingsModelTemplateMapper.java deleted file mode 100644 index 07572988..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/ThingsModelTemplateMapper.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.ruoyi.iot.mapper; - -import com.ruoyi.iot.domain.ThingsModelTemplate; -import org.springframework.stereotype.Repository; - -import java.util.List; - -/** - * 通用物模型Mapper接口 - * - * @author kerwincui - * @date 2021-12-16 - */ -@Repository -public interface ThingsModelTemplateMapper -{ - /** - * 查询通用物模型 - * - * @param templateId 通用物模型主键 - * @return 通用物模型 - */ - public ThingsModelTemplate selectThingsModelTemplateByTemplateId(Long templateId); - - /** - * 根据id数组查询通用物模型集合 - * @param templateIds - * @return - */ - public List selectThingsModelTemplateByTemplateIds (Long[] templateIds); - - /** - * 查询通用物模型列表 - * - * @param thingsModelTemplate 通用物模型 - * @return 通用物模型集合 - */ - public List selectThingsModelTemplateList(ThingsModelTemplate thingsModelTemplate); - - /** - * 新增通用物模型 - * - * @param thingsModelTemplate 通用物模型 - * @return 结果 - */ - public int insertThingsModelTemplate(ThingsModelTemplate thingsModelTemplate); - - /** - * 修改通用物模型 - * - * @param thingsModelTemplate 通用物模型 - * @return 结果 - */ - public int updateThingsModelTemplate(ThingsModelTemplate thingsModelTemplate); - - /** - * 删除通用物模型 - * - * @param templateId 通用物模型主键 - * @return 结果 - */ - public int deleteThingsModelTemplateByTemplateId(Long templateId); - - /** - * 批量删除通用物模型 - * - * @param templateIds 需要删除的数据主键集合 - * @return 结果 - */ - public int deleteThingsModelTemplateByTemplateIds(Long[] templateIds); - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/Action.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/Action.java deleted file mode 100644 index 436d8fc5..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/Action.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.ruoyi.iot.model; - -/** - * 动作 - * @author kerwincui - * @date 2021-12-16 - */ -public class Action -{ - /** 标识符 */ - private String id; - - /** 名称 */ - private String name; - - /** 值 */ - private String value; - - /** 类型:1=属性,2=功能,3=事件,5=设备上线,6=设备下线 */ - private int type; - - /** 源:1=设备,2=定时,3=告警输出 */ - private int source; - - /** 设备ID */ - private Long deviceId; - - /** 设备名称 */ - private String deviceName; - - /** 告警名称 */ - private String alertName; - - /** 告警级别 */ - private int alertLevel; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public int getType() { - return type; - } - - public void setType(int type) { - this.type = type; - } - - public int getSource() { - return source; - } - - public void setSource(int source) { - this.source = source; - } - - public Long getDeviceId() { - return deviceId; - } - - public void setDeviceId(Long deviceId) { - this.deviceId = deviceId; - } - - public String getDeviceName() { - return deviceName; - } - - public void setDeviceName(String deviceName) { - this.deviceName = deviceName; - } - - public String getAlertName() { - return alertName; - } - - public void setAlertName(String alertName) { - this.alertName = alertName; - } - - public int getAlertLevel() { - return alertLevel; - } - - public void setAlertLevel(int alertLevel) { - this.alertLevel = alertLevel; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/AuthenticateInputModel.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/AuthenticateInputModel.java deleted file mode 100644 index 66c43211..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/AuthenticateInputModel.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.ruoyi.iot.model; - -/** - * 动作 - * @author kerwincui - * @date 2021-12-16 - */ -public class AuthenticateInputModel -{ - /** 设备编号 */ - private String serialNumber; - - /** 产品ID */ - private Long productId; - - public AuthenticateInputModel(String serialNumber,Long productId){ - this.serialNumber=serialNumber; - this.productId=productId; - } - - public String getSerialNumber() { - return serialNumber; - } - - public void setSerialNumber(String serialNumber) { - this.serialNumber = serialNumber; - } - - public Long getProductId() { - return productId; - } - - public void setProductId(Long productId) { - this.productId = productId; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/CategoryNews.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/CategoryNews.java deleted file mode 100644 index a1d4111d..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/CategoryNews.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.ruoyi.iot.model; - -import com.ruoyi.iot.domain.News; - -import java.util.ArrayList; -import java.util.List; - -/** - * 产品分类的Id和名称输出 - * - * @author kerwincui - * @date 2021-12-16 - */ -public class CategoryNews -{ - private Long categoryId; - - private String categoryName; - - private List newsList; - - public CategoryNews(){ - this.newsList=new ArrayList<>(); - } - - public Long getCategoryId() { - return categoryId; - } - - public void setCategoryId(Long categoryId) { - this.categoryId = categoryId; - } - - public String getCategoryName() { - return categoryName; - } - - public void setCategoryName(String categoryName) { - this.categoryName = categoryName; - } - - public List getNewsList() { - return newsList; - } - - public void setNewsList(List newsList) { - this.newsList = newsList; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ChangeProductStatusModel.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ChangeProductStatusModel.java deleted file mode 100644 index 39ece707..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ChangeProductStatusModel.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.ruoyi.iot.model; - -/** - * id和name - * - * @author kerwincui - * @date 2021-12-16 - */ -public class ChangeProductStatusModel -{ - private Long productId; - - private Integer status; - - public Long getProductId() { - return productId; - } - - public void setProductId(Long productId) { - this.productId = productId; - } - - public Integer getStatus() { - return status; - } - - public void setStatus(Integer status) { - this.status = status; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/DeviceAllShortOutput.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/DeviceAllShortOutput.java deleted file mode 100644 index a29fbad0..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/DeviceAllShortOutput.java +++ /dev/null @@ -1,199 +0,0 @@ -package com.ruoyi.iot.model; - -import com.fasterxml.jackson.annotation.JsonFormat; - -import java.math.BigDecimal; -import java.util.Date; - -/** - * 设备对象 iot_device - * - * @author kerwincui - * @date 2021-12-16 - */ -public class DeviceAllShortOutput -{ - private static final long serialVersionUID = 1L; - - /** 产品分类ID */ - private Long deviceId; - - /** 产品分类名称 */ - private String deviceName; - - /** 产品名称 */ - private String productName; - - /** 用户昵称 */ - private String userName; - - /** 设备编号 */ - private String serialNumber; - - /** 固件版本 */ - private BigDecimal firmwareVersion; - - /** 设备状态(1-未激活,2-禁用,3-在线,4-离线) */ - private Integer status; - - /** 设备影子 */ - private Integer isShadow; - - /** wifi信号强度(信号极好4格[-55— 0],信号好3格[-70— -55],信号一般2格[-85— -70],信号差1格[-100— -85]) */ - private Integer rssi; - - /** 激活时间 */ - @JsonFormat(pattern = "yyyy-MM-dd") - private Date activeTime; - - /** 是否自定义位置 **/ - private Integer locationWay; - - /** 设备地址 */ - private String networkAddress; - - /** 经度 */ - private BigDecimal longitude; - - /** 纬度 */ - private BigDecimal latitude; - - /** 是否设备所有者,用于查询 **/ - private Integer isOwner; - - public Integer getLocationWay() { - return locationWay; - } - - public void setLocationWay(Integer locationWay) { - this.locationWay = locationWay; - } - - public Integer getIsOwner() { - return isOwner; - } - - public void setIsOwner(Integer isOwner) { - this.isOwner = isOwner; - } - - public String getNetworkAddress() { - return networkAddress; - } - - public void setNetworkAddress(String networkAddress) { - this.networkAddress = networkAddress; - } - - public BigDecimal getLongitude() { - return longitude; - } - - public void setLongitude(BigDecimal longitude) { - this.longitude = longitude; - } - - public BigDecimal getLatitude() { - return latitude; - } - - public void setLatitude(BigDecimal latitude) { - this.latitude = latitude; - } - - public Integer getIsShadow() { - return isShadow; - } - - public void setIsShadow(Integer isShadow) { - this.isShadow = isShadow; - } - - public void setRssi(Integer rssi) - { - this.rssi = rssi; - } - - public Integer getRssi() - { - return rssi; - } - - public void setDeviceId(Long deviceId) - { - this.deviceId = deviceId; - } - - public Long getDeviceId() - { - return deviceId; - } - public void setDeviceName(String deviceName) - { - this.deviceName = deviceName; - } - - public String getDeviceName() - { - return deviceName; - } - - public void setProductName(String productName) - { - this.productName = productName; - } - - public String getProductName() - { - return productName; - } - - public void setUserName(String userName) - { - this.userName = userName; - } - - public String getUserName() - { - return userName; - } - - public void setStatus(Integer status) - { - this.status = status; - } - public Integer getStatus() - { - return status; - } - - public void setSerialNumber(String serialNumber) - { - this.serialNumber = serialNumber; - } - - public String getSerialNumber() - { - return serialNumber; - } - public void setFirmwareVersion(BigDecimal firmwareVersion) - { - this.firmwareVersion = firmwareVersion; - } - - public BigDecimal getFirmwareVersion() - { - return firmwareVersion; - } - - public void setActiveTime(Date activeTime) - { - this.activeTime = activeTime; - } - - public Date getActiveTime() - { - return activeTime; - } - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/DeviceGroupInput.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/DeviceGroupInput.java deleted file mode 100644 index 61f135d8..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/DeviceGroupInput.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.ruoyi.iot.model; - -/** - * 设备分组对象 iot_device_group - * - * @author kerwincui - * @date 2021-12-16 - */ -public class DeviceGroupInput -{ - private static final long serialVersionUID = 1L; - - /** 分组ID */ - private Long groupId; - - /** 设备ID */ - private Long[] deviceIds; - - public Long getGroupId() { - return groupId; - } - - public void setGroupId(Long groupId) { - this.groupId = groupId; - } - - public Long[] getDeviceIds() { - return deviceIds; - } - - public void setDeviceIds(Long[] deviceIds) { - this.deviceIds = deviceIds; - } - - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/DeviceNumberAndProductId.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/DeviceNumberAndProductId.java deleted file mode 100644 index 7379f81e..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/DeviceNumberAndProductId.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.ruoyi.iot.model; - -/** - * - * @author kerwincui - * @date 2021-12-16 - */ -public class DeviceNumberAndProductId -{ - /** 产品ID,用于自动添加设备 */ - private Long productId; - - /** 设备编号集合 */ - private String deviceNumber; - - public DeviceNumberAndProductId(){} - - public DeviceNumberAndProductId(Long productId, String deviceNumber){ - this.productId=productId; - this.deviceNumber=deviceNumber; - } - - public Long getProductId() { - return productId; - } - - public void setProductId(Long productId) { - this.productId = productId; - } - - public String getDeviceNumber() { - return deviceNumber; - } - - public void setDeviceNumber(String deviceNumber) { - this.deviceNumber = deviceNumber; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/DeviceRelateUserInput.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/DeviceRelateUserInput.java deleted file mode 100644 index e4b30e27..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/DeviceRelateUserInput.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.ruoyi.iot.model; - -import java.util.List; - -/** - * - * @author kerwincui - * @date 2021-12-16 - */ -public class DeviceRelateUserInput -{ - - /** 用户Id */ - private Long userId; - - /** 设备编号和产品ID集合 */ - private List deviceNumberAndProductIds; - - public DeviceRelateUserInput(){} - - public DeviceRelateUserInput(Long userId,List deviceNumberAndProductIds){ - this.userId=userId; - this.deviceNumberAndProductIds=deviceNumberAndProductIds; - } - - public Long getUserId() { - return userId; - } - - public void setUserId(Long userId) { - this.userId = userId; - } - - public List getDeviceNumberAndProductIds() { - return deviceNumberAndProductIds; - } - - public void setDeviceNumberAndProductIds(List deviceNumberAndProductIds) { - this.deviceNumberAndProductIds = deviceNumberAndProductIds; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/DeviceShortOutput.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/DeviceShortOutput.java deleted file mode 100644 index 6c7a5902..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/DeviceShortOutput.java +++ /dev/null @@ -1,322 +0,0 @@ -package com.ruoyi.iot.model; - -import com.fasterxml.jackson.annotation.JsonFormat; -import com.ruoyi.common.annotation.Excel; -import com.ruoyi.iot.model.ThingsModelItem.*; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -/** - * 设备对象 iot_device - * - * @author kerwincui - * @date 2021-12-16 - */ -public class DeviceShortOutput -{ - public DeviceShortOutput(){ - this.stringList=new ArrayList<>(); - this.integerList=new ArrayList<>(); - this.decimalList=new ArrayList<>(); - this.enumList=new ArrayList<>(); - this.arrayList=new ArrayList<>(); - this.readOnlyList =new ArrayList<>(); - this.boolList=new ArrayList<>(); - } - - private static final long serialVersionUID = 1L; - - /** 产品分类ID */ - private Long deviceId; - - /** 产品分类名称 */ - @Excel(name = "设备名称") - private String deviceName; - - /** 产品ID */ - @Excel(name = "产品ID") - private Long productId; - - /** 产品名称 */ - @Excel(name = "产品名称") - private String productName; - - /** 用户ID */ - @Excel(name = "用户ID") - private Long userId; - - /** 用户昵称 */ - @Excel(name = "用户昵称") - private String userName; - - /** 租户ID */ - @Excel(name = "租户ID") - private Long tenantId; - - /** 租户名称 */ - @Excel(name = "租户名称") - private String tenantName; - - /** 设备编号 */ - @Excel(name = "设备编号") - private String serialNumber; - - /** 固件版本 */ - @Excel(name = "固件版本") - private BigDecimal firmwareVersion; - - /** 设备状态(1-未激活,2-禁用,3-在线,4-离线) */ - @Excel(name = "设备状态") - private Integer status; - - /** 设备影子 */ - private Integer isShadow; - - /** wifi信号强度(信号极好4格[-55— 0],信号好3格[-70— -55],信号一般2格[-85— -70],信号差1格[-100— -85]) */ - @Excel(name = "wifi信号强度") - private Integer rssi; - - @Excel(name = "物模型") - private String thingsModelValue; - - /** 激活时间 */ - @JsonFormat(pattern = "yyyy-MM-dd") - @Excel(name = "激活时间", width = 30, dateFormat = "yyyy-MM-dd") - private Date activeTime; - - /** 是否自定义位置 **/ - private Integer locationWay; - - /** 图片地址 */ - private String imgUrl; - - /** 是否设备所有者,用于查询 **/ - private Integer isOwner; - - private List stringList; - private List integerList; - private List decimalList; - private List enumList; - private List arrayList; - private List boolList; - private List readOnlyList; - - public Integer getLocationWay() { - return locationWay; - } - - public void setLocationWay(Integer locationWay) { - this.locationWay = locationWay; - } - - public Integer getIsOwner() { - return isOwner; - } - - public void setIsOwner(Integer isOwner) { - this.isOwner = isOwner; - } - - public String getImgUrl() { - return imgUrl; - } - - public void setImgUrl(String imgUrl) { - this.imgUrl = imgUrl; - } - - public Integer getIsShadow() { - return isShadow; - } - - public void setIsShadow(Integer isShadow) { - this.isShadow = isShadow; - } - - public List getBoolList() { - return boolList; - } - - public void setBoolList(List boolList) { - this.boolList = boolList; - } - - public List getReadOnlyList() { - return readOnlyList; - } - - public void setReadOnlyList(List readOnlyList) { - this.readOnlyList = readOnlyList; - } - - public List getStringList() { - return stringList; - } - - public void setStringList(List stringList) { - this.stringList = stringList; - } - - public List getIntegerList() { - return integerList; - } - - public void setIntegerList(List integerList) { - this.integerList = integerList; - } - - public List getDecimalList() { - return decimalList; - } - - public void setDecimalList(List decimalList) { - this.decimalList = decimalList; - } - - public List getEnumList() { - return enumList; - } - - public void setEnumList(List enumList) { - this.enumList = enumList; - } - - public List getArrayList() { - return arrayList; - } - - public void setArrayList(List arrayList) { - this.arrayList = arrayList; - } - public void setRssi(Integer rssi) - { - this.rssi = rssi; - } - - public Integer getRssi() - { - return rssi; - } - public void setThingsModelValue(String thingsModelValue) - { - this.thingsModelValue = thingsModelValue; - } - - public String getThingsModelValue() - { - return thingsModelValue; - } - public void setDeviceId(Long deviceId) - { - this.deviceId = deviceId; - } - - public Long getDeviceId() - { - return deviceId; - } - public void setDeviceName(String deviceName) - { - this.deviceName = deviceName; - } - - public String getDeviceName() - { - return deviceName; - } - public void setProductId(Long productId) - { - this.productId = productId; - } - - public Long getProductId() - { - return productId; - } - public void setProductName(String productName) - { - this.productName = productName; - } - - public String getProductName() - { - return productName; - } - public void setUserId(Long userId) - { - this.userId = userId; - } - - public Long getUserId() - { - return userId; - } - public void setUserName(String userName) - { - this.userName = userName; - } - - public String getUserName() - { - return userName; - } - public void setTenantId(Long tenantId) - { - this.tenantId = tenantId; - } - - public void setStatus(Integer status) - { - this.status = status; - } - public Integer getStatus() - { - return status; - } - - public Long getTenantId() - { - return tenantId; - } - public void setTenantName(String tenantName) - { - this.tenantName = tenantName; - } - - public String getTenantName() - { - return tenantName; - } - public void setSerialNumber(String serialNumber) - { - this.serialNumber = serialNumber; - } - - public String getSerialNumber() - { - return serialNumber; - } - public void setFirmwareVersion(BigDecimal firmwareVersion) - { - this.firmwareVersion = firmwareVersion; - } - - public BigDecimal getFirmwareVersion() - { - return firmwareVersion; - } - - public void setActiveTime(Date activeTime) - { - this.activeTime = activeTime; - } - - public Date getActiveTime() - { - return activeTime; - } - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/DeviceStatistic.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/DeviceStatistic.java deleted file mode 100644 index 943f000a..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/DeviceStatistic.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.ruoyi.iot.model; - -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; - -/** - * id和name - * - * @author kerwincui - * @date 2021-12-16 - */ -public class DeviceStatistic -{ - /** 设备数量 **/ - private int deviceCount; - - /** 产品数量 **/ - private int productCount; - - /** 告警 **/ - private long alertCount; - - /** 属性上报 **/ - private long propertyCount; - - /** 功能上报 **/ - private long functionCount; - - /** 事件上报 **/ - private long eventCount; - - /** 监测数据上报 **/ - private long monitorCount; - - public long getMonitorCount() { - return monitorCount; - } - - public void setMonitorCount(long monitorCount) { - this.monitorCount = monitorCount; - } - - public int getDeviceCount() { - return deviceCount; - } - - public void setDeviceCount(int deviceCount) { - this.deviceCount = deviceCount; - } - - public int getProductCount() { - return productCount; - } - - public void setProductCount(int productCount) { - this.productCount = productCount; - } - - public long getAlertCount() { - return alertCount; - } - - public void setAlertCount(long alertCount) { - this.alertCount = alertCount; - } - - public long getPropertyCount() { - return propertyCount; - } - - public void setPropertyCount(long propertyCount) { - this.propertyCount = propertyCount; - } - - public long getFunctionCount() { - return functionCount; - } - - public void setFunctionCount(long functionCount) { - this.functionCount = functionCount; - } - - public long getEventCount() { - return eventCount; - } - - public void setEventCount(long eventCount) { - this.eventCount = eventCount; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/IdAndName.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/IdAndName.java deleted file mode 100644 index 4e2a39ea..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/IdAndName.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.ruoyi.iot.model; - -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; - -/** - * id和name - * - * @author kerwincui - * @date 2021-12-16 - */ -public class IdAndName -{ - private Long id; - - private String name; - - - public void setId(Long id) - { - this.id = id; - } - public Long getId() - { - return id; - } - - public void setName(String name) - { - this.name = name; - } - public String getName() - { - return name; - } - - @Override - public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("categoryId", getId()) - .append("categoryName", getName()) - .toString(); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/IdOutput.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/IdOutput.java deleted file mode 100644 index e5d96c97..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/IdOutput.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.ruoyi.iot.model; - -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; - -/** - * 产品分类的Id和名称输出 - * - * @author kerwincui - * @date 2021-12-16 - */ -public class IdOutput -{ - private Long id; - - public void setId(Long id) - { - this.id = id; - } - public Long getId() - { - return id; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ImportThingsModelInput.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ImportThingsModelInput.java deleted file mode 100644 index e81e3075..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ImportThingsModelInput.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.ruoyi.iot.model; - -import com.ruoyi.common.annotation.Excel; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; - -/** - * 导入产品物模型的输入对象 - * - * @author kerwincui - * @date 2021-12-16 - */ -public class ImportThingsModelInput -{ - /** 产品ID */ - private Long productId; - - /** 产品名称 */ - private String ProductName; - - /** 通用物模型ID集合 */ - private Long[] templateIds; - - public Long getProductId() { - return productId; - } - - public void setProductId(Long productId) { - this.productId = productId; - } - - public String getProductName() { - return ProductName; - } - - public void setProductName(String productName) { - ProductName = productName; - } - - public Long[] getTemplateIds() { - return templateIds; - } - - public void setTemplateIds(Long[] templateIds) { - this.templateIds = templateIds; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/MonitorModel.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/MonitorModel.java deleted file mode 100644 index 1cb2f1e8..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/MonitorModel.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.ruoyi.iot.model; - -import com.fasterxml.jackson.annotation.JsonFormat; - -import java.util.Date; - -/** - * 动作 - * @author kerwincui - * @date 2021-12-16 - */ -public class MonitorModel -{ - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private Date time; - - private String value; - - public Date getTime() { - return time; - } - - public void setTime(Date time) { - this.time = time; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/MqttAuthenticationModel.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/MqttAuthenticationModel.java deleted file mode 100644 index 1cf2dd63..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/MqttAuthenticationModel.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.ruoyi.iot.model; - -/** - * 动作 - * @author kerwincui - * @date 2021-12-16 - */ -public class MqttAuthenticationModel -{ - /** Mqtt客户端ID */ - String clientId; - - /** Mqtt用户名 */ - String userName; - - /** Mqtt密码 */ - String password; - - /** 设备编号 */ - String deviceNumber; - - /** 产品ID */ - Long productId; - - /** 设备关联的用户ID */ - Long userId; - - public MqttAuthenticationModel(String clientid,String username,String password,String deviceNumber ,Long productId,Long userId){ - this.clientId=clientid; - this.userName=username; - this.password=password; - this.deviceNumber=deviceNumber; - this.productId=productId; - this.userId=userId; - } - public MqttAuthenticationModel(String clientid,String username,String password){ - this.clientId=clientid; - this.userName=username; - this.password=password; - } - - public String getClientId() { - return clientId; - } - - public void setClientId(String clientId) { - this.clientId = clientId; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public String getDeviceNumber() { - return deviceNumber; - } - - public void setDeviceNumber(String deviceNumber) { - this.deviceNumber = deviceNumber; - } - - public Long getProductId() { - return productId; - } - - public void setProductId(Long productId) { - this.productId = productId; - } - - public Long getUserId() { - return userId; - } - - public void setUserId(Long userId) { - this.userId = userId; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/MqttClientConnectModel.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/MqttClientConnectModel.java deleted file mode 100644 index c5b5708f..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/MqttClientConnectModel.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.ruoyi.iot.model; - -/** - * 客户端连接模型 - * - * @author kerwincui - * @date 2021-12-16 - */ -public class MqttClientConnectModel -{ - /** 事件名称(固定为:"client_connected" "client_disconnected") **/ - private String action; - - /** 客户端 ClientId **/ - private String clientid; - - /** 客户端 Username,不存在时该值为 "undefined" **/ - private String username; - - /** 客户端源 IP 地址 **/ - private String ipaddress; - - /** 客户端申请的心跳保活时间 **/ - private Integer keepalive; - - /** 协议版本号 **/ - private Integer proto_ver; - - /** 时间戳(秒) **/ - private Long connected_at; - - /** 错误原因 **/ - private String reason; - - public String getAction() { - return action; - } - - public void setAction(String action) { - this.action = action; - } - - public String getClientid() { - return clientid; - } - - public void setClientid(String clientid) { - this.clientid = clientid; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getIpaddress() { - return ipaddress; - } - - public void setIpaddress(String ipaddress) { - this.ipaddress = ipaddress; - } - - public Integer getKeepalive() { - return keepalive; - } - - public void setKeepalive(Integer keepalive) { - this.keepalive = keepalive; - } - - public Integer getProto_ver() { - return proto_ver; - } - - public void setProto_ver(Integer proto_ver) { - this.proto_ver = proto_ver; - } - - public Long getConnected_at() { - return connected_at; - } - - public void setConnected_at(Long connected_at) { - this.connected_at = connected_at; - } - - public String getReason() { - return reason; - } - - public void setReason(String reason) { - this.reason = reason; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/MqttInfoModel.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/MqttInfoModel.java deleted file mode 100644 index 553929b5..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/MqttInfoModel.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.ruoyi.iot.model; - -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; - -/** - * id和name - * - * @author kerwincui - * @date 2021-12-16 - */ -public class MqttInfoModel -{ - private String clientid; - - private String username; - - private String password; - - public String getClientid() { - return clientid; - } - - public void setClientid(String clientid) { - this.clientid = clientid; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/NtpModel.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/NtpModel.java deleted file mode 100644 index 6e132203..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/NtpModel.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.ruoyi.iot.model; - -/** - * 产品分类的Id和名称输出 - * - * @author kerwincui - * @date 2021-12-16 - */ -public class NtpModel -{ - private Long deviceSendTime; - - private Long serverRecvTime; - - private Long serverSendTime; - - public Long getDeviceSendTime() { - return deviceSendTime; - } - - public void setDeviceSendTime(Long deviceSendTime) { - this.deviceSendTime = deviceSendTime; - } - - public Long getServerRecvTime() { - return serverRecvTime; - } - - public void setServerRecvTime(Long serverRecvTime) { - this.serverRecvTime = serverRecvTime; - } - - public Long getServerSendTime() { - return serverSendTime; - } - - public void setServerSendTime(Long serverSendTime) { - this.serverSendTime = serverSendTime; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ProductAuthenticateModel.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ProductAuthenticateModel.java deleted file mode 100644 index 1bfe0e1b..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ProductAuthenticateModel.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.ruoyi.iot.model; - - -import com.ruoyi.common.annotation.Excel; - -public class ProductAuthenticateModel { - /** 产品分类ID */ - private Long deviceId; - - /** 产品分类名称 */ - private String deviceName; - - /**设备状态(1-未激活,2-禁用,3-在线,4-离线)**/ - private int status; - - /** 产品ID */ - private Long productId; - - /** 产品名称 */ - private String productName; - - /** 产品状态 1-未发布,2-已发布 */ - private int productStatus; - - /** 是否启用授权码(0-否,1-是) */ - private Integer isAuthorize; - - /** 设备编号 */ - private String serialNumber; - - /** mqtt账号 */ - private String mqttAccount; - - /** mqtt密码 */ - private String mqttPassword; - - /** 产品秘钥 */ - private String mqttSecret; - - private int vertificateMethod; - - public int getVertificateMethod() { - return vertificateMethod; - } - - public void setVertificateMethod(int vertificateMethod) { - this.vertificateMethod = vertificateMethod; - } - - public Integer getIsAuthorize() { - return isAuthorize; - } - - public void setIsAuthorize(Integer isAuthorize) { - this.isAuthorize = isAuthorize; - } - - public int getProductStatus() { - return productStatus; - } - - public void setProductStatus(int productStatus) { - this.productStatus = productStatus; - } - - public int getStatus() { - return status; - } - - public void setStatus(int status) { - this.status = status; - } - - public Long getDeviceId() { - return deviceId; - } - - public void setDeviceId(Long deviceId) { - this.deviceId = deviceId; - } - - public String getDeviceName() { - return deviceName; - } - - public void setDeviceName(String deviceName) { - this.deviceName = deviceName; - } - - public Long getProductId() { - return productId; - } - - public void setProductId(Long productId) { - this.productId = productId; - } - - public String getProductName() { - return productName; - } - - public void setProductName(String productName) { - this.productName = productName; - } - - public String getSerialNumber() { - return serialNumber; - } - - public void setSerialNumber(String serialNumber) { - this.serialNumber = serialNumber; - } - - public String getMqttAccount() { - return mqttAccount; - } - - public void setMqttAccount(String mqttAccount) { - this.mqttAccount = mqttAccount; - } - - public String getMqttPassword() { - return mqttPassword; - } - - public void setMqttPassword(String mqttPassword) { - this.mqttPassword = mqttPassword; - } - - public String getMqttSecret() { - return mqttSecret; - } - - public void setMqttSecret(String mqttSecret) { - this.mqttSecret = mqttSecret; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ProductAuthorizeVO.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ProductAuthorizeVO.java deleted file mode 100644 index a21c8966..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ProductAuthorizeVO.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.ruoyi.iot.model; - -/** - * 批量新增产品授权码VO - * - * @author Venus Zhang - * @create 2022-04-11 15:04 - */ - -public class ProductAuthorizeVO { - - private Long productId; - private int createNum; - - public Long getProductId() { - return productId; - } - - public void setProductId(Long productId) { - this.productId = productId; - } - - public int getCreateNum() { - return createNum; - } - - public void setCreateNum(int createNum) { - this.createNum = createNum; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/RegisterUserInput.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/RegisterUserInput.java deleted file mode 100644 index 5119a79a..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/RegisterUserInput.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.ruoyi.iot.model; - -public class RegisterUserInput { - /** - * 用户名 - */ - private String username; - - /** - * 用户密码 - */ - private String password; - - /** - * 验证码 - */ - private String code; - - private String phonenumber; - - /** - * 唯一标识 - */ - private String uuid = ""; - - public String getPhonenumber() { - return phonenumber; - } - - public void setPhonenumber(String phonenumber) { - this.phonenumber = phonenumber; - } - - public String getUsername() - { - return username; - } - - public void setUsername(String username) - { - this.username = username; - } - - public String getPassword() - { - return password; - } - - public void setPassword(String password) - { - this.password = password; - } - - public String getCode() - { - return code; - } - - public void setCode(String code) - { - this.code = code; - } - - public String getUuid() - { - return uuid; - } - - public void setUuid(String uuid) - { - this.uuid = uuid; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/ArrayModelOutput.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/ArrayModelOutput.java deleted file mode 100644 index 5c910634..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/ArrayModelOutput.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.ruoyi.iot.model.ThingsModelItem; - -public class ArrayModelOutput extends ThingsModelItemBase -{ - private String arrayType; - - public String getArrayType() { - return arrayType; - } - - public void setArrayType(String arrayType) { - this.arrayType = arrayType; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/BoolModelOutput.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/BoolModelOutput.java deleted file mode 100644 index 7f362bc2..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/BoolModelOutput.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.ruoyi.iot.model.ThingsModelItem; - -public class BoolModelOutput extends ThingsModelItemBase -{ - private String falseText; - private String trueText; - - public String getFalseText() { - return falseText; - } - - public void setFalseText(String falseText) { - this.falseText = falseText; - } - - public String getTrueText() { - return trueText; - } - - public void setTrueText(String trueText) { - this.trueText = trueText; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/DecimalModelOutput.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/DecimalModelOutput.java deleted file mode 100644 index d8ff3145..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/DecimalModelOutput.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.ruoyi.iot.model.ThingsModelItem; - -import java.math.BigDecimal; - -public class DecimalModelOutput extends ThingsModelItemBase -{ - private BigDecimal min; - private BigDecimal max; - private BigDecimal step; - private String unit; - - public BigDecimal getMin() { - return min; - } - - public void setMin(BigDecimal min) { - this.min = min; - } - - public BigDecimal getMax() { - return max; - } - - public void setMax(BigDecimal max) { - this.max = max; - } - - public BigDecimal getStep() { - return step; - } - - public void setStep(BigDecimal step) { - this.step = step; - } - - public String getUnit() { - return unit; - } - - public void setUnit(String unit) { - this.unit = unit; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/EnumItemOutput.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/EnumItemOutput.java deleted file mode 100644 index 7a9b25c4..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/EnumItemOutput.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.ruoyi.iot.model.ThingsModelItem; - -public class EnumItemOutput -{ - private String text; - private String value; - - public String getText() { - return text; - } - - public void setText(String text) { - this.text = text; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/EnumModelOutput.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/EnumModelOutput.java deleted file mode 100644 index 56e04c37..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/EnumModelOutput.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.ruoyi.iot.model.ThingsModelItem; - -import java.util.List; - -public class EnumModelOutput extends ThingsModelItemBase -{ - private List enumList; - - public List getEnumList() { - return enumList; - } - - public void setEnumList(List enumList) { - this.enumList = enumList; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/IntegerModelOutput.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/IntegerModelOutput.java deleted file mode 100644 index 4d6a30f1..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/IntegerModelOutput.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.ruoyi.iot.model.ThingsModelItem; - -import java.math.BigDecimal; - -public class IntegerModelOutput extends ThingsModelItemBase -{ - private BigDecimal min; - private BigDecimal max; - private BigDecimal step; - private String unit; - - public BigDecimal getMin() { - return min; - } - - public void setMin(BigDecimal min) { - this.min = min; - } - - public BigDecimal getMax() { - return max; - } - - public void setMax(BigDecimal max) { - this.max = max; - } - - public BigDecimal getStep() { - return step; - } - - public void setStep(BigDecimal step) { - this.step = step; - } - - public String getUnit() { - return unit; - } - - public void setUnit(String unit) { - this.unit = unit; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/ReadOnlyModelOutput.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/ReadOnlyModelOutput.java deleted file mode 100644 index 3da683d4..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/ReadOnlyModelOutput.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.ruoyi.iot.model.ThingsModelItem; - -import java.math.BigDecimal; -import java.util.List; - -public class ReadOnlyModelOutput extends ThingsModelItemBase -{ - private BigDecimal min; - private BigDecimal max; - private BigDecimal step; - private String unit; - private String arrayType; - private String falseText; - private String trueText; - private int maxLength; - private List enumList; - - public List getEnumList() { - return enumList; - } - - public void setEnumList(List enumList) { - this.enumList = enumList; - } - - public int getMaxLength() { - return maxLength; - } - - public void setMaxLength(int maxLength) { - this.maxLength = maxLength; - } - - public String getFalseText() { - return falseText; - } - - public void setFalseText(String falseText) { - this.falseText = falseText; - } - - public String getTrueText() { - return trueText; - } - - public void setTrueText(String trueText) { - this.trueText = trueText; - } - - public String getArrayType() { - return arrayType; - } - - public void setArrayType(String arrayType) { - this.arrayType = arrayType; - } - - public BigDecimal getMin() { - return min; - } - - public void setMin(BigDecimal min) { - this.min = min; - } - - public BigDecimal getMax() { - return max; - } - - public void setMax(BigDecimal max) { - this.max = max; - } - - public BigDecimal getStep() { - return step; - } - - public void setStep(BigDecimal step) { - this.step = step; - } - - public String getUnit() { - return unit; - } - - public void setUnit(String unit) { - this.unit = unit; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/StringModelOutput.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/StringModelOutput.java deleted file mode 100644 index 2429a7b0..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/StringModelOutput.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.ruoyi.iot.model.ThingsModelItem; - -public class StringModelOutput extends ThingsModelItemBase -{ - private int maxLength; - - public int getMaxLength() { - return maxLength; - } - - public void setMaxLength(int maxLength) { - this.maxLength = maxLength; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/ThingsModelItemBase.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/ThingsModelItemBase.java deleted file mode 100644 index 6efcf555..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModelItem/ThingsModelItemBase.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.ruoyi.iot.model.ThingsModelItem; - -import com.ruoyi.common.annotation.Excel; - -public class ThingsModelItemBase -{ - /** 物模型唯一标识符 */ - private String id; - /** 物模型名称 */ - private String name; - /** 物模型值 */ - private String value; - /** 是否首页显示(0-否,1-是) */ - private Integer isTop; - /** 是否实时监测(0-否,1-是) */ - private Integer isMonitor; - /** 数据类型 */ - private String type; - /** 影子值 */ - private String shadow; - - public String getShadow() { - return shadow; - } - - public void setShadow(String shadow) { - this.shadow = shadow; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public Integer getIsTop() { - return isTop; - } - - public void setIsTop(Integer isTop) { - this.isTop = isTop; - } - - public Integer getIsMonitor() { - return isMonitor; - } - - public void setIsMonitor(Integer isMonitor) { - this.isMonitor = isMonitor; - } - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/EventDto.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/EventDto.java deleted file mode 100644 index a345bf00..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/EventDto.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.ruoyi.iot.model.ThingsModels; - -import com.alibaba.fastjson.JSONObject; - -import java.util.List; - -/** - * 产品分类的Id和名称输出 - * - * @author kerwincui - * @date 2021-12-16 - */ -public class EventDto -{ - /** 物模型唯一标识符 */ - private String id; - /** 物模型名称 */ - private String name; - /** 数据定义 */ - private JSONObject datatype; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public JSONObject getDatatype() { - return datatype; - } - - public void setDatatype(JSONObject datatype) { - this.datatype = datatype; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/FunctionDto.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/FunctionDto.java deleted file mode 100644 index def54f02..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/FunctionDto.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.ruoyi.iot.model.ThingsModels; - -import com.alibaba.fastjson.JSONObject; - -import java.util.List; - -/** - * 产品分类的Id和名称输出 - * - * @author kerwincui - * @date 2021-12-16 - */ -public class FunctionDto -{ - /** 物模型唯一标识符 */ - private String id; - /** 物模型名称 */ - private String name; - /** 是否首页显示(0-否,1-是) */ - private Integer isTop; - /** 数据定义 */ - private JSONObject datatype; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Integer getIsTop() { - return isTop; - } - - public void setIsTop(Integer isTop) { - this.isTop = isTop; - } - - public JSONObject getDatatype() { - return datatype; - } - - public void setDatatype(JSONObject datatype) { - this.datatype = datatype; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/IdentityAndName.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/IdentityAndName.java deleted file mode 100644 index 5cd7e64a..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/IdentityAndName.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.ruoyi.iot.model.ThingsModels; - -import org.apache.commons.math3.analysis.function.Identity; - -/** - * 物模型值的项 - * - * @author kerwincui - * @date 2021-12-16 - */ -public class IdentityAndName -{ - public IdentityAndName(){ - - } - - public IdentityAndName(String id,String value){ - this.id=id; - this.value=value; - } - - /** 物模型唯一标识符 */ - private String id; - - /** 物模型值 */ - private String value; - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/PropertyDto.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/PropertyDto.java deleted file mode 100644 index fb61538f..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/PropertyDto.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.ruoyi.iot.model.ThingsModels; - -import com.alibaba.fastjson.JSONObject; - -import java.util.List; - -/** - * 产品分类的Id和名称输出 - * - * @author kerwincui - * @date 2021-12-16 - */ -public class PropertyDto -{ - /** 物模型唯一标识符 */ - private String id; - /** 物模型名称 */ - private String name; - /** 是否首页显示(0-否,1-是) */ - private Integer isTop; - /** 是否实时监测(0-否,1-是) */ - private Integer isMonitor; - /** 数据定义 */ - private JSONObject datatype; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Integer getIsTop() { - return isTop; - } - - public void setIsTop(Integer isTop) { - this.isTop = isTop; - } - - public Integer getIsMonitor() { - return isMonitor; - } - - public void setIsMonitor(Integer isMonitor) { - this.isMonitor = isMonitor; - } - - public JSONObject getDatatype() { - return datatype; - } - - public void setDatatype(JSONObject datatype) { - this.datatype = datatype; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/ThingsModelShadow.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/ThingsModelShadow.java deleted file mode 100644 index 6b58d8bc..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/ThingsModelShadow.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.ruoyi.iot.model.ThingsModels; - -import java.util.ArrayList; -import java.util.List; - -/** - * 产品分类的Id和名称输出 - * - * @author kerwincui - * @date 2021-12-16 - */ -public class ThingsModelShadow -{ - public ThingsModelShadow(){ - this.properties=new ArrayList<>(); - this.functions=new ArrayList<>(); - } - - public ThingsModelShadow(List properties, List functions){ - this.properties=properties; - this.functions=functions; - } - - /** 属性 */ - List properties; - - /** 功能 */ - List functions; - - public List getProperties() { - return properties; - } - - public void setProperties(List properties) { - this.properties = properties; - } - - public List getFunctions() { - return functions; - } - - public void setFunctions(List functions) { - this.functions = functions; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/ThingsModelValueItem.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/ThingsModelValueItem.java deleted file mode 100644 index 89c95185..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/ThingsModelValueItem.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.ruoyi.iot.model.ThingsModels; - -/** - * 物模型值的项 - * - * @author kerwincui - * @date 2021-12-16 - */ -public class ThingsModelValueItem -{ - /** 物模型唯一标识符 */ - private String id; - - /** 物模型值 */ - private String value; - - /** 影子值 **/ - private String shadow; - - public String getShadow() { - return shadow; - } - - public void setShadow(String shadow) { - this.shadow = shadow; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/ThingsModelValueItemDto.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/ThingsModelValueItemDto.java deleted file mode 100644 index 0ea0d0c9..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/ThingsModelValueItemDto.java +++ /dev/null @@ -1,196 +0,0 @@ -package com.ruoyi.iot.model.ThingsModels; - -import org.springframework.data.redis.connection.DataType; - -import java.math.BigDecimal; -import java.util.List; - -/** - * 物模型 - * - * @author kerwincui - * @date 2021-12-16 - */ -public class ThingsModelValueItemDto -{ - /** 物模型唯一标识符 */ - private String id; - - /** 物模型名称 */ - private String name; - - /** 物模型值 */ - private String value; - - /** 是否首页显示(0-否,1-是) */ - private Integer isTop; - - /** 是否实时监测(0-否,1-是) */ - private Integer isMonitor; - - private DataType dataType; - - public Integer getIsTop() { - return isTop; - } - - public void setIsTop(Integer isTop) { - this.isTop = isTop; - } - - public Integer getIsMonitor() { - return isMonitor; - } - - public void setIsMonitor(Integer isMonitor) { - this.isMonitor = isMonitor; - } - - public DataType getDataType() { - return dataType; - } - - public void setDataType(DataType dataType) { - this.dataType = dataType; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public static class DataType{ - private String type; - private String falseText; - private String trueText; - private Integer maxLength; - private String arrayType; - private String unit; - private BigDecimal min; - private BigDecimal max; - private BigDecimal step; - private List enumList; - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getFalseText() { - return falseText; - } - - public void setFalseText(String falseText) { - this.falseText = falseText; - } - - public String getTrueText() { - return trueText; - } - - public void setTrueText(String trueText) { - this.trueText = trueText; - } - - public Integer getMaxLength() { - return maxLength; - } - - public void setMaxLength(Integer maxLength) { - this.maxLength = maxLength; - } - - public String getArrayType() { - return arrayType; - } - - public void setArrayType(String arrayType) { - this.arrayType = arrayType; - } - - public String getUnit() { - return unit; - } - - public void setUnit(String unit) { - this.unit = unit; - } - - public BigDecimal getMin() { - return min; - } - - public void setMin(BigDecimal min) { - this.min = min; - } - - public BigDecimal getMax() { - return max; - } - - public void setMax(BigDecimal max) { - this.max = max; - } - - public BigDecimal getStep() { - return step; - } - - public void setStep(BigDecimal step) { - this.step = step; - } - - public List getEnumList() { - return enumList; - } - - public void setEnumList(List enumList) { - this.enumList = enumList; - } - } - - public static class EnumItem - { - private String text; - private String value; - - public String getText() { - return text; - } - - public void setText(String text) { - this.text = text; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - } - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/ThingsModelValueRemarkItem.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/ThingsModelValueRemarkItem.java deleted file mode 100644 index a633c7a2..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/ThingsModelValueRemarkItem.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.ruoyi.iot.model.ThingsModels; - -import com.alibaba.fastjson.JSONObject; - -/** - * 物模型值的项 - * - * @author kerwincui - * @date 2021-12-16 - */ -public class ThingsModelValueRemarkItem -{ - /** 物模型唯一标识符 */ - private String id; - - /** 物模型值 */ - private String value; - - /** 备注 **/ - private String remark; - - public String getRemark() { - return remark; - } - - public void setRemark(String remark) { - this.remark = remark; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/ThingsModelValuesInput.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/ThingsModelValuesInput.java deleted file mode 100644 index 3011f470..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/ThingsModelValuesInput.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.ruoyi.iot.model.ThingsModels; - -import java.util.List; - -/** - * 设备输入物模型值参数 - * - * @author kerwincui - * @date 2021-12-16 - */ -public class ThingsModelValuesInput -{ - /** 产品ID **/ - private Long productId; - - private Long deviceId; - - /** 设备ID **/ - private String deviceNumber; - - /** 设备物模型值的字符串格式 **/ - private String stringValue; - - /** 设备物模型值的集合 **/ - private List thingsModelValueRemarkItem; - - public Long getDeviceId() { - return deviceId; - } - - public void setDeviceId(Long deviceId) { - this.deviceId = deviceId; - } - - public Long getProductId() { - return productId; - } - - public void setProductId(Long productId) { - this.productId = productId; - } - - public String getStringValue() { - return stringValue; - } - - public void setStringValue(String stringValue) { - this.stringValue = stringValue; - } - - public String getDeviceNumber() { - return deviceNumber; - } - - public void setDeviceNumber(String deviceNumber) { - this.deviceNumber = deviceNumber; - } - - public List getThingsModelValueRemarkItem() { - return thingsModelValueRemarkItem; - } - - public void setThingsModelValueRemarkItem(List thingsModelValueRemarkItem) { - this.thingsModelValueRemarkItem = thingsModelValueRemarkItem; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/ThingsModelValuesOutput.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/ThingsModelValuesOutput.java deleted file mode 100644 index 942acfce..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/ThingsModelValuesOutput.java +++ /dev/null @@ -1,139 +0,0 @@ -package com.ruoyi.iot.model.ThingsModels; - -import com.ruoyi.common.annotation.Excel; - -/** - * 设备输入物模型值参数 - * - * @author kerwincui - * @date 2021-12-16 - */ -public class ThingsModelValuesOutput -{ - /** 产品ID **/ - private Long productId; - - private String productName; - - private Long deviceId; - - private String deviceName; - - private int status; - - private int isShadow; - - /** 设备ID **/ - private String serialNumber; - - /** 用户ID */ - private Long userId; - - /** 用户昵称 */ - private String userName; - - /** 租户ID */ - private Long tenantId; - - /** 租户名称 */ - private String tenantName; - - /** 设备物模型值 **/ - private String thingsModelValue; - - public Long getUserId() { - return userId; - } - - public void setUserId(Long userId) { - this.userId = userId; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public Long getTenantId() { - return tenantId; - } - - public void setTenantId(Long tenantId) { - this.tenantId = tenantId; - } - - public String getTenantName() { - return tenantName; - } - - public void setTenantName(String tenantName) { - this.tenantName = tenantName; - } - - public int getIsShadow() { - return isShadow; - } - - public void setIsShadow(int isShadow) { - this.isShadow = isShadow; - } - - public int getStatus() { - return status; - } - - public void setStatus(int status) { - this.status = status; - } - - public Long getProductId() { - return productId; - } - - public void setProductId(Long productId) { - this.productId = productId; - } - - public String getProductName() { - return productName; - } - - public void setProductName(String productName) { - this.productName = productName; - } - - public Long getDeviceId() { - return deviceId; - } - - public void setDeviceId(Long deviceId) { - this.deviceId = deviceId; - } - - public String getDeviceName() { - return deviceName; - } - - public void setDeviceName(String deviceName) { - this.deviceName = deviceName; - } - - public String getSerialNumber() { - return serialNumber; - } - - public void setSerialNumber(String serialNumber) { - this.serialNumber = serialNumber; - } - - public String getThingsModelValue() { - return thingsModelValue; - } - - public void setThingsModelValue(String thingsModelValue) { - this.thingsModelValue = thingsModelValue; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/ThingsModelsDto.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/ThingsModelsDto.java deleted file mode 100644 index 5236ab19..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/ThingsModels/ThingsModelsDto.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.ruoyi.iot.model.ThingsModels; - -import java.util.ArrayList; -import java.util.List; - -/** - * 产品分类的Id和名称输出 - * - * @author kerwincui - * @date 2021-12-16 - */ -public class ThingsModelsDto -{ - public ThingsModelsDto(){ - properties=new ArrayList<>(); - functions=new ArrayList<>(); - events=new ArrayList<>(); - } - - /** 属性 */ - private List properties; - /** 功能 */ - private List functions; - /** 事件 */ - private List events; - - public List getProperties() { - return properties; - } - - public void setProperties(List properties) { - this.properties = properties; - } - - public List getFunctions() { - return functions; - } - - public void setFunctions(List functions) { - this.functions = functions; - } - - public List getEvents() { - return events; - } - - public void setEvents(List events) { - this.events = events; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/UserIdDeviceIdModel.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/UserIdDeviceIdModel.java deleted file mode 100644 index 7ba75b9d..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/UserIdDeviceIdModel.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.ruoyi.iot.model; - -/** - * 用户ID和设备ID模型 - * - * @author kerwincui - * @date 2021-12-16 - */ -public class UserIdDeviceIdModel -{ - private Long userId; - - private Long deviceId; - - public UserIdDeviceIdModel(Long userId, Long deviceId){ - this.userId=userId; - this.deviceId=deviceId; - } - - - public Long getUserId() { - return userId; - } - - public void setUserId(Long userId) { - this.userId = userId; - } - - public Long getDeviceId() { - return deviceId; - } - - public void setDeviceId(Long deviceId) { - this.deviceId = deviceId; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/login/AuthRequestWrap.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/login/AuthRequestWrap.java deleted file mode 100644 index f37b7b38..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/login/AuthRequestWrap.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.ruoyi.iot.model.login; - -import com.ruoyi.iot.domain.SocialPlatform; -import me.zhyd.oauth.request.AuthRequest; - -public class AuthRequestWrap { - private AuthRequest authRequest; - - private SocialPlatform socialPlatform; - - public AuthRequest getAuthRequest() { - return authRequest; - } - - public void setAuthRequest(AuthRequest authRequest) { - this.authRequest = authRequest; - } - - public SocialPlatform getSocialPlatform() { - return socialPlatform; - } - - public void setSocialPlatform(SocialPlatform socialPlatform) { - this.socialPlatform = socialPlatform; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/login/BindIdValue.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/login/BindIdValue.java deleted file mode 100644 index b3e3e9c6..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/login/BindIdValue.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.ruoyi.iot.model.login; - -public class BindIdValue { - - private String uuid; - private String source; - - public String getSource() { - return source; - } - - public void setSource(String source) { - this.source = source; - } - - public String getUuid() { - return uuid; - } - - public void setUuid(String uuid) { - this.uuid = uuid; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/login/LoginIdValue.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/login/LoginIdValue.java deleted file mode 100644 index b348ed58..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/login/LoginIdValue.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.ruoyi.iot.model.login; - -public class LoginIdValue { - String username; - String password; - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mqtt/EmqxCallback.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mqtt/EmqxCallback.java deleted file mode 100644 index b08864db..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mqtt/EmqxCallback.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.ruoyi.iot.mqtt; - -import com.ruoyi.framework.web.domain.server.Sys; -import org.eclipse.paho.client.mqttv3.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Lazy; -import org.springframework.stereotype.Component; - -/** - * @Classname MqttCallback - * @Description 消费监听类 - */ -@Component -public class EmqxCallback implements MqttCallbackExtended { - private static final Logger logger = LoggerFactory.getLogger(EmqxCallback.class); - - @Autowired - private EmqxClient emqxClient; - - @Lazy - @Autowired - private EmqxService emqxService; - - @Override - public void connectionLost(Throwable throwable) { - logger.info("mqtt断开连接--"); - - } - - - - @Override - public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception { - emqxService.subscribeCallback(topic,mqttMessage); - } - - /** - * 发布消息后,到达MQTT服务器,服务器回调消息接收 - * @param iMqttDeliveryToken - */ - @Override - public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) { - // 消息到达 MQTT 代理时触发的事件 - } - - /** - * 监听mqtt连接消息 - * @param reconnect - * @param serverURI - */ - @Override - public void connectComplete(boolean reconnect, String serverURI) { - logger.info("mqtt已经连接!!"); - //连接后,可以在此做初始化事件,或订阅 - try { - emqxService.subscribe(EmqxClient.client); - } catch (MqttException e) { - logger.error("======>>>>>订阅主题失败 error={}",e.getMessage()); - } - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mqtt/EmqxClient.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mqtt/EmqxClient.java deleted file mode 100644 index c6e9ef31..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mqtt/EmqxClient.java +++ /dev/null @@ -1,201 +0,0 @@ -package com.ruoyi.iot.mqtt; - -import com.ruoyi.common.exception.ServiceException; -import org.eclipse.paho.client.mqttv3.*; -import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -/** - * @Classname EmqxClient - * @Description mqtt推送客户端 - */ -//@Component -public class EmqxClient { - private static final Logger logger = LoggerFactory.getLogger(EmqxClient.class); - - @Autowired - private EmqxCallback emqxCallback; - - @Autowired - private EmqxService emqxService; - - /**MQTT异步客户端*/ - public static MqttAsyncClient client; - - /**连接配置*/ - private MqttConnectOptions options; - - /**服务器地址url*/ - private String hostname; - - /**超时时间*/ - private int timeout; - - /**包活时间*/ - private int keepalive; - - /**客户端唯一ID*/ - private String clientId; - - /**用户名*/ - private String username; - - /**密码*/ - private String password; - - /**是否清除会话*/ - private boolean clearSession; - - public EmqxClient(String clientId,String username,String password,String hostname, - int timeout,int keepalive,boolean clearSession){ - this.clientId = clientId; - this.username = username; - this.password = password; - this.hostname = hostname; - this.timeout = timeout; - this.keepalive = keepalive; - this.clearSession = clearSession; - } - - - /** - * 连接MQTT服务器 - */ - public synchronized void connect(){ - - /*设置配置*/ - if (options == null){ - setOptions(); - } - if (client == null){ - createClient(); - } - while (!client.isConnected()){ - try { - IMqttToken token = client.connect(options); - token.waitForCompletion(); - }catch (Exception e){ - logger.error("=====>>>>>mqtt连接失败 message={}",e.getMessage()); - e.printStackTrace(); - } - } - } - - /** - * 创建客户端 - */ - private void createClient(){ - if (client == null){ - try { - /*host为主机名,clientId是连接MQTT的客户端ID,MemoryPersistence设置clientId的保存方式 - 默认是以内存方式保存*/ - client = new MqttAsyncClient(hostname,clientId,new MemoryPersistence()); - //设置回调函数 - client.setCallback(emqxCallback); - logger.debug("====>>>mqtt客户端启动成功"); - }catch (MqttException e){ - logger.error("mqtt客户端连接错误 error={}",e.getMessage()); - e.printStackTrace(); - } - } - } - - /** - * 设置连接属性 - */ - private void setOptions(){ - if (options != null){ - options = null; - } - options = new MqttConnectOptions(); - options.setUserName(username); - options.setPassword(password.toCharArray()); - options.setConnectionTimeout(timeout); - options.setKeepAliveInterval(keepalive); - //设置自动重新连接 - options.setAutomaticReconnect(true); - options.setCleanSession(clearSession); - logger.debug("====>>>>设置mqtt参数成功"); - } - - /** - * 断开与mqtt的连接 - */ - public synchronized void disconnect(){ - //判断客户端是否null 是否连接 - if (client != null && client.isConnected()){ - try { - IMqttToken token = client.disconnect(); - token.waitForCompletion(); - }catch (MqttException e){ - logger.error("====>>>>断开mqtt连接发生错误 message={}",e.getMessage()); - } - } - client = null; - } - - /** - * 重新连接MQTT - */ - public synchronized void refresh(){ - disconnect(); - setOptions(); - createClient(); - connect(); - } - - - - - /** - * 发布 - * @param qos 连接方式 - * @param retained 是否保留 - * @param topic 主题 - * @param pushMessage 消息体 - */ - public void publish(int qos, boolean retained, String topic, String pushMessage) { - logger.info("发布主题" + topic); - MqttMessage message = new MqttMessage(); - message.setQos(qos); - message.setRetained(retained); - message.setPayload(pushMessage.getBytes()); - - try { - IMqttDeliveryToken token = client.publish(topic,message); - token.waitForCompletion(); - } catch (MqttPersistenceException e) { - e.printStackTrace(); - } catch (MqttException e) { - logger.error("=======>>>>>发布主题时发生错误 topic={},message={}",topic,e.getMessage()); - } - } - - /** - * 订阅某个主题 - * @param topic 主题 - * @param qos 消息质量 - * Qos1:消息发送一次,不确保 - * Qos2:至少分发一次,服务器确保接收消息进行确认 - * Qos3:只分发一次,确保消息送达和只传递一次 - */ - public void subscribe(String topic, int qos){ - logger.info("=======>>>>>订阅了主题 topic={}",topic); - try { - IMqttToken token = client.subscribe(topic, qos); - token.waitForCompletion(); - }catch (MqttException e){ - logger.error("=======>>>>>订阅主题 topic={} 失败 message={}",topic,e.getMessage()); - } - } - - /**是否处于连接状态*/ - public boolean isConnected(){ - return client != null && client.isConnected(); - } - - public String getClientId() {return clientId;}; -} \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mqtt/EmqxService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mqtt/EmqxService.java deleted file mode 100644 index 02dbf699..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mqtt/EmqxService.java +++ /dev/null @@ -1,283 +0,0 @@ -package com.ruoyi.iot.mqtt; - -import com.alibaba.fastjson.JSON; -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.iot.domain.Device; -import com.ruoyi.iot.domain.DeviceLog; -import com.ruoyi.iot.model.NtpModel; -import com.ruoyi.iot.model.ThingsModels.IdentityAndName; -import com.ruoyi.iot.model.ThingsModels.ThingsModelValueItem; -import com.ruoyi.iot.model.ThingsModels.ThingsModelValueRemarkItem; -import com.ruoyi.iot.model.ThingsModels.ThingsModelValuesInput; -import com.ruoyi.iot.service.IDeviceLogService; -import com.ruoyi.iot.service.IDeviceService; -import com.ruoyi.iot.tdengine.service.ILogService; -import org.eclipse.paho.client.mqttv3.MqttAsyncClient; -import org.eclipse.paho.client.mqttv3.MqttClient; -import org.eclipse.paho.client.mqttv3.MqttException; -import org.eclipse.paho.client.mqttv3.MqttMessage; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.scheduling.annotation.Async; -import org.springframework.stereotype.Service; - -import java.util.List; - -@Service -public class EmqxService { - private static final Logger logger = LoggerFactory.getLogger(EmqxService.class); - - @Autowired - private EmqxClient emqxClient; - - @Autowired - private IDeviceService deviceService; - - @Autowired - private ILogService logService; - - /** - * 订阅的主题 - */ - private static final String prefix = "/+/+/"; - String sInfoTopic = prefix + "info/post"; - String sNtpTopic = prefix + "ntp/post"; - String sPropertyTopic = prefix + "property/post"; - String sFunctionTopic = prefix + "function/post"; - String sEventTopic = prefix + "event/post"; - String sShadowPropertyTopic = prefix + "property-offline/post"; - String sShadowFunctionTopic = prefix + "function-offline/post"; - - /** - * 发布的主题 - */ - String pStatusTopic = "/status/post"; - String pInfoTopic = "/info/get"; - String pNtpTopic = "/ntp/get"; - String pPropertyTopic = "/property/get"; - String pFunctionTopic = "/function/get"; - - public void subscribe(MqttAsyncClient client) throws MqttException { - // 订阅设备信息 - client.subscribe(sInfoTopic, 1); - // 订阅时钟同步 - client.subscribe(sNtpTopic, 1); - // 订阅设备属性 - client.subscribe(sPropertyTopic, 1); - // 订阅设备功能 - client.subscribe(sFunctionTopic, 1); - // 订阅设备事件 - client.subscribe(sEventTopic, 1); - // 订阅属性(影子模式) - client.subscribe(sShadowPropertyTopic, 1); - // 订阅功能(影子模式) - client.subscribe(sShadowFunctionTopic, 1); - logger.info("mqtt订阅了设备信息和物模型主题"); - } - - /** - * 消息回调方法 - * @param topic 主题 - * @param mqttMessage 消息体 - */ - @Async - public void subscribeCallback(String topic, MqttMessage mqttMessage) throws InterruptedException { - - /**测试线程池使用*/ - logger.info("====>>>>线程名--{}",Thread.currentThread().getName()); - /**模拟耗时操作*/ - // Thread.sleep(1000); - // subscribe后得到的消息会执行到这里面 - String message = new String(mqttMessage.getPayload()); - logger.info("接收消息主题 : " + topic); - logger.info("接收消息Qos : " + mqttMessage.getQos()); - logger.info("接收消息内容 : " + message); - - String[] topicItem = topic.substring(1).split("/"); - Long productId = Long.valueOf(topicItem[0]); - String deviceNum = topicItem[1]; - String name = topicItem[2]; - switch (name) { - case "info": - reportDevice(productId, deviceNum, message); - break; - case "ntp": - publishNtp(productId, deviceNum, message); - break; - case "property": - reportProperty(productId, deviceNum, message, false); - break; - case "function": - reportFunction(productId, deviceNum, message, false); - break; - case "event": - reportEvent(productId, deviceNum, message); - break; - case "property-offline": - reportProperty(productId, deviceNum, message, true); - break; - case "function-offline": - reportFunction(productId, deviceNum, message, true); - break; - } - } - - /** - * 上报设备信息 - */ - private void reportDevice(Long productId, String deviceNum, String message) { - try { - // 设备实体 - Device deviceEntity=deviceService.selectDeviceBySerialNumber(deviceNum); - // 上报设备信息 - Device device = JSON.parseObject(message, Device.class); - device.setProductId(productId); - device.setSerialNumber(deviceNum); - deviceService.reportDevice(device,deviceEntity); - // 发布设备状态 - publishStatus(productId, deviceNum, 3, deviceEntity.getIsShadow(),device.getRssi()); - } catch (Exception e) { - logger.error("接收设备信息,解析数据时异常 message={}", e.getMessage()); - } - } - - /** - * 上报属性 - * - * @param message - */ - private void reportProperty(Long productId, String deviceNum, String message, boolean isShadow) { - try { - List thingsModelValueRemarkItems = JSON.parseArray(message, ThingsModelValueRemarkItem.class); - ThingsModelValuesInput input = new ThingsModelValuesInput(); - input.setProductId(productId); - input.setDeviceNumber(deviceNum); - input.setThingsModelValueRemarkItem(thingsModelValueRemarkItems); - deviceService.reportDeviceThingsModelValue(input, 1, isShadow); - } catch (Exception e) { - logger.error("接收属性数据,解析数据时异常 message={}", e.getMessage()); - } - } - - /** - * 上报功能 - * - * @param message - */ - private void reportFunction(Long productId, String deviceNum, String message, boolean isShadow) { - try { - List thingsModelValueRemarkItems = JSON.parseArray(message, ThingsModelValueRemarkItem.class); - ThingsModelValuesInput input = new ThingsModelValuesInput(); - input.setProductId(productId); - input.setDeviceNumber(deviceNum); - input.setThingsModelValueRemarkItem(thingsModelValueRemarkItems); - deviceService.reportDeviceThingsModelValue(input, 2, isShadow); - } catch (Exception e) { - logger.error("接收功能,解析数据时异常 message={}", e.getMessage()); - } - } - - /** - * 上报事件 - * - * @param message - */ - private void reportEvent(Long productId, String deviceNum, String message) { - try { - List thingsModelValueRemarkItems = JSON.parseArray(message, ThingsModelValueRemarkItem.class); - Device device = deviceService.selectDeviceBySerialNumber(deviceNum); - for (int i = 0; i < thingsModelValueRemarkItems.size(); i++) { - // 添加到设备日志 - DeviceLog deviceLog = new DeviceLog(); - deviceLog.setDeviceId(device.getDeviceId()); - deviceLog.setDeviceName(device.getDeviceName()); - deviceLog.setLogValue(thingsModelValueRemarkItems.get(i).getValue()); - deviceLog.setRemark(thingsModelValueRemarkItems.get(i).getRemark()); - deviceLog.setSerialNumber(device.getSerialNumber()); - deviceLog.setIdentity(thingsModelValueRemarkItems.get(i).getId()); - deviceLog.setLogType(3); - deviceLog.setIsMonitor(0); - deviceLog.setUserId(device.getUserId()); - deviceLog.setUserName(device.getUserName()); - deviceLog.setTenantId(device.getTenantId()); - deviceLog.setTenantName(device.getTenantName()); - deviceLog.setCreateTime(DateUtils.getNowDate()); - // 1=影子模式,2=在线模式,3=其他 - deviceLog.setMode(2); - logService.saveDeviceLog(deviceLog); - } - } catch (Exception e) { - logger.error("接收事件,解析数据时异常 message={}", e.getMessage()); - } - } - - - /** - * 1.发布设备状态 - */ - public void publishStatus(Long productId, String deviceNum, int deviceStatus, int isShadow,int rssi) { - String message = "{\"status\":" + deviceStatus + ",\"isShadow\":" + isShadow + ",\"rssi\":" + rssi + "}"; - emqxClient.publish(1, false, "/" + productId + "/" + deviceNum + pStatusTopic, message); - } - - /** - * 2.发布设备信息 - */ - public void publishInfo(Long productId, String deviceNum) { - emqxClient.publish(1, false, "/" + productId + "/" + deviceNum + pInfoTopic, ""); - } - - /** - * 3.发布时钟同步信息 - * - * @param message - */ - private void publishNtp(Long productId, String deviceNum, String message) { - NtpModel ntpModel = JSON.parseObject(message, NtpModel.class); - ntpModel.setServerRecvTime(System.currentTimeMillis()); - ntpModel.setServerSendTime(System.currentTimeMillis()); - emqxClient.publish(1, false, "/" + productId + "/" + deviceNum + pNtpTopic, JSON.toJSONString(ntpModel)); - } - - /** - * 4.发布属性 - */ - public void publishProperty(Long productId, String deviceNum, List thingsList) { - if (thingsList == null) { - emqxClient.publish(1, true, "/" + productId + "/" + deviceNum + pPropertyTopic, ""); - } else { - emqxClient.publish(1, true, "/" + productId + "/" + deviceNum + pPropertyTopic, JSON.toJSONString(thingsList)); - } - } - - /** - * 5.发布功能 - */ - public void publishFunction(Long productId, String deviceNum, List thingsList) { - if (thingsList == null) { - emqxClient.publish(1, true, "/" + productId + "/" + deviceNum + pFunctionTopic, ""); - } else { - emqxClient.publish(1, true, "/" + productId + "/" + deviceNum + pFunctionTopic, JSON.toJSONString(thingsList)); - } - - } - - /** - * 设备数据同步 - * - * @param deviceNumber 设备编号 - * @return 设备 - */ - public Device deviceSynchronization(String deviceNumber) { - Device device=deviceService.selectDeviceBySerialNumber(deviceNumber); - // 1-未激活,2-禁用,3-在线,4-离线 - if(device.getStatus()==3){ - device.setStatus(4); - deviceService.updateDeviceStatus(device); - // 发布设备信息 - publishInfo(device.getProductId(),device.getSerialNumber()); - } - return device; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mqtt/EmqxStart.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mqtt/EmqxStart.java deleted file mode 100644 index fd2f2d0e..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mqtt/EmqxStart.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.ruoyi.iot.mqtt; - -import com.alibaba.fastjson.JSONObject; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.ApplicationArguments; -import org.springframework.boot.ApplicationRunner; -import org.springframework.core.annotation.Order; -import org.springframework.stereotype.Component; - -/** - *项目启动执行 - */ -@Component -@Order(value = 1) //执行顺序控制 -public class EmqxStart implements ApplicationRunner { - - @Autowired - private EmqxClient emqxClient; - - @Override - public void run(ApplicationArguments applicationArguments) throws Exception{ - emqxClient.connect(); - - /*模拟客户端发布主题,测试多线程处理订阅主题业务*/ - /** JSONObject message = new JSONObject(); - message.put("id",2); - message.put("value","hello"); - message.put("remark","12"); - Thread.sleep(10000); - new Thread(() ->{ - for (int i = 0; i < 3000; i++) { - emqxClient.publish(0,false,"/2/D6329VL54419L1Y0/info/post",message.toJSONString()); - //测试多线程性能 - try { - Thread.sleep(300); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - }).start(); - */ - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mqtt/MqttClientConfiguration.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mqtt/MqttClientConfiguration.java deleted file mode 100644 index 25e3dbe1..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mqtt/MqttClientConfiguration.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.ruoyi.iot.mqtt; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class MqttClientConfiguration { - - @Autowired - private MqttConfig mqttConfig; - - @Bean - EmqxClient mqttClient(){ - EmqxClient client = new EmqxClient(mqttConfig.getclientId(), - mqttConfig.getusername(), - mqttConfig.getpassword(), - mqttConfig.gethostUrl(), - mqttConfig.gettimeout(), - mqttConfig.getkeepalive(), - mqttConfig.isClearSession() - ); - return client; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mqtt/MqttConfig.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mqtt/MqttConfig.java deleted file mode 100644 index 1542ef7d..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mqtt/MqttConfig.java +++ /dev/null @@ -1,123 +0,0 @@ -package com.ruoyi.iot.mqtt; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.stereotype.Component; - -/** - * @Classname MqttConfig - * @Description mqtt配置信息 - * @author kerwincui - */ -@Component -@ConfigurationProperties("spring.mqtt") -public class MqttConfig { - - private static final Logger logger = LoggerFactory.getLogger(MqttConfig.class); - - /** - * 用户名 - */ - private String username; - /** - * 密码 - */ - private String password; - /** - * 连接地址 - */ - private String hostUrl; - /** - * 客户Id - */ - private String clientId; - /** - * 默认连接话题 - */ - private String defaultTopic; - /** - * 超时时间 - */ - private int timeout; - /** - * 保持连接数 - */ - private int keepalive; - - /**是否清除session*/ - private boolean clearSession; - /**是否共享订阅*/ - private boolean isShared; - /**分组共享订阅*/ - private boolean isSharedGroup; - - - public String getusername() - { - return username; - } - public void setusername(String username) {this.username = username;} - - public String getpassword() - { - return password; - } - public void setpassword(String password) {this.password = password;} - - public String gethostUrl() - { - return hostUrl; - } - public void sethostUrl(String hostUrl) {this.hostUrl = hostUrl;} - - public String getclientId() - { - return "server-"+clientId; - } - public void setclientId(String clientId) {this.clientId = clientId;} - - public String getdefaultTopic() - { - return defaultTopic; - } - public void setdefaultTopic(String defaultTopic) {this.defaultTopic = defaultTopic;} - - public int gettimeout() - { - return timeout; - } - public void settimeout(int timeout) {this.timeout = timeout;} - - public int getkeepalive() - { - return keepalive; - } - public void setkeepalive(int keepalive) {this.keepalive = keepalive;} - - public boolean isClearSession() { - return clearSession; - } - - public void setClearSession(boolean clearSession) { - this.clearSession = clearSession; - } - - public boolean isShared() { - return isShared; - } - - public void setShared(boolean shared) { - isShared = shared; - } - - public boolean isSharedGroup() { - return isSharedGroup; - } - - public void setSharedGroup(boolean sharedGroup) { - isSharedGroup = sharedGroup; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/oauth/AuthorizationServerConfig.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/oauth/AuthorizationServerConfig.java deleted file mode 100644 index f07302b8..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/oauth/AuthorizationServerConfig.java +++ /dev/null @@ -1,119 +0,0 @@ -package com.ruoyi.iot.oauth; - - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; -import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; -import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; -import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; -import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; -import org.springframework.security.oauth2.provider.OAuth2RequestFactory; -import org.springframework.security.oauth2.provider.approval.ApprovalStore; -import org.springframework.security.oauth2.provider.approval.JdbcApprovalStore; -import org.springframework.security.oauth2.provider.approval.UserApprovalHandler; -import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService; -import org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices; -import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint; -import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; -import org.springframework.security.oauth2.provider.token.TokenStore; -import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore; - -import javax.sql.DataSource; - -/** - * 授权服务器配置,配置客户端id,密钥和令牌的过期时间 - */ -@Configuration -@EnableAuthorizationServer -public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { - @Autowired - private DataSource dataSource; - - @Autowired - private AuthenticationManager authenticationManager; - - @Autowired - private UserDetailsService userDetailsService; - - /** - * 用来配置令牌端点(Token Endpoint)的安全约束 - * @param security - * @throws Exception - */ - @Override - public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { - security.allowFormAuthenticationForClients() - .authenticationEntryPoint(new OAuth2AuthenticationEntryPoint()); - } - - /** - * 用来配置客户端详情服务 - * @param clients - * @throws Exception - */ - @Override - public void configure(ClientDetailsServiceConfigurer clients) throws Exception { - - clients.withClientDetails(getClientDetailsService()); - } - - /** - * 用来配置授权(authorization)以及令牌(token)的访问端点和令牌服务(token services)。 - * @param endpoints - * @throws Exception - */ - @Override - public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { - // 查询用户、授权、分组,可以被重写 - endpoints.userDetailsService(userDetailsService) - // 审批客户端的授权 - .userApprovalHandler(userApprovalHandler()) - // 授权审批 - .approvalStore(approvalStore()) - // 获取授权码 - .authorizationCodeServices(new JdbcAuthorizationCodeServices(dataSource)) - // 验证token - .authenticationManager(authenticationManager) - // 查询、保存、刷新token - .tokenStore(this.getJdbcTokenStore()); - } - - @Bean - public ApprovalStore approvalStore() { - return new JdbcApprovalStore(dataSource); - } - - @Bean - public UserApprovalHandler userApprovalHandler() { - return new SpeakerApprovalHandler(getClientDetailsService(), approvalStore(), oAuth2RequestFactory()); - } - - @Bean - public JdbcClientDetailsService getClientDetailsService() { - JdbcClientDetailsService jdbcClientDetailsService = new JdbcClientDetailsService(dataSource); - jdbcClientDetailsService.setPasswordEncoder(passwordEncoder()); - return jdbcClientDetailsService; - } - - @Bean - public OAuth2RequestFactory oAuth2RequestFactory() { - return new DefaultOAuth2RequestFactory(getClientDetailsService()); - } - @Bean - public TokenStore getJdbcTokenStore(){ - TokenStore tokenStore = new JdbcTokenStore(dataSource); - return tokenStore; - } - - - - public BCryptPasswordEncoder passwordEncoder(){ - return new BCryptPasswordEncoder(); - } - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/oauth/ResourceServerConfig.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/oauth/ResourceServerConfig.java deleted file mode 100644 index a97973c5..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/oauth/ResourceServerConfig.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.ruoyi.iot.oauth; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.annotation.Order; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; -import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; -import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; -import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationManager; -import org.springframework.security.oauth2.provider.token.TokenStore; -import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore; - -import javax.sql.DataSource; - -@Configuration -@EnableResourceServer -public class ResourceServerConfig extends ResourceServerConfigurerAdapter { - - @Autowired - private DataSource dataSource; - - @Override - public void configure(ResourceServerSecurityConfigurer resources) throws Exception { - TokenStore tokenStore = jdbcTokenStore(); - OAuth2AuthenticationManager auth2AuthenticationManager= new OAuth2AuthenticationManager(); - resources.authenticationManager(auth2AuthenticationManager); - resources.resourceId("speaker-service").tokenStore(tokenStore).stateless(true); - } - - @Override - public void configure(HttpSecurity http) throws Exception { - // 限制资源服务器只接管匹配的资源 - http.requestMatchers().antMatchers("/oauth/speaker/**") - .and() - //授权的请求 - .authorizeRequests() - .anyRequest().authenticated() - //关闭跨站请求防护 - .and() - .csrf().disable(); - } - - public TokenStore jdbcTokenStore(){ - TokenStore tokenStore = new JdbcTokenStore(dataSource); - return tokenStore; - } - -} \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/oauth/SpeakerApprovalHandler.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/oauth/SpeakerApprovalHandler.java deleted file mode 100644 index f6260371..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/oauth/SpeakerApprovalHandler.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.ruoyi.iot.oauth; - - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.common.util.OAuth2Utils; -import org.springframework.security.oauth2.provider.AuthorizationRequest; -import org.springframework.security.oauth2.provider.OAuth2RequestFactory; -import org.springframework.security.oauth2.provider.approval.Approval; -import org.springframework.security.oauth2.provider.approval.ApprovalStore; -import org.springframework.security.oauth2.provider.approval.ApprovalStoreUserApprovalHandler; -import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService; - -import java.util.*; - -/** - * kerwincui - */ -public class SpeakerApprovalHandler extends ApprovalStoreUserApprovalHandler { - - private int approvalExpirySeconds = -1; - - @Autowired - private ApprovalStore approvalStore; - - public SpeakerApprovalHandler(JdbcClientDetailsService clientDetailsService, ApprovalStore approvalStore, OAuth2RequestFactory oAuth2RequestFactory) { - this.setApprovalStore(approvalStore); - this.setClientDetailsService(clientDetailsService); - this.setRequestFactory(oAuth2RequestFactory); - } - - @Override - public AuthorizationRequest updateAfterApproval(AuthorizationRequest authorizationRequest, Authentication userAuthentication) { - // 获取授权过的范围 - Set requestedScopes = authorizationRequest.getScope(); - Set approvedScopes = new HashSet(); - Set approvals = new HashSet(); - Date expiry = computeExpiry(); - - // 存储授权或拒绝的范围 - Map approvalParameters = authorizationRequest.getApprovalParameters(); - for (String requestedScope : requestedScopes) { - String approvalParameter = OAuth2Utils.SCOPE_PREFIX + requestedScope; - String value = approvalParameters.get(approvalParameter); - value = value == null ? "" : value.toLowerCase(); - if ("true".equals(value) || value.startsWith("approve")||value.equals("on")) { - approvedScopes.add(requestedScope); - approvals.add(new Approval(userAuthentication.getName(), authorizationRequest.getClientId(), - requestedScope, expiry, Approval.ApprovalStatus.APPROVED)); - } - else { - approvals.add(new Approval(userAuthentication.getName(), authorizationRequest.getClientId(), - requestedScope, expiry, Approval.ApprovalStatus.DENIED)); - } - } - approvalStore.addApprovals(approvals); - - boolean approved; - authorizationRequest.setScope(approvedScopes); - if (approvedScopes.isEmpty() && !requestedScopes.isEmpty()) { - approved = false; - } - else { - approved = true; - } - authorizationRequest.setApproved(approved); - return authorizationRequest; - } - - private Date computeExpiry() { - Calendar expiresAt = Calendar.getInstance(); - // 默认一个月 - if (approvalExpirySeconds == -1) { - expiresAt.add(Calendar.MONTH, 1); - } - else { - expiresAt.add(Calendar.SECOND, approvalExpirySeconds); - } - return expiresAt.getTime(); - } - -} - diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/oauth/api/ConfirmAccessController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/oauth/api/ConfirmAccessController.java deleted file mode 100644 index afeb7386..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/oauth/api/ConfirmAccessController.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.ruoyi.iot.oauth.api; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.oauth2.common.util.OAuth2Utils; -import org.springframework.security.oauth2.provider.AuthorizationRequest; -import org.springframework.security.oauth2.provider.ClientDetails; -import org.springframework.security.oauth2.provider.approval.Approval; -import org.springframework.security.oauth2.provider.approval.ApprovalStore; -import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.SessionAttributes; - -import java.security.Principal; -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * kerwincui - */ -@Controller -@SessionAttributes("authorizationRequest") -public class ConfirmAccessController { - @Autowired - private JdbcClientDetailsService clientDetailsService; - @Autowired - private ApprovalStore approvalStore; - - @RequestMapping("/oauth/confirm_access") - public String getAccessConfirmation(Map model, Principal principal ) { - AuthorizationRequest clientAuth = (AuthorizationRequest) model.remove("authorizationRequest"); - ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId()); - - Map scopes = new LinkedHashMap(); - for (String scope : clientAuth.getScope()) { - scopes.put(OAuth2Utils.SCOPE_PREFIX + scope, "false"); - } - for (Approval approval : approvalStore.getApprovals(principal.getName(), client.getClientId())) { - if (clientAuth.getScope().contains(approval.getScope())) { - scopes.put(OAuth2Utils.SCOPE_PREFIX + approval.getScope(), - approval.getStatus() == Approval.ApprovalStatus.APPROVED ? "true" : "false"); - } - } - model.put("auth_request", clientAuth); - model.put("client", client); - model.put("scopes", scopes); - return "oauth/access_confirmation"; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/oauth/api/LoginController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/oauth/api/LoginController.java deleted file mode 100644 index aa1913eb..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/oauth/api/LoginController.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.ruoyi.iot.oauth.api; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.provider.token.TokenStore; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; - -@Controller -public class LoginController { - @Autowired - private TokenStore tokenStore; - - @RequestMapping("/oauth/login") - public String login() { - return "oauth/login"; - } - - @RequestMapping("/oauth/index") - public String index() { - return "oauth/index"; - } - - @GetMapping("/oauth/logout") - @ResponseBody - public String logout(@RequestHeader String Authorization) { - if (!Authorization.isEmpty()){ - String token=Authorization.split(" ")[1]; - OAuth2AccessToken auth2AccessToken = tokenStore.readAccessToken(token); - tokenStore.removeAccessToken(auth2AccessToken); - return "SUCCESS"; - }else{ - return "FAIL"; - } - - } -} \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/oauth/api/SpeakerController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/oauth/api/SpeakerController.java deleted file mode 100644 index 9c41e9b7..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/oauth/api/SpeakerController.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.ruoyi.iot.oauth.api; - -import com.alibaba.fastjson.JSONObject; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RestController; - -/** - * kerwincui - */ -@RestController -public class SpeakerController { - @GetMapping("/oauth/speaker/get") - public JSONObject getSpeaker() { -// Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - JSONObject Json = new JSONObject(); - Json.put("1", "1"); - Json.put("2", "2"); - Json.put("3", "3"); - System.out.println("调用了接口get"); - return Json; - } - @PostMapping("/oauth/speaker/post") - public JSONObject postSpeaker() { -// Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - JSONObject bookJson = new JSONObject(); - bookJson.put("1", "1"); - System.out.println("调用了接口post"); - return bookJson; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IAlertLogService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IAlertLogService.java deleted file mode 100644 index 984be858..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IAlertLogService.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.ruoyi.iot.service; - -import com.ruoyi.iot.domain.AlertLog; - -import java.util.List; - -/** - * 设备告警Service接口 - * - * @author kerwincui - * @date 2022-01-13 - */ -public interface IAlertLogService -{ - /** - * 查询设备告警 - * - * @param alertLogId 设备告警主键 - * @return 设备告警 - */ - public AlertLog selectAlertLogByAlertLogId(Long alertLogId); - - /** - * 查询设备告警列表 - * - * @param alertLog 设备告警 - * @return 设备告警集合 - */ - public List selectAlertLogList(AlertLog alertLog); - - /** - * 新增设备告警 - * - * @param alertLog 设备告警 - * @return 结果 - */ - public int insertAlertLog(AlertLog alertLog); - - /** - * 修改设备告警 - * - * @param alertLog 设备告警 - * @return 结果 - */ - public int updateAlertLog(AlertLog alertLog); - - /** - * 批量删除设备告警 - * - * @param alertLogIds 需要删除的设备告警主键集合 - * @return 结果 - */ - public int deleteAlertLogByAlertLogIds(Long[] alertLogIds); - - /** - * 删除设备告警信息 - * - * @param alertLogId 设备告警主键 - * @return 结果 - */ - public int deleteAlertLogByAlertLogId(Long alertLogId); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IAlertService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IAlertService.java deleted file mode 100644 index f43ef244..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IAlertService.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.ruoyi.iot.service; - -import java.util.List; -import com.ruoyi.iot.domain.Alert; - -/** - * 设备告警Service接口 - * - * @author kerwincui - * @date 2022-01-13 - */ -public interface IAlertService -{ - /** - * 查询设备告警 - * - * @param alertId 设备告警主键 - * @return 设备告警 - */ - public Alert selectAlertByAlertId(Long alertId); - - /** - * 查询设备告警列表 - * - * @param alert 设备告警 - * @return 设备告警集合 - */ - public List selectAlertList(Alert alert); - - /** - * 新增设备告警 - * - * @param alert 设备告警 - * @return 结果 - */ - public int insertAlert(Alert alert); - - /** - * 修改设备告警 - * - * @param alert 设备告警 - * @return 结果 - */ - public int updateAlert(Alert alert); - - /** - * 批量删除设备告警 - * - * @param alertIds 需要删除的设备告警主键集合 - * @return 结果 - */ - public int deleteAlertByAlertIds(Long[] alertIds); - - /** - * 删除设备告警信息 - * - * @param alertId 设备告警主键 - * @return 结果 - */ - public int deleteAlertByAlertId(Long alertId); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IAuthRequestFactory.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IAuthRequestFactory.java deleted file mode 100644 index 3515ba4e..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IAuthRequestFactory.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.ruoyi.iot.service; - -import com.ruoyi.iot.model.login.AuthRequestWrap; - -/** - * AuthRequest简单工程类接口 - * - * @author json - * @date 2022-04-12 - */ -public interface IAuthRequestFactory { - - AuthRequestWrap getAuthRequest(String source); - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/ICategoryService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/ICategoryService.java deleted file mode 100644 index fd715ff7..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/ICategoryService.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.ruoyi.iot.service; - -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.iot.domain.Category; -import com.ruoyi.iot.model.IdAndName; - -import java.util.List; - -/** - * 产品分类Service接口 - * - * @author kerwincui - * @date 2021-12-16 - */ -public interface ICategoryService -{ - /** - * 查询产品分类 - * - * @param categoryId 产品分类主键 - * @return 产品分类 - */ - public Category selectCategoryByCategoryId(Long categoryId); - - /** - * 查询产品分类列表 - * - * @param category 产品分类 - * @return 产品分类集合 - */ - public List selectCategoryList(Category category); - - /** - * 查询产品简短分类列表 - * - * @return 产品分类集合 - */ - public List selectCategoryShortList(); - - /** - * 新增产品分类 - * - * @param category 产品分类 - * @return 结果 - */ - public int insertCategory(Category category); - - /** - * 修改产品分类 - * - * @param category 产品分类 - * @return 结果 - */ - public int updateCategory(Category category); - - /** - * 批量删除产品分类 - * - * @param categoryIds 需要删除的产品分类主键集合 - * @return 结果 - */ - public AjaxResult deleteCategoryByCategoryIds(Long[] categoryIds); - - /** - * 删除产品分类信息 - * - * @param categoryId 产品分类主键 - * @return 结果 - */ - public int deleteCategoryByCategoryId(Long categoryId); - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IDeviceJobService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IDeviceJobService.java deleted file mode 100644 index 0dfc3b55..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IDeviceJobService.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.ruoyi.iot.service; - -import com.ruoyi.common.exception.job.TaskException; -import com.ruoyi.iot.domain.DeviceJob; -import org.quartz.SchedulerException; - -import java.util.List; - -/** - * 定时任务调度信息信息 服务层 - * - * @author kerwincui - */ -public interface IDeviceJobService -{ - /** - * 获取quartz调度器的计划任务 - * - * @param job 调度信息 - * @return 调度任务集合 - */ - public List selectJobList(DeviceJob job); - - /** - * 通过调度任务ID查询调度信息 - * - * @param jobId 调度任务ID - * @return 调度任务对象信息 - */ - public DeviceJob selectJobById(Long jobId); - - /** - * 暂停任务 - * - * @param job 调度信息 - * @return 结果 - */ - public int pauseJob(DeviceJob job) throws SchedulerException; - - /** - * 恢复任务 - * - * @param job 调度信息 - * @return 结果 - */ - public int resumeJob(DeviceJob job) throws SchedulerException; - - /** - * 删除任务后,所对应的trigger也将被删除 - * - * @param job 调度信息 - * @return 结果 - */ - public int deleteJob(DeviceJob job) throws SchedulerException; - - /** - * 批量删除调度信息 - * - * @param jobIds 需要删除的任务ID - * @return 结果 - */ - public void deleteJobByIds(Long[] jobIds) throws SchedulerException; - - /** - * 根据设备Ids批量删除调度信息 - * - * @param deviceIds 需要删除数据的设备Ids - * @return 结果 - */ - public void deleteJobByDeviceIds(Long[] deviceIds) throws SchedulerException; - - /** - * 任务调度状态修改 - * - * @param job 调度信息 - * @return 结果 - */ - public int changeStatus(DeviceJob job) throws SchedulerException; - - /** - * 立即运行任务 - * - * @param job 调度信息 - * @return 结果 - */ - public void run(DeviceJob job) throws SchedulerException; - - /** - * 新增任务 - * - * @param job 调度信息 - * @return 结果 - */ - public int insertJob(DeviceJob job) throws SchedulerException, TaskException; - - /** - * 更新任务 - * - * @param job 调度信息 - * @return 结果 - */ - public int updateJob(DeviceJob job) throws SchedulerException, TaskException; - - /** - * 校验cron表达式是否有效 - * - * @param cronExpression 表达式 - * @return 结果 - */ - public boolean checkCronExpressionIsValid(String cronExpression); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IDeviceLogService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IDeviceLogService.java deleted file mode 100644 index 237e2a21..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IDeviceLogService.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.ruoyi.iot.service; - -import com.ruoyi.iot.domain.DeviceLog; -import com.ruoyi.iot.model.MonitorModel; - -import java.util.List; - -/** - * 设备日志Service接口 - * - * @author kerwincui - * @date 2022-01-13 - */ -public interface IDeviceLogService -{ - /** - * 查询设备日志 - * - * @param logId 设备日志主键 - * @return 设备日志 - */ - public DeviceLog selectDeviceLogByLogId(Long logId); - - /** - * 查询设备日志列表 - * - * @param deviceLog 设备日志 - * @return 设备日志集合 - */ - public List selectDeviceLogList(DeviceLog deviceLog); - - /** - * 查询设备监测数据 - * - * @param deviceLog 设备日志 - * @return 设备日志集合 - */ - public List selectMonitorList(DeviceLog deviceLog); - - /** - * 新增设备日志 - * - * @param deviceLog 设备日志 - * @return 结果 - */ - public int insertDeviceLog(DeviceLog deviceLog); - - /** - * 修改设备日志 - * - * @param deviceLog 设备日志 - * @return 结果 - */ - public int updateDeviceLog(DeviceLog deviceLog); - - /** - * 批量删除设备日志 - * - * @param logIds 需要删除的设备日志主键集合 - * @return 结果 - */ - public int deleteDeviceLogByLogIds(Long[] logIds); - - /** - * 删除设备日志信息 - * - * @param logId 设备日志主键 - * @return 结果 - */ - public int deleteDeviceLogByLogId(Long logId); - - /** - * 根据设备编号批量删除设备日志 - * - * @param deviceNumber 需要删除的设备日志ID - * @return 结果 - */ - public int deleteDeviceLogByDeviceNumber(String deviceNumber); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IDeviceService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IDeviceService.java deleted file mode 100644 index b99792ce..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IDeviceService.java +++ /dev/null @@ -1,194 +0,0 @@ -package com.ruoyi.iot.service; - -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.iot.domain.Device; -import com.ruoyi.iot.model.*; -import com.ruoyi.iot.model.ThingsModels.ThingsModelShadow; -import com.ruoyi.iot.model.ThingsModels.ThingsModelValuesInput; -import org.quartz.SchedulerException; - -import java.util.List; - -/** - * 设备Service接口 - * - * @author kerwincui - * @date 2021-12-16 - */ -public interface IDeviceService -{ - /** - * 查询设备 - * - * @param deviceId 设备主键 - * @return 设备 - */ - public Device selectDeviceByDeviceId(Long deviceId); - - /** - * 查询设备统计信息 - * - * @return 设备 - */ - public DeviceStatistic selectDeviceStatistic(); - - /** - * 根据设备编号查询设备 - * - * @param serialNumber 设备主键 - * @return 设备 - */ - public Device selectDeviceBySerialNumber(String serialNumber); - - /** - * 根据设备编号查询简介设备 - * - * @param serialNumber 设备主键 - * @return 设备 - */ - public Device selectShortDeviceBySerialNumber(String serialNumber); - - /** - * 根据设备编号查询设备认证信息 - * - * @param model 设备编号和产品ID - * @return 设备 - */ - public ProductAuthenticateModel selectProductAuthenticate(AuthenticateInputModel model); - - /** - * 查询设备和运行状态 - * - * @param deviceId 设备主键 - * @return 设备 - */ - public DeviceShortOutput selectDeviceRunningStatusByDeviceId(Long deviceId); - - /** - * 上报设备的物模型 - * @param input - * @return - */ - public int reportDeviceThingsModelValue(ThingsModelValuesInput input,int type,boolean isShadow); - - /** - * 查询设备列表 - * - * @param device 设备 - * @return 设备集合 - */ - public List selectDeviceList(Device device); - - /** - * 查询未分配授权码设备列表 - * - * @param device 设备 - * @return 设备集合 - */ - public List selectUnAuthDeviceList(Device device); - - /** - * 查询分组可添加设备分页列表 - * - * @param device 设备 - * @return 设备集合 - */ - public List selectDeviceListByGroup(Device device); - - /** - * 查询所有设备简短列表 - * - * @return 设备 - */ - public List selectAllDeviceShortList(); - - /** - * 查询设备简短列表 - * - * @param device 设备 - * @return 设备集合 - */ - public List selectDeviceShortList(Device device); - - /** - * 新增设备 - * - * @param device 设备 - * @return 结果 - */ - public Device insertDevice(Device device); - - /** - * 设备关联用户 - * - * @param deviceRelateUserInput 设备 - * @return 结果 - */ - public AjaxResult deviceRelateUser(DeviceRelateUserInput deviceRelateUserInput); - - /** - * 设备认证后自动添加设备 - * - * @return 结果 - */ - public int insertDeviceAuto(String serialNumber,Long userId,Long productId); - - /** - * 获取设备设置的影子 - * @param device - * @return - */ - public ThingsModelShadow getDeviceShadowThingsModel(Device device); - - /** - * 修改设备 - * - * @param device 设备 - * @return 结果 - */ - public AjaxResult updateDevice(Device device); - - /** - * 更新设备状态和定位 - * @param device 设备 - * @return 结果 - */ - public int updateDeviceStatusAndLocation(Device device,String ipAddress); - - /** - * 更新设备状态 - * @param device 设备 - * @return 结果 - */ - public int updateDeviceStatus(Device device); - - /** - * 上报设备信息 - * @param device 设备 - * @return 结果 - */ - public int reportDevice(Device device,Device deviceentity); - - /** - * 删除设备 - * - * @param deviceId 需要删除的设备主键集合 - * @return 结果 - */ - public int deleteDeviceByDeviceId(Long deviceId) throws SchedulerException; - - - /** - * 生成设备唯一编号 - * @return 结果 - */ - public String generationDeviceNum(); - - /** - * 重置设备状态 - * @return 结果 - */ - public int resetDeviceStatus(String deviceNum); - - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IDeviceUserService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IDeviceUserService.java deleted file mode 100644 index 91d485f3..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IDeviceUserService.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.ruoyi.iot.service; - -import java.util.List; -import com.ruoyi.iot.domain.DeviceUser; - -/** - * 设备用户Service接口 - * - * @author kerwincui - * @date 2021-12-16 - */ -public interface IDeviceUserService -{ - /** - * 查询设备用户 - * - * @param deviceId 设备用户主键 - * @return 设备用户 - */ - public List selectDeviceUserByDeviceId(Long deviceId); - - /** - * 查询设备用户列表 - * - * @param deviceUser 设备用户 - * @return 设备用户集合 - */ - public List selectDeviceUserList(DeviceUser deviceUser); - - /** - * 新增设备用户 - * - * @param deviceUser 设备用户 - * @return 结果 - */ - public int insertDeviceUser(DeviceUser deviceUser); - - /** - * 修改设备用户 - * - * @param deviceUser 设备用户 - * @return 结果 - */ - public int updateDeviceUser(DeviceUser deviceUser); - - /** - * 批量删除设备用户 - * - * @param deviceIds 需要删除的设备用户主键集合 - * @return 结果 - */ - public int deleteDeviceUserByDeviceIds(Long[] deviceIds); - - /** - * 删除设备用户信息 - * - * @param deviceId 设备用户主键 - * @return 结果 - */ - public int deleteDeviceUserByDeviceId(Long deviceId); - - /** - * 批量添加设备用户 - * @param deviceUsers 设备用户 - * @return 结果 - */ - public int insertDeviceUserList(List deviceUsers); - - /** - * 查询设备用户 - * - * @param deviceId 设备用户主键 - * @return 设备用户 - */ - public DeviceUser selectDeviceUserByDeviceIdAndUserId(Long deviceId, Long userId); - - public int deleteDeviceUser(DeviceUser deviceUser); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IFirmwareService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IFirmwareService.java deleted file mode 100644 index eac0b66b..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IFirmwareService.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.ruoyi.iot.service; - -import java.util.List; -import com.ruoyi.iot.domain.Firmware; - -/** - * 产品固件Service接口 - * - * @author kerwincui - * @date 2021-12-16 - */ -public interface IFirmwareService -{ - /** - * 查询产品固件 - * - * @param firmwareId 产品固件主键 - * @return 产品固件 - */ - public Firmware selectFirmwareByFirmwareId(Long firmwareId); - - /** - * 查询设备最新固件 - * - * @param deviceId 产品固件主键 - * @return 产品固件 - */ - public Firmware selectLatestFirmware(Long deviceId); - - /** - * 查询产品固件列表 - * - * @param firmware 产品固件 - * @return 产品固件集合 - */ - public List selectFirmwareList(Firmware firmware); - - /** - * 新增产品固件 - * - * @param firmware 产品固件 - * @return 结果 - */ - public int insertFirmware(Firmware firmware); - - /** - * 修改产品固件 - * - * @param firmware 产品固件 - * @return 结果 - */ - public int updateFirmware(Firmware firmware); - - /** - * 批量删除产品固件 - * - * @param firmwareIds 需要删除的产品固件主键集合 - * @return 结果 - */ - public int deleteFirmwareByFirmwareIds(Long[] firmwareIds); - - /** - * 删除产品固件信息 - * - * @param firmwareId 产品固件主键 - * @return 结果 - */ - public int deleteFirmwareByFirmwareId(Long firmwareId); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IGroupService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IGroupService.java deleted file mode 100644 index b403934e..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IGroupService.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.ruoyi.iot.service; - -import com.ruoyi.iot.domain.Group; -import com.ruoyi.iot.model.DeviceGroupInput; - -import java.util.List; - -/** - * 设备分组Service接口 - * - * @author kerwincui - * @date 2021-12-16 - */ -public interface IGroupService -{ - /** - * 查询设备分组 - * - * @param groupId 设备分组主键 - * @return 设备分组 - */ - public Group selectGroupByGroupId(Long groupId); - - /** - * 通过分组ID查询关联的设备ID数组 - * @param groupId - * @return - */ - public Long[] selectDeviceIdsByGroupId(Long groupId); - - /** - * 查询设备分组列表 - * - * @param group 设备分组 - * @return 设备分组集合 - */ - public List selectGroupList(Group group); - - /** - * 新增设备分组 - * - * @param group 设备分组 - * @return 结果 - */ - public int insertGroup(Group group); - - /** - * 分组下批量添加设备分组 - * @return - */ - public int updateDeviceGroups(DeviceGroupInput input); - - /** - * 修改设备分组 - * - * @param group 设备分组 - * @return 结果 - */ - public int updateGroup(Group group); - - /** - * 批量删除分组 - * - * @param groupIds 需要删除的设备分组主键集合 - * @return 结果 - */ - public int deleteGroupByGroupIds(Long[] groupIds); - - /** - * 删除分组信息 - * - * @param groupId 设备分组主键 - * @return 结果 - */ - public int deleteGroupByGroupId(Long groupId); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/INewsCategoryService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/INewsCategoryService.java deleted file mode 100644 index c7d0cf8a..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/INewsCategoryService.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.ruoyi.iot.service; - -import java.util.List; - -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.iot.domain.NewsCategory; -import com.ruoyi.iot.model.IdAndName; - -/** - * 新闻分类Service接口 - * - * @author kerwincui - * @date 2022-04-09 - */ -public interface INewsCategoryService -{ - /** - * 查询新闻分类 - * - * @param categoryId 新闻分类主键 - * @return 新闻分类 - */ - public NewsCategory selectNewsCategoryByCategoryId(Long categoryId); - - /** - * 查询新闻分类列表 - * - * @param newsCategory 新闻分类 - * @return 新闻分类集合 - */ - public List selectNewsCategoryList(NewsCategory newsCategory); - - /** - * 查询新闻分类简短列表 - * - * @return 新闻分类集合 - */ - public List selectNewsCategoryShortList(); - - /** - * 新增新闻分类 - * - * @param newsCategory 新闻分类 - * @return 结果 - */ - public int insertNewsCategory(NewsCategory newsCategory); - - /** - * 修改新闻分类 - * - * @param newsCategory 新闻分类 - * @return 结果 - */ - public int updateNewsCategory(NewsCategory newsCategory); - - /** - * 批量删除新闻分类 - * - * @param categoryIds 需要删除的新闻分类主键集合 - * @return 结果 - */ - public AjaxResult deleteNewsCategoryByCategoryIds(Long[] categoryIds); - - /** - * 删除新闻分类信息 - * - * @param categoryId 新闻分类主键 - * @return 结果 - */ - public int deleteNewsCategoryByCategoryId(Long categoryId); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/INewsService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/INewsService.java deleted file mode 100644 index 9b872c1b..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/INewsService.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.ruoyi.iot.service; - -import java.util.List; -import com.ruoyi.iot.domain.News; -import com.ruoyi.iot.model.CategoryNews; - -/** - * 新闻资讯Service接口 - * - * @author kerwincui - * @date 2022-04-09 - */ -public interface INewsService -{ - /** - * 查询新闻资讯 - * - * @param newsId 新闻资讯主键 - * @return 新闻资讯 - */ - public News selectNewsByNewsId(Long newsId); - - /** - * 查询新闻资讯列表 - * - * @param news 新闻资讯 - * @return 新闻资讯集合 - */ - public List selectNewsList(News news); - - /** - * 查询置顶新闻资讯列表 - * - * @return 新闻资讯集合 - */ - public List selectTopNewsList(); - - /** - * 新增新闻资讯 - * - * @param news 新闻资讯 - * @return 结果 - */ - public int insertNews(News news); - - /** - * 修改新闻资讯 - * - * @param news 新闻资讯 - * @return 结果 - */ - public int updateNews(News news); - - /** - * 批量删除新闻资讯 - * - * @param newsIds 需要删除的新闻资讯主键集合 - * @return 结果 - */ - public int deleteNewsByNewsIds(Long[] newsIds); - - /** - * 删除新闻资讯信息 - * - * @param newsId 新闻资讯主键 - * @return 结果 - */ - public int deleteNewsByNewsId(Long newsId); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IOauthClientDetailsService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IOauthClientDetailsService.java deleted file mode 100644 index f5eabab8..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IOauthClientDetailsService.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.ruoyi.iot.service; - -import java.util.List; -import com.ruoyi.iot.domain.OauthClientDetails; - -/** - * 云云对接Service接口 - * - * @author kerwincui - * @date 2022-02-07 - */ -public interface IOauthClientDetailsService -{ - /** - * 查询云云对接 - * - * @param clientId 云云对接主键 - * @return 云云对接 - */ - public OauthClientDetails selectOauthClientDetailsByClientId(String clientId); - - /** - * 查询云云对接列表 - * - * @param oauthClientDetails 云云对接 - * @return 云云对接集合 - */ - public List selectOauthClientDetailsList(OauthClientDetails oauthClientDetails); - - /** - * 新增云云对接 - * - * @param oauthClientDetails 云云对接 - * @return 结果 - */ - public int insertOauthClientDetails(OauthClientDetails oauthClientDetails); - - /** - * 修改云云对接 - * - * @param oauthClientDetails 云云对接 - * @return 结果 - */ - public int updateOauthClientDetails(OauthClientDetails oauthClientDetails); - - /** - * 批量删除云云对接 - * - * @param clientIds 需要删除的云云对接主键集合 - * @return 结果 - */ - public int deleteOauthClientDetailsByClientIds(String[] clientIds); - - /** - * 删除云云对接信息 - * - * @param clientId 云云对接主键 - * @return 结果 - */ - public int deleteOauthClientDetailsByClientId(String clientId); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IProductAuthorizeService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IProductAuthorizeService.java deleted file mode 100644 index f4fe9f29..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IProductAuthorizeService.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.ruoyi.iot.service; - -import java.util.List; -import com.ruoyi.iot.domain.ProductAuthorize; -import com.ruoyi.iot.model.ProductAuthorizeVO; - -/** - * 产品授权码Service接口 - * - * @author kami - * @date 2022-04-11 - */ -public interface IProductAuthorizeService -{ - /** - * 查询产品授权码 - * - * @param authorizeId 产品授权码主键 - * @return 产品授权码 - */ - public ProductAuthorize selectProductAuthorizeByAuthorizeId(Long authorizeId); - - /** - * 查询产品授权码列表 - * - * @param productAuthorize 产品授权码 - * @return 产品授权码集合 - */ - public List selectProductAuthorizeList(ProductAuthorize productAuthorize); - - /** - * 新增产品授权码 - * - * @param productAuthorize 产品授权码 - * @return 结果 - */ - public int insertProductAuthorize(ProductAuthorize productAuthorize); - - /** - * 修改产品授权码 - * - * @param productAuthorize 产品授权码 - * @return 结果 - */ - public int updateProductAuthorize(ProductAuthorize productAuthorize); - - /** - * 批量删除产品授权码 - * - * @param authorizeIds 需要删除的产品授权码主键集合 - * @return 结果 - */ - public int deleteProductAuthorizeByAuthorizeIds(Long[] authorizeIds); - - /** - * 删除产品授权码信息 - * - * @param authorizeId 产品授权码主键 - * @return 结果 - */ - public int deleteProductAuthorizeByAuthorizeId(Long authorizeId); - - /** - * 根据数量批量新增产品授权码 - * @param productAuthorizeVO - * @return - */ - public int addProductAuthorizeByNum(ProductAuthorizeVO productAuthorizeVO); - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IProductService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IProductService.java deleted file mode 100644 index 8c691e7b..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IProductService.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.ruoyi.iot.service; - -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.iot.domain.Product; -import com.ruoyi.iot.model.ChangeProductStatusModel; -import com.ruoyi.iot.model.IdAndName; - -import java.util.List; - -/** - * 产品Service接口 - * - * @author kerwincui - * @date 2021-12-16 - */ -public interface IProductService -{ - /** - * 查询产品 - * - * @param productId 产品主键 - * @return 产品 - */ - public Product selectProductByProductId(Long productId); - - /** - * 查询产品列表 - * - * @param product 产品 - * @return 产品集合 - */ - public List selectProductList(Product product); - - /** - * 查询产品简短列表 - * - * @return 产品集合 - */ - public List selectProductShortList(); - - /** - * 新增产品 - * - * @param product 产品 - * @return 结果 - */ - public Product insertProduct(Product product); - - /** - * 修改产品 - * - * @param product 产品 - * @return 结果 - */ - public int updateProduct(Product product); - - /** - * 更新产品状态,1-未发布,2-已发布 - * - * @param model - * @return 结果 - */ - public AjaxResult changeProductStatus(ChangeProductStatusModel model); - - /** - * 批量删除产品 - * - * @param productIds 需要删除的产品主键集合 - * @return 结果 - */ - public AjaxResult deleteProductByProductIds(Long[] productIds); - - /** - * 删除产品信息 - * - * @param productId 产品主键 - * @return 结果 - */ - public int deleteProductByProductId(Long productId); - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/ISceneService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/ISceneService.java deleted file mode 100644 index d27cd23a..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/ISceneService.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.ruoyi.iot.service; - -import java.util.List; -import com.ruoyi.iot.domain.Scene; - -/** - * 场景联动Service接口 - * - * @author kerwincui - * @date 2022-01-13 - */ -public interface ISceneService -{ - /** - * 查询场景联动 - * - * @param sceneId 场景联动主键 - * @return 场景联动 - */ - public Scene selectSceneBySceneId(Long sceneId); - - /** - * 查询场景联动列表 - * - * @param scene 场景联动 - * @return 场景联动集合 - */ - public List selectSceneList(Scene scene); - - /** - * 新增场景联动 - * - * @param scene 场景联动 - * @return 结果 - */ - public int insertScene(Scene scene); - - /** - * 修改场景联动 - * - * @param scene 场景联动 - * @return 结果 - */ - public int updateScene(Scene scene); - - /** - * 批量删除场景联动 - * - * @param sceneIds 需要删除的场景联动主键集合 - * @return 结果 - */ - public int deleteSceneBySceneIds(Long[] sceneIds); - - /** - * 删除场景联动信息 - * - * @param sceneId 场景联动主键 - * @return 结果 - */ - public int deleteSceneBySceneId(Long sceneId); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/ISocialLoginService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/ISocialLoginService.java deleted file mode 100644 index d3a8a611..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/ISocialLoginService.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.ruoyi.iot.service; - -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.domain.model.BindLoginBody; -import com.ruoyi.common.core.domain.model.BindRegisterBody; -import me.zhyd.oauth.model.AuthCallback; - -import javax.servlet.http.HttpServletRequest; - -/** - * 第三方登录Service接口 - * 处理登录跳转业务逻辑 - * - * @author json - * @date 2022-04-12 - */ -public interface ISocialLoginService { - - /** - * 第三方登录跳转 - * - * @param source 平台 - * @param httpServletRequest 当前请求 - * @return 跳转路径 - */ - String renderAuth(String source, HttpServletRequest httpServletRequest); - - /** - * 第三方登录callback - * - * @param source 平台 - * @param authCallback 回调参数 - * @param httpServletRequest 当前请求 - * @return 跳转路径 - */ - String callback(String source, AuthCallback authCallback, HttpServletRequest httpServletRequest); - - /** - * 检查是否bindId - * - * @param bindId 绑定id - * @return - */ - AjaxResult checkBindId(String bindId); - - /** - * 获得错误显示 - * - * @param errorId errorId - * @return - */ - AjaxResult getErrorMsg(String errorId); - - /** - * 跳转直接登录 - * - * @param loginId 登录id - * @return - */ - AjaxResult socialLogin(String loginId); - - /** - * 绑定登录api - * - * @param bindLoginBody 绑定账户参数 - * @return - */ - AjaxResult bindLogin(BindLoginBody bindLoginBody); - - /** - * 注册绑定api - * - * @param bindRegisterBody - * @return - */ - AjaxResult bindRegister(BindRegisterBody bindRegisterBody); - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/ISocialPlatformService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/ISocialPlatformService.java deleted file mode 100644 index d4cadecf..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/ISocialPlatformService.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.ruoyi.iot.service; - -import java.util.List; -import com.ruoyi.iot.domain.SocialPlatform; - -/** - * 第三方登录平台控制Service接口 - * - * @author json - * @date 2022-04-12 - */ -public interface ISocialPlatformService -{ - /** - * 查询第三方登录平台控制 - * - * @param socialPlatformId 第三方登录平台控制主键 - * @return 第三方登录平台控制 - */ - public SocialPlatform selectSocialPlatformBySocialPlatformId(Long socialPlatformId); - - /** - * 查询第三方登录平台控制 - * - * @param platform 第三方登录平台名称 - * @return 第三方登录平台控制 - */ - public SocialPlatform selectSocialPlatformByPlatform(String platform); - - /** - * 查询第三方登录平台控制列表 - * - * @param socialPlatform 第三方登录平台控制 - * @return 第三方登录平台控制集合 - */ - public List selectSocialPlatformList(SocialPlatform socialPlatform); - - /** - * 新增第三方登录平台控制 - * - * @param socialPlatform 第三方登录平台控制 - * @return 结果 - */ - public int insertSocialPlatform(SocialPlatform socialPlatform); - - /** - * 修改第三方登录平台控制 - * - * @param socialPlatform 第三方登录平台控制 - * @return 结果 - */ - public int updateSocialPlatform(SocialPlatform socialPlatform); - - /** - * 批量删除第三方登录平台控制 - * - * @param socialPlatformIds 需要删除的第三方登录平台控制主键集合 - * @return 结果 - */ - public int deleteSocialPlatformBySocialPlatformIds(Long[] socialPlatformIds); - - /** - * 删除第三方登录平台控制信息 - * - * @param socialPlatformId 第三方登录平台控制主键 - * @return 结果 - */ - public int deleteSocialPlatformBySocialPlatformId(Long socialPlatformId); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/ISocialUserService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/ISocialUserService.java deleted file mode 100644 index b16ebdb1..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/ISocialUserService.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.ruoyi.iot.service; - -import java.util.List; -import com.ruoyi.iot.domain.SocialUser; - -/** - * 用户第三方用户信息Service接口 - * - * @author json - * @date 2022-04-18 - */ -public interface ISocialUserService -{ - /** - * 查询用户第三方用户信息 - * - * @param socialUserId 用户第三方用户信息主键 - * @return 用户第三方用户信息 - */ - public SocialUser selectSocialUserBySocialUserId(Long socialUserId); - - /** - * 查询用户第三方用户信息列表 - * - * @param socialUser 用户第三方用户信息 - * @return 用户第三方用户信息集合 - */ - public List selectSocialUserList(SocialUser socialUser); - - /** - * 新增用户第三方用户信息 - * - * @param socialUser 用户第三方用户信息 - * @return 结果 - */ - public int insertSocialUser(SocialUser socialUser); - - /** - * 修改用户第三方用户信息 - * - * @param socialUser 用户第三方用户信息 - * @return 结果 - */ - public int updateSocialUser(SocialUser socialUser); - - /** - * 批量删除用户第三方用户信息 - * - * @param socialUserIds 需要删除的用户第三方用户信息主键集合 - * @return 结果 - */ - public int deleteSocialUserBySocialUserIds(Long[] socialUserIds); - - /** - * 删除用户第三方用户信息信息 - * - * @param socialUserId 用户第三方用户信息主键 - * @return 结果 - */ - public int deleteSocialUserBySocialUserId(Long socialUserId); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IThingsModelService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IThingsModelService.java deleted file mode 100644 index 11554b3a..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IThingsModelService.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.ruoyi.iot.service; - -import java.util.List; -import com.ruoyi.iot.domain.ThingsModel; -import com.ruoyi.iot.model.ImportThingsModelInput; - -/** - * 物模型Service接口 - * - * @author kerwincui - * @date 2021-12-16 - */ -public interface IThingsModelService -{ - /** - * 查询物模型 - * - * @param modelId 物模型主键 - * @return 物模型 - */ - public ThingsModel selectThingsModelByModelId(Long modelId); - - /** - * 查询物模型列表 - * - * @param thingsModel 物模型 - * @return 物模型集合 - */ - public List selectThingsModelList(ThingsModel thingsModel); - - /** - * 新增物模型 - * - * @param thingsModel 物模型 - * @return 结果 - */ - public int insertThingsModel(ThingsModel thingsModel); - - /** - * 从模板导入物模型 - * @param input - * @return - */ - public int importByTemplateIds(ImportThingsModelInput input); - - /** - * 修改物模型 - * - * @param thingsModel 物模型 - * @return 结果 - */ - public int updateThingsModel(ThingsModel thingsModel); - - /** - * 批量删除物模型 - * - * @param modelIds 需要删除的物模型主键集合 - * @return 结果 - */ - public int deleteThingsModelByModelIds(Long[] modelIds); - - /** - * 删除物模型信息 - * - * @param modelId 物模型主键 - * @return 结果 - */ - public int deleteThingsModelByModelId(Long modelId); - - /** - * 根据产品ID获取JSON物模型 - * @param productId - * @return - */ - public String getCacheThingsModelByProductId(Long productId); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IThingsModelTemplateService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IThingsModelTemplateService.java deleted file mode 100644 index 41c98186..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IThingsModelTemplateService.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.ruoyi.iot.service; - -import java.util.List; -import com.ruoyi.iot.domain.ThingsModelTemplate; - -/** - * 通用物模型Service接口 - * - * @author kerwincui - * @date 2021-12-16 - */ -public interface IThingsModelTemplateService -{ - /** - * 查询通用物模型 - * - * @param templateId 通用物模型主键 - * @return 通用物模型 - */ - public ThingsModelTemplate selectThingsModelTemplateByTemplateId(Long templateId); - - /** - * 查询通用物模型列表 - * - * @param thingsModelTemplate 通用物模型 - * @return 通用物模型集合 - */ - public List selectThingsModelTemplateList(ThingsModelTemplate thingsModelTemplate); - - /** - * 新增通用物模型 - * - * @param thingsModelTemplate 通用物模型 - * @return 结果 - */ - public int insertThingsModelTemplate(ThingsModelTemplate thingsModelTemplate); - - /** - * 修改通用物模型 - * - * @param thingsModelTemplate 通用物模型 - * @return 结果 - */ - public int updateThingsModelTemplate(ThingsModelTemplate thingsModelTemplate); - - /** - * 批量删除通用物模型 - * - * @param templateIds 需要删除的通用物模型主键集合 - * @return 结果 - */ - public int deleteThingsModelTemplateByTemplateIds(Long[] templateIds); - - /** - * 删除通用物模型信息 - * - * @param templateId 通用物模型主键 - * @return 结果 - */ - public int deleteThingsModelTemplateByTemplateId(Long templateId); - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IToolService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IToolService.java deleted file mode 100644 index 8884873f..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IToolService.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.ruoyi.iot.service; - -import com.ruoyi.common.core.domain.entity.SysUser; -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.iot.domain.ProductAuthorize; -import com.ruoyi.iot.model.MqttAuthenticationModel; -import com.ruoyi.iot.model.ProductAuthenticateModel; -import com.ruoyi.iot.model.RegisterUserInput; -import com.ruoyi.iot.util.AESUtils; -import org.springframework.http.ResponseEntity; - -import java.util.List; - -/** - * - * @author kerwincui - * @date 2021-12-16 - */ -public interface IToolService -{ - /** - * 注册 - */ - public String register(RegisterUserInput registerBody); - - /** - * 根据条件分页查询用户列表 - * - * @param user 用户信息 - * @return 用户信息集合信息 - */ - public List selectUserList(SysUser user); - - /** - * 生成随机数字和字母 - */ - public String getStringRandom(int length); - - /** - * 设备简单认证 - */ - public ResponseEntity simpleMqttAuthentication(MqttAuthenticationModel mqttModel, ProductAuthenticateModel productModel); - - /** - * 设备加密认证 - * - * @return - */ - public ResponseEntity encryptAuthentication(MqttAuthenticationModel mqttModel, ProductAuthenticateModel productModel)throws Exception; - - - /** - * 返回认证信息 - */ - public ResponseEntity returnUnauthorized(MqttAuthenticationModel mqttModel, String message); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IUserSocialProfileService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IUserSocialProfileService.java deleted file mode 100644 index 5ba21c64..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IUserSocialProfileService.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.ruoyi.iot.service; - -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.iot.domain.UserSocialProfile; - -import java.util.List; - -public interface IUserSocialProfileService { - /** - * 找到用户绑定的社交账户 - * - * @param sysUserId 用户主键 - * @return - */ - List selectUserSocialProfile(Long sysUserId); - - /** - * 绑定用户 - * - * @param bindId 绑定的Id - * @param sysUserId 用户主键 - * @return - */ - AjaxResult bindUser(String bindId, Long sysUserId); - - /** - * 点击绑定跳转api - * - * @param platform 平台 - * @return - */ - AjaxResult bindSocialAccount(String platform); - - /** - * 解除绑定 - * - * @param socialUserId 要解除的社交账户主键 - * @param sysUserId 用户主键 - * @return - */ - AjaxResult unbindSocialAccount(Long socialUserId, Long sysUserId); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/AlertLogServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/AlertLogServiceImpl.java deleted file mode 100644 index 5fe6d135..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/AlertLogServiceImpl.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.ruoyi.iot.service.impl; - -import java.util.List; -import com.ruoyi.common.utils.DateUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import com.ruoyi.iot.mapper.AlertLogMapper; -import com.ruoyi.iot.domain.AlertLog; -import com.ruoyi.iot.service.IAlertLogService; - -/** - * 设备告警Service业务层处理 - * - * @author kerwincui - * @date 2022-01-13 - */ -@Service -public class AlertLogServiceImpl implements IAlertLogService -{ - @Autowired - private AlertLogMapper alertLogMapper; - - /** - * 查询设备告警 - * - * @param alertLogId 设备告警主键 - * @return 设备告警 - */ - @Override - public AlertLog selectAlertLogByAlertLogId(Long alertLogId) - { - return alertLogMapper.selectAlertLogByAlertLogId(alertLogId); - } - - /** - * 查询设备告警列表 - * - * @param alertLog 设备告警 - * @return 设备告警 - */ - @Override - public List selectAlertLogList(AlertLog alertLog) - { - return alertLogMapper.selectAlertLogList(alertLog); - } - - /** - * 新增设备告警 - * - * @param alertLog 设备告警 - * @return 结果 - */ - @Override - public int insertAlertLog(AlertLog alertLog) - { - alertLog.setCreateTime(DateUtils.getNowDate()); - return alertLogMapper.insertAlertLog(alertLog); - } - - /** - * 修改设备告警 - * - * @param alertLog 设备告警 - * @return 结果 - */ - @Override - public int updateAlertLog(AlertLog alertLog) - { - alertLog.setUpdateTime(DateUtils.getNowDate()); - return alertLogMapper.updateAlertLog(alertLog); - } - - /** - * 批量删除设备告警 - * - * @param alertLogIds 需要删除的设备告警主键 - * @return 结果 - */ - @Override - public int deleteAlertLogByAlertLogIds(Long[] alertLogIds) - { - return alertLogMapper.deleteAlertLogByAlertLogIds(alertLogIds); - } - - /** - * 删除设备告警信息 - * - * @param alertLogId 设备告警主键 - * @return 结果 - */ - @Override - public int deleteAlertLogByAlertLogId(Long alertLogId) - { - return alertLogMapper.deleteAlertLogByAlertLogId(alertLogId); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/AlertServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/AlertServiceImpl.java deleted file mode 100644 index a5211ae9..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/AlertServiceImpl.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.ruoyi.iot.service.impl; - -import java.util.List; -import com.ruoyi.common.utils.DateUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import com.ruoyi.iot.mapper.AlertMapper; -import com.ruoyi.iot.domain.Alert; -import com.ruoyi.iot.service.IAlertService; - -/** - * 设备告警Service业务层处理 - * - * @author kerwincui - * @date 2022-01-13 - */ -@Service -public class AlertServiceImpl implements IAlertService -{ - @Autowired - private AlertMapper alertMapper; - - /** - * 查询设备告警 - * - * @param alertId 设备告警主键 - * @return 设备告警 - */ - @Override - public Alert selectAlertByAlertId(Long alertId) - { - return alertMapper.selectAlertByAlertId(alertId); - } - - /** - * 查询设备告警列表 - * - * @param alert 设备告警 - * @return 设备告警 - */ - @Override - public List selectAlertList(Alert alert) - { - return alertMapper.selectAlertList(alert); - } - - /** - * 新增设备告警 - * - * @param alert 设备告警 - * @return 结果 - */ - @Override - public int insertAlert(Alert alert) - { - alert.setCreateTime(DateUtils.getNowDate()); - return alertMapper.insertAlert(alert); - } - - /** - * 修改设备告警 - * - * @param alert 设备告警 - * @return 结果 - */ - @Override - public int updateAlert(Alert alert) - { - alert.setUpdateTime(DateUtils.getNowDate()); - return alertMapper.updateAlert(alert); - } - - /** - * 批量删除设备告警 - * - * @param alertIds 需要删除的设备告警主键 - * @return 结果 - */ - @Override - public int deleteAlertByAlertIds(Long[] alertIds) - { - return alertMapper.deleteAlertByAlertIds(alertIds); - } - - /** - * 删除设备告警信息 - * - * @param alertId 设备告警主键 - * @return 结果 - */ - @Override - public int deleteAlertByAlertId(Long alertId) - { - return alertMapper.deleteAlertByAlertId(alertId); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/AuthRequestFactoryImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/AuthRequestFactoryImpl.java deleted file mode 100644 index 57324d81..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/AuthRequestFactoryImpl.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.ruoyi.iot.service.impl; - -import com.ruoyi.common.enums.SocialPlatformType; -import com.ruoyi.common.exception.ServiceException; -import com.ruoyi.iot.domain.SocialPlatform; -import com.ruoyi.iot.model.login.AuthRequestWrap; -import com.ruoyi.iot.service.IAuthRequestFactory; -import com.ruoyi.iot.service.ISocialPlatformService; -import me.zhyd.oauth.config.AuthConfig; -import me.zhyd.oauth.request.AuthQqRequest; -import me.zhyd.oauth.request.AuthRequest; -import me.zhyd.oauth.request.AuthWeChatMpRequest; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.Locale; - -@Service -public class AuthRequestFactoryImpl implements IAuthRequestFactory { - - private static final Logger log = LoggerFactory.getLogger(AuthRequestFactoryImpl.class); - - @Autowired - private ISocialPlatformService iSocialPlatformService; - - @Autowired - private AuthStateRedisCache authStateRedisCache; - - /** - * 获得对于AUthRequest - * - * @param source 登录方式 - * @return 对应AuthRequest - */ - @Override - public AuthRequestWrap getAuthRequest(String source) { - AuthRequestWrap authRequestWrap = new AuthRequestWrap(); - AuthRequest authRequest; - try { - SocialPlatformType socialPlatformType = SocialPlatformType.valueOf(source.toUpperCase(Locale.ROOT)); - SocialPlatform socialPlatform = iSocialPlatformService.selectSocialPlatformByPlatform(source); - authRequestWrap.setSocialPlatform(socialPlatform); - AuthConfig authConfig = AuthConfig.builder() - .clientId(socialPlatform.getClientId()) - .clientSecret(socialPlatform.getSecretKey()) - .redirectUri(socialPlatform.getRedirectUri()) - .build(); - switch (socialPlatformType) { - case QQ: { - authRequest = new AuthQqRequest(authConfig, authStateRedisCache); - break; - } - case Wechat: { - authRequest = new AuthWeChatMpRequest(authConfig, authStateRedisCache); - break; - } - default: { - throw new ServiceException("source: " + source + ",暂不支持"); - } - } - authRequestWrap.setAuthRequest(authRequest); - return authRequestWrap; - } catch (Exception e) { - throw new ServiceException(e.getMessage()); - } - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/AuthStateRedisCache.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/AuthStateRedisCache.java deleted file mode 100644 index 48071a13..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/AuthStateRedisCache.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.ruoyi.iot.service.impl; - -import com.ruoyi.common.core.redis.RedisCache; -import com.ruoyi.common.utils.sign.Md5Utils; -import me.zhyd.oauth.cache.AuthCacheConfig; -import me.zhyd.oauth.cache.AuthStateCache; -import me.zhyd.oauth.utils.AuthStateUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.springframework.stereotype.Service; - -import java.util.concurrent.TimeUnit; - -/** - * 扩展Redis版的state缓存 - * - * @author json - * @date 2022/04/12 - */ -@Component -public class AuthStateRedisCache implements AuthStateCache { - - @Autowired - private RedisCache redisCache; - - @Override - public void cache(String key, String value) { - redisCache.setCacheObject(key, getValue(value), (int) AuthCacheConfig.timeout, TimeUnit.MILLISECONDS); - } - - @Override - public void cache(String key, String value, long timeout) { - redisCache.setCacheObject(key, getValue(value), (int) timeout, TimeUnit.MILLISECONDS); - } - - @Override - public String get(String key) { - return redisCache.getCacheObject(key); - } - - @Override - public boolean containsKey(String key) { - return redisCache.containsKey(key); - } - - /** - * 自定义state - * @param oldState - * @return state - */ - private String getValue(String oldState) { - return Md5Utils.hash(oldState + System.currentTimeMillis()); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/CategoryServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/CategoryServiceImpl.java deleted file mode 100644 index f30979ae..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/CategoryServiceImpl.java +++ /dev/null @@ -1,146 +0,0 @@ -package com.ruoyi.iot.service.impl; - -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.domain.entity.SysRole; -import com.ruoyi.common.core.domain.entity.SysUser; -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.iot.domain.Category; -import com.ruoyi.iot.mapper.CategoryMapper; -import com.ruoyi.iot.model.IdAndName; -import com.ruoyi.iot.service.ICategoryService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; - -import static com.ruoyi.common.utils.SecurityUtils.getLoginUser; - -/** - * 产品分类Service业务层处理 - * - * @author kerwincui - * @date 2021-12-16 - */ -@Service -public class CategoryServiceImpl implements ICategoryService -{ - @Autowired - private CategoryMapper categoryMapper; - - /** - * 查询产品分类 - * - * @param categoryId 产品分类主键 - * @return 产品分类 - */ - @Override - public Category selectCategoryByCategoryId(Long categoryId) - { - return categoryMapper.selectCategoryByCategoryId(categoryId); - } - - /** - * 查询产品分类列表 - * - * @param category 产品分类 - * @return 产品分类 - */ - @Override - public List selectCategoryList(Category category) - { - SysUser user = getLoginUser().getUser(); - List roles=user.getRoles(); - // 租户 - if(roles.stream().anyMatch(a->a.getRoleKey().equals("tenant"))){ - category.setTenantId(user.getUserId()); - } - return categoryMapper.selectCategoryList(category); - } - - /** - * 查询产品分简短类列表 - * - * @return 产品分类 - */ - @Override - public List selectCategoryShortList() - { - Category category=new Category(); - SysUser user = getLoginUser().getUser(); - List roles=user.getRoles(); - // 租户 - if(roles.stream().anyMatch(a->a.getRoleKey().equals("tenant"))){ - category.setTenantId(user.getUserId()); - } - return categoryMapper.selectCategoryShortList(category); - } - - /** - * 新增产品分类 - * - * @param category 产品分类 - * @return 结果 - */ - @Override - public int insertCategory(Category category) - { - // 判断是否为管理员 - category.setIsSys(1); - SysUser user = getLoginUser().getUser(); - List roles=user.getRoles(); - for(int i=0;i0){ - return AjaxResult.error("删除失败,请先删除对应分类下的产品"); - } - if(categoryMapper.deleteCategoryByCategoryIds(categoryIds)>0){ - return AjaxResult.success("删除成功"); - } - return AjaxResult.error("删除失败"); - } - - /** - * 删除产品分类信息 - * - * @param categoryId 产品分类主键 - * @return 结果 - */ - @Override - public int deleteCategoryByCategoryId(Long categoryId) - { - return categoryMapper.deleteCategoryByCategoryId(categoryId); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/DeviceJobServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/DeviceJobServiceImpl.java deleted file mode 100644 index 1d714cc7..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/DeviceJobServiceImpl.java +++ /dev/null @@ -1,277 +0,0 @@ -package com.ruoyi.iot.service.impl; - -import com.ruoyi.common.constant.ScheduleConstants; -import com.ruoyi.common.exception.job.TaskException; -import com.ruoyi.iot.domain.DeviceJob; -import com.ruoyi.iot.mapper.DeviceJobMapper; -import com.ruoyi.iot.service.IDeviceJobService; -import com.ruoyi.iot.util.quartz.CronUtils; -import com.ruoyi.iot.util.quartz.ScheduleUtils; -import org.quartz.JobDataMap; -import org.quartz.JobKey; -import org.quartz.Scheduler; -import org.quartz.SchedulerException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import javax.annotation.PostConstruct; -import java.util.List; - -/** - * 定时任务调度信息 服务层 - * - * @author kerwincui - */ -@Service -public class DeviceJobServiceImpl implements IDeviceJobService -{ - @Autowired - private Scheduler scheduler; - - @Autowired - private DeviceJobMapper jobMapper; - - /** - * 项目启动时,初始化定时器 主要是防止手动修改数据库导致未同步到定时任务处理(注:不能手动修改数据库ID和任务组名,否则会导致脏数据) - */ - @PostConstruct - public void init() throws SchedulerException, TaskException - { - scheduler.clear(); - List jobList = jobMapper.selectJobAll(); - for (DeviceJob deviceJob : jobList) - { - ScheduleUtils.createScheduleJob(scheduler, deviceJob); - } - } - - /** - * 获取quartz调度器的计划任务列表 - * - * @param job 调度信息 - * @return - */ - @Override - public List selectJobList(DeviceJob job) - { - return jobMapper.selectJobList(job); - } - - /** - * 通过调度任务ID查询调度信息 - * - * @param jobId 调度任务ID - * @return 调度任务对象信息 - */ - @Override - public DeviceJob selectJobById(Long jobId) - { - return jobMapper.selectJobById(jobId); - } - - /** - * 暂停任务 - * - * @param job 调度信息 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public int pauseJob(DeviceJob job) throws SchedulerException - { - Long jobId = job.getJobId(); - String jobGroup = job.getJobGroup(); - job.setStatus(ScheduleConstants.Status.PAUSE.getValue()); - int rows = jobMapper.updateJob(job); - if (rows > 0) - { - scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup)); - } - return rows; - } - - /** - * 恢复任务 - * - * @param job 调度信息 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public int resumeJob(DeviceJob job) throws SchedulerException - { - Long jobId = job.getJobId(); - String jobGroup = job.getJobGroup(); - job.setStatus(ScheduleConstants.Status.NORMAL.getValue()); - int rows = jobMapper.updateJob(job); - if (rows > 0) - { - scheduler.resumeJob(ScheduleUtils.getJobKey(jobId, jobGroup)); - } - return rows; - } - - /** - * 删除任务后,所对应的trigger也将被删除 - * - * @param job 调度信息 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public int deleteJob(DeviceJob job) throws SchedulerException - { - Long jobId = job.getJobId(); - String jobGroup = job.getJobGroup(); - int rows = jobMapper.deleteJobById(jobId); - if (rows > 0) - { - scheduler.deleteJob(ScheduleUtils.getJobKey(jobId, jobGroup)); - } - return rows; - } - - /** - * 批量删除调度信息 - * - * @param jobIds 需要删除的任务ID - * @return 结果 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public void deleteJobByIds(Long[] jobIds) throws SchedulerException - { - for (Long jobId : jobIds) - { - DeviceJob job = jobMapper.selectJobById(jobId); - deleteJob(job); - } - } - - /** - * 根据设备Ids批量删除调度信息 - * - * @param deviceIds 需要删除数据的设备Ids - * @return 结果 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public void deleteJobByDeviceIds(Long[] deviceIds) throws SchedulerException - { - // 查出所有job - List deviceJobs=jobMapper.selectShortJobListByDeviceIds(deviceIds); - - // 批量删除job - int rows=jobMapper.deleteJobByDeviceIds(deviceIds); - - // 批量删除调度器 - for(DeviceJob job:deviceJobs){ - scheduler.deleteJob(ScheduleUtils.getJobKey(job.getJobId(), job.getJobGroup())); - } - - } - - /** - * 任务调度状态修改 - * - * @param job 调度信息 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public int changeStatus(DeviceJob job) throws SchedulerException - { - int rows = 0; - String status = job.getStatus(); - if (ScheduleConstants.Status.NORMAL.getValue().equals(status)) - { - rows = resumeJob(job); - } - else if (ScheduleConstants.Status.PAUSE.getValue().equals(status)) - { - rows = pauseJob(job); - } - return rows; - } - - /** - * 立即运行任务 - * - * @param job 调度信息 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public void run(DeviceJob job) throws SchedulerException - { - Long jobId = job.getJobId(); - String jobGroup = job.getJobGroup(); - DeviceJob properties = selectJobById(job.getJobId()); - // 参数 - JobDataMap dataMap = new JobDataMap(); - dataMap.put(ScheduleConstants.TASK_PROPERTIES, properties); - scheduler.triggerJob(ScheduleUtils.getJobKey(jobId, jobGroup), dataMap); - } - - /** - * 新增任务 - * - * @param deviceJob 调度信息 调度信息 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public int insertJob(DeviceJob deviceJob) throws SchedulerException, TaskException - { - int rows = jobMapper.insertJob(deviceJob); - if (rows > 0) - { - ScheduleUtils.createScheduleJob(scheduler, deviceJob); - } - return rows; - } - - /** - * 更新任务的时间表达式 - * - * @param deviceJob 调度信息 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public int updateJob(DeviceJob deviceJob) throws SchedulerException, TaskException - { - DeviceJob properties = selectJobById(deviceJob.getJobId()); - int rows = jobMapper.updateJob(deviceJob); - if (rows > 0) - { - updateSchedulerJob(deviceJob, properties.getJobGroup()); - } - return rows; - } - - /** - * 更新任务 - * - * @param deviceJob 任务对象 - * @param jobGroup 任务组名 - */ - public void updateSchedulerJob(DeviceJob deviceJob, String jobGroup) throws SchedulerException, TaskException - { - Long jobId = deviceJob.getJobId(); - // 判断是否存在 - JobKey jobKey = ScheduleUtils.getJobKey(jobId, jobGroup); - if (scheduler.checkExists(jobKey)) - { - // 防止创建时存在数据问题 先移除,然后在执行创建操作 - scheduler.deleteJob(jobKey); - } - ScheduleUtils.createScheduleJob(scheduler, deviceJob); - } - - /** - * 校验cron表达式是否有效 - * - * @param cronExpression 表达式 - * @return 结果 - */ - @Override - public boolean checkCronExpressionIsValid(String cronExpression) - { - return CronUtils.isValid(cronExpression); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/DeviceLogServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/DeviceLogServiceImpl.java deleted file mode 100644 index 5b3dc5a3..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/DeviceLogServiceImpl.java +++ /dev/null @@ -1,124 +0,0 @@ -package com.ruoyi.iot.service.impl; - -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.iot.domain.DeviceLog; -import com.ruoyi.iot.tdengine.service.ILogService; -import com.ruoyi.iot.mapper.DeviceLogMapper; -import com.ruoyi.iot.model.MonitorModel; -import com.ruoyi.iot.service.IDeviceLogService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; - -/** - * 设备日志Service业务层处理 - * - * @author kerwincui - * @date 2022-01-13 - */ -@Service -public class DeviceLogServiceImpl implements IDeviceLogService -{ - @Autowired - private DeviceLogMapper deviceLogMapper; - - @Autowired - private ILogService logService; - - /** - * 查询设备日志 - * - * @param logId 设备日志主键 - * @return 设备日志 - */ - @Override - public DeviceLog selectDeviceLogByLogId(Long logId) - { - return deviceLogMapper.selectDeviceLogByLogId(logId); - } - - /** - * 查询设备日志列表 - * - * @param deviceLog 设备日志 - * @return 设备日志 - */ - @Override - public List selectDeviceLogList(DeviceLog deviceLog) - { - return logService.selectDeviceLogList(deviceLog); - } - - /** - * 查询设备监测数据 - * - * @param deviceLog 设备日志 - * @return 设备日志 - */ - @Override - public List selectMonitorList(DeviceLog deviceLog) - { - return logService.selectMonitorList(deviceLog); - } - - /** - * 新增设备日志 - * - * @param deviceLog 设备日志 - * @return 结果 - */ - @Override - public int insertDeviceLog(DeviceLog deviceLog) - { - return logService.saveDeviceLog(deviceLog); - } - - /** - * 修改设备日志 - * - * @param deviceLog 设备日志 - * @return 结果 - */ - @Override - public int updateDeviceLog(DeviceLog deviceLog) - { - return deviceLogMapper.updateDeviceLog(deviceLog); - } - - /** - * 批量删除设备日志 - * - * @param logIds 需要删除的设备日志主键 - * @return 结果 - */ - @Override - public int deleteDeviceLogByLogIds(Long[] logIds) - { - return deviceLogMapper.deleteDeviceLogByLogIds(logIds); - } - - /** - * 根据设备Ids批量删除设备日志 - * - * @param deviceNumber 需要删除数据的设备Ids - * @return 结果 - */ - @Override - public int deleteDeviceLogByDeviceNumber(String deviceNumber) - { - return deviceLogMapper.deleteDeviceLogByDeviceNumber(deviceNumber); - } - - /** - * 删除设备日志信息 - * - * @param logId 设备日志主键 - * @return 结果 - */ - @Override - public int deleteDeviceLogByLogId(Long logId) - { - return deviceLogMapper.deleteDeviceLogByLogId(logId); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/DeviceServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/DeviceServiceImpl.java deleted file mode 100644 index c815cd5e..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/DeviceServiceImpl.java +++ /dev/null @@ -1,1004 +0,0 @@ -package com.ruoyi.iot.service.impl; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.domain.entity.SysRole; -import com.ruoyi.common.core.domain.entity.SysUser; -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.http.HttpUtils; -import com.ruoyi.common.utils.ip.IpUtils; -import com.ruoyi.iot.domain.Device; -import com.ruoyi.iot.domain.DeviceLog; -import com.ruoyi.iot.domain.DeviceUser; -import com.ruoyi.iot.domain.Product; -import com.ruoyi.iot.mqtt.EmqxService; -import com.ruoyi.iot.tdengine.service.ILogService; -import com.ruoyi.iot.mapper.DeviceLogMapper; -import com.ruoyi.iot.mapper.DeviceMapper; -import com.ruoyi.iot.mapper.DeviceUserMapper; -import com.ruoyi.iot.model.*; -import com.ruoyi.iot.model.ThingsModelItem.*; -import com.ruoyi.iot.model.ThingsModels.*; -import com.ruoyi.iot.service.IDeviceService; -import com.ruoyi.iot.service.IProductService; -import com.ruoyi.iot.service.IToolService; -import com.ruoyi.system.service.ISysUserService; -import org.quartz.SchedulerException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.BeanUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Lazy; -import org.springframework.scheduling.annotation.Async; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.stream.Collectors; - -import static com.ruoyi.common.utils.SecurityUtils.getLoginUser; - -/** - * 设备Service业务层处理 - * - * @author kerwincui - * @date 2021-12-16 - */ -@Service -public class DeviceServiceImpl implements IDeviceService { - private static final Logger log = LoggerFactory.getLogger(DeviceServiceImpl.class); - - @Autowired - private DeviceMapper deviceMapper; - - @Autowired - private DeviceUserMapper deviceUserMapper; - - @Autowired - private ThingsModelServiceImpl thingsModelService; - - @Autowired - private DeviceJobServiceImpl deviceJobService; - - @Autowired - private DeviceLogMapper deviceLogMapper; - - @Autowired - private IToolService toolService; - - @Autowired - private IProductService productService; - - @Autowired - private ISysUserService userService; - - @Autowired - private ILogService logService; - - @Autowired - @Lazy - private EmqxService emqxService; - - /** - * 查询设备 - * - * @param deviceId 设备主键 - * @return 设备 - */ - @Override - public Device selectDeviceByDeviceId(Long deviceId) { - return deviceMapper.selectDeviceByDeviceId(deviceId); - } - - /** - * 查询设备统计信息 - * - * @return 设备 - */ - @Override - public DeviceStatistic selectDeviceStatistic() { - Device device = new Device(); - SysUser user = getLoginUser().getUser(); - List roles = user.getRoles(); - for (int i = 0; i < roles.size(); i++) { - if (roles.get(i).getRoleKey().equals("tenant")) { - // 租户查看产品下所有设备 - device.setTenantId(user.getUserId()); - } else if (roles.get(i).getRoleKey().equals("general")) { - // 用户查看自己设备 - device.setUserId(user.getUserId()); - } - } - // 获取设备、产品和告警数量 - DeviceStatistic statistic = deviceMapper.selectDeviceProductAlertCount(device); - if (statistic == null) { - statistic = new DeviceStatistic(); - return statistic; - } - // 获取属性、功能和事件 - DeviceStatistic thingsCount = logService.selectCategoryLogCount(device); - if (thingsCount == null) { - return statistic; - } - // 组合属性、功能、事件和监测数据 - statistic.setPropertyCount(thingsCount.getPropertyCount()); - statistic.setFunctionCount(thingsCount.getFunctionCount()); - statistic.setEventCount(thingsCount.getEventCount()); - statistic.setMonitorCount(thingsCount.getMonitorCount()); - return statistic; - } - - /** - * 根据设备编号查询设备 - * - * @param serialNumber 设备主键 - * @return 设备 - */ - @Override - public Device selectDeviceBySerialNumber(String serialNumber) { - return deviceMapper.selectDeviceBySerialNumber(serialNumber); - } - - /** - * 根据设备编号查询简介设备 - * - * @param serialNumber 设备主键 - * @return 设备 - */ - @Override - public Device selectShortDeviceBySerialNumber(String serialNumber) { - return deviceMapper.selectShortDeviceBySerialNumber(serialNumber); - } - - /** - * 根据设备编号查询设备认证信息 - * - * @param model 设备编号和产品ID - * @return 设备 - */ - @Override - public ProductAuthenticateModel selectProductAuthenticate(AuthenticateInputModel model) { - return deviceMapper.selectProductAuthenticate(model); - } - - /** - * 查询设备 - * - * @param deviceId 设备主键 - * @return 设备 - */ - @Override - public DeviceShortOutput selectDeviceRunningStatusByDeviceId(Long deviceId) { - DeviceShortOutput device = deviceMapper.selectDeviceRunningStatusByDeviceId(deviceId); - JSONObject thingsModelObject = JSONObject.parseObject(thingsModelService.getCacheThingsModelByProductId(device.getProductId())); - JSONArray properties = thingsModelObject.getJSONArray("properties"); - JSONArray functions = thingsModelObject.getJSONArray("functions"); - // 物模型转换为对象中的不同类别集合 - convertJsonToCategoryList(properties, device, false, false); - convertJsonToCategoryList(functions, device, false, false); - device.setThingsModelValue(""); - return device; - } - - - /** - * 更新设备的物模型 - * - * @param input 设备ID和物模型值 - * @param type 1=属性 2=功能 - * @return 设备 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public int reportDeviceThingsModelValue(ThingsModelValuesInput input, int type, boolean isShadow) { - // 查询物模型 - String thingsModels = thingsModelService.getCacheThingsModelByProductId(input.getProductId()); - JSONObject thingsModelObject = JSONObject.parseObject(thingsModels); - List valueList = null; - if (type == 1) { - JSONArray properties = thingsModelObject.getJSONArray("properties"); - valueList = properties.toJavaList(ThingsModelValueItemDto.class); - } else if (type == 2) { - JSONArray functions = thingsModelObject.getJSONArray("functions"); - valueList = functions.toJavaList(ThingsModelValueItemDto.class); - } - - // 查询物模型值 - ThingsModelValuesOutput deviceThings = deviceMapper.selectDeviceThingsModelValueBySerialNumber(input.getDeviceNumber()); - List thingsModelValues = JSONObject.parseArray(deviceThings.getThingsModelValue(), ThingsModelValueItem.class); - - for (int i = 0; i < input.getThingsModelValueRemarkItem().size(); i++) { - // 赋值 - for (int j = 0; j < thingsModelValues.size(); j++) { - if (input.getThingsModelValueRemarkItem().get(i).getId().equals(thingsModelValues.get(j).getId())) { - // 影子模式只更新影子值 - if (!isShadow) { - thingsModelValues.get(j).setValue(String.valueOf(input.getThingsModelValueRemarkItem().get(i).getValue())); - } - thingsModelValues.get(j).setShadow(String.valueOf(input.getThingsModelValueRemarkItem().get(i).getValue())); - break; - } - } - - //日志 - for (int k = 0; k < valueList.size(); k++) { - if (valueList.get(k).getId().equals(input.getThingsModelValueRemarkItem().get(i).getId())) { - valueList.get(k).setValue(input.getThingsModelValueRemarkItem().get(i).getValue()); - // TODO 场景联动、告警规则匹配处理 - - // 添加到设备日志 - DeviceLog deviceLog = new DeviceLog(); - deviceLog.setDeviceId(deviceThings.getDeviceId()); - deviceLog.setSerialNumber(deviceThings.getSerialNumber()); - deviceLog.setDeviceName(deviceThings.getDeviceName()); - deviceLog.setLogValue(input.getThingsModelValueRemarkItem().get(i).getValue()); - deviceLog.setRemark(input.getThingsModelValueRemarkItem().get(i).getRemark()); - deviceLog.setIdentity(input.getThingsModelValueRemarkItem().get(i).getId()); - deviceLog.setIsMonitor(valueList.get(k).getIsMonitor() == null ? 0 : valueList.get(k).getIsMonitor()); - deviceLog.setLogType(type); - deviceLog.setUserId(deviceThings.getUserId()); - deviceLog.setUserName(deviceThings.getUserName()); - deviceLog.setTenantId(deviceThings.getTenantId()); - deviceLog.setTenantName(deviceThings.getTenantName()); - deviceLog.setCreateTime(DateUtils.getNowDate()); - // 1=影子模式,2=在线模式,3=其他 - deviceLog.setMode(isShadow ? 1 : 2); - logService.saveDeviceLog(deviceLog); - break; - } - } - } - input.setStringValue(JSONObject.toJSONString(thingsModelValues)); - input.setDeviceId(deviceThings.getDeviceId()); - return deviceMapper.updateDeviceThingsModelValue(input); - } - - /** - * 查询设备列表 - * - * @param device 设备 - * @return 设备 - */ - @Override - public List selectDeviceList(Device device) { - SysUser user = getLoginUser().getUser(); - List roles = user.getRoles(); - for (int i = 0; i < roles.size(); i++) { - if (roles.get(i).getRoleKey().equals("tenant")) { - // 租户查看产品下所有设备 - device.setTenantId(user.getUserId()); - } else if (roles.get(i).getRoleKey().equals("general")) { - // 用户查看自己设备 - device.setUserId(user.getUserId()); - } - } - return deviceMapper.selectDeviceList(device); - } - - /** - * 查询未分配授权码设备列表 - * - * @param device 设备 - * @return 设备 - */ - @Override - public List selectUnAuthDeviceList(Device device) { - SysUser user = getLoginUser().getUser(); - List roles = user.getRoles(); - for (int i = 0; i < roles.size(); i++) { - if (roles.get(i).getRoleKey().equals("tenant")) { - // 租户查看产品下所有设备 - device.setTenantId(user.getUserId()); - } else if (roles.get(i).getRoleKey().equals("general")) { - // 用户查看自己设备 - device.setUserId(user.getUserId()); - } - } - return deviceMapper.selectUnAuthDeviceList(device); - } - - /** - * 查询分组可添加设备分页列表(分组用户与设备用户匹配) - * - * @param device 设备 - * @return 设备 - */ - @Override - public List selectDeviceListByGroup(Device device) { - SysUser user = getLoginUser().getUser(); - List roles = user.getRoles(); - for (int i = 0; i < roles.size(); i++) { - if (roles.get(i).getRoleKey().equals("tenant")) { - // 租户查看产品下所有设备 - device.setTenantId(user.getUserId()); - } else if (roles.get(i).getRoleKey().equals("general")) { - // 用户查看自己设备 - device.setUserId(user.getUserId()); - } - } - return deviceMapper.selectDeviceListByGroup(device); - } - - /** - * 查询所有设备简短列表 - * - * @return 设备 - */ - @Override - public List selectAllDeviceShortList() { - Device device = new Device(); - SysUser user = getLoginUser().getUser(); - List roles = user.getRoles(); - for (int i = 0; i < roles.size(); i++) { - if (roles.get(i).getRoleKey().equals("tenant")) { - // 租户查看产品下所有设备 - device.setTenantId(user.getUserId()); - break; - } else if (roles.get(i).getRoleKey().equals("general")) { - // 用户查看自己设备 - device.setUserId(user.getUserId()); - break; - } - } - return deviceMapper.selectAllDeviceShortList(device); - } - - /** - * 查询设备简短列表 - * - * @param device 设备 - * @return 设备 - */ - @Override - public List selectDeviceShortList(Device device) { - SysUser user = getLoginUser().getUser(); - List roles = user.getRoles(); - for (int i = 0; i < roles.size(); i++) { - if (roles.get(i).getRoleKey().equals("tenant")) { - // 租户查看产品下所有设备 - device.setTenantId(user.getUserId()); - break; - } else if (roles.get(i).getRoleKey().equals("general")) { - // 用户查看自己设备 - device.setUserId(user.getUserId()); - break; - } - } - List deviceList = deviceMapper.selectDeviceShortList(device); - for (int i = 0; i < deviceList.size(); i++) { - JSONObject thingsModelObject = JSONObject.parseObject(thingsModelService.getCacheThingsModelByProductId(deviceList.get(i).getProductId())); - JSONArray properties = thingsModelObject.getJSONArray("properties"); - JSONArray functions = thingsModelObject.getJSONArray("functions"); - // 物模型转换为对象中的不同类别集合 - convertJsonToCategoryList(properties, deviceList.get(i), true, false); - convertJsonToCategoryList(functions, deviceList.get(i), true, false); - // 置空物模型,已分配到不同类型中 - deviceList.get(i).setThingsModelValue(""); - } - return deviceList; - } - - - /** - * Json物模型集合转换为对象中的分类集合 - * - * @param jsonArray 物模型集合 - * @param isOnlyTop 是否只显示置顶数据 - * @param isOnlyRead 是否设置为只读 - * @param device 设备 - */ - @Async - public void convertJsonToCategoryList(JSONArray jsonArray, DeviceShortOutput device, boolean isOnlyTop, boolean isOnlyRead) { - // 获取物模型值 - JSONArray thingsValueArray = JSONObject.parseArray(device.getThingsModelValue()); - for (int i = 0; i < jsonArray.size(); i++) { - JSONObject thingsJson = jsonArray.getJSONObject(i); - JSONObject datatypeJson = thingsJson.getJSONObject("datatype"); - ThingsModelItemBase thingsModel = new ThingsModelItemBase(); - thingsModel.setIsTop(thingsJson.getInteger("isTop")); - // 只显示isTop数据 - if (thingsModel.getIsTop() == 0 && isOnlyTop == true) { - continue; - } - - thingsModel.setId(thingsJson.getString("id")); - thingsModel.setName(thingsJson.getString("name")); - thingsModel.setIsMonitor(thingsJson.getInteger("isMonitor") == null ? 0 : thingsJson.getInteger("isMonitor")); - thingsModel.setType(datatypeJson.getString("type")); - thingsModel.setValue(""); - // 获取value - for (int j = 0; j < thingsValueArray.size(); j++) { - if (thingsValueArray.getJSONObject(j).getString("id").equals(thingsModel.getId())) { - String value = thingsValueArray.getJSONObject(j).getString("value"); - String shadow = thingsValueArray.getJSONObject(j).getString("shadow"); - thingsModel.setValue(value); - thingsModel.setShadow(shadow); - // bool 类型默认值为0,解决移动端报错问题 - if (thingsModel.getType().equals("bool")) { - thingsModel.setValue(value.equals("") ? "0" : value); - thingsModel.setShadow(shadow.equals("") ? "0" : shadow); - } - break; - } - } - // 根据分类不同,存储到不同集合 - if (datatypeJson.getString("type").equals("decimal")) { - DecimalModelOutput model = new DecimalModelOutput(); - BeanUtils.copyProperties(thingsModel, model); - model.setMax(datatypeJson.getBigDecimal("max")); - model.setMin(datatypeJson.getBigDecimal("min")); - model.setStep(datatypeJson.getBigDecimal("step")); - model.setUnit(datatypeJson.getString("unit")); - if (model.getIsMonitor() == 1 || isOnlyRead == true) { - ReadOnlyModelOutput readonlyModel = new ReadOnlyModelOutput(); - BeanUtils.copyProperties(model, readonlyModel); - device.getReadOnlyList().add(readonlyModel); - } else { - device.getDecimalList().add(model); - } - } else if (datatypeJson.getString("type").equals("integer")) { - IntegerModelOutput model = new IntegerModelOutput(); - BeanUtils.copyProperties(thingsModel, model); - model.setMax(datatypeJson.getBigDecimal("max")); - model.setMin(datatypeJson.getBigDecimal("min")); - model.setStep(datatypeJson.getBigDecimal("step")); - model.setUnit(datatypeJson.getString("unit")); - if (model.getIsMonitor() == 1 || isOnlyRead == true) { - ReadOnlyModelOutput readonlyModel = new ReadOnlyModelOutput(); - BeanUtils.copyProperties(model, readonlyModel); - device.getReadOnlyList().add(readonlyModel); - } else { - device.getIntegerList().add(model); - } - } else if (datatypeJson.getString("type").equals("bool")) { - BoolModelOutput model = new BoolModelOutput(); - BeanUtils.copyProperties(thingsModel, model); - model.setFalseText(datatypeJson.getString("falseText")); - model.setTrueText(datatypeJson.getString("trueText")); - if (model.getIsMonitor() == 1 || isOnlyRead == true) { - ReadOnlyModelOutput readonlyModel = new ReadOnlyModelOutput(); - BeanUtils.copyProperties(model, readonlyModel); - device.getReadOnlyList().add(readonlyModel); - } else { - device.getBoolList().add(model); - } - } else if (datatypeJson.getString("type").equals("string")) { - StringModelOutput model = new StringModelOutput(); - BeanUtils.copyProperties(thingsModel, model); - model.setMaxLength(datatypeJson.getInteger("maxLength")); - if (model.getIsMonitor() == 1 || isOnlyRead == true) { - ReadOnlyModelOutput readonlyModel = new ReadOnlyModelOutput(); - BeanUtils.copyProperties(model, readonlyModel); - device.getReadOnlyList().add(readonlyModel); - } else { - device.getStringList().add(model); - } - } else if (datatypeJson.getString("type").equals("array")) { - ArrayModelOutput model = new ArrayModelOutput(); - BeanUtils.copyProperties(thingsModel, model); - model.setArrayType(datatypeJson.getString("arrayType")); - if (model.getIsMonitor() == 1 || isOnlyRead == true) { - ReadOnlyModelOutput readonlyModel = new ReadOnlyModelOutput(); - BeanUtils.copyProperties(model, readonlyModel); - device.getReadOnlyList().add(readonlyModel); - } else { - device.getArrayList().add(model); - } - } else if (datatypeJson.getString("type").equals("enum")) { - EnumModelOutput model = new EnumModelOutput(); - BeanUtils.copyProperties(thingsModel, model); - List enumItemList = JSONObject.parseArray(datatypeJson.getString("enumList"), EnumItemOutput.class); - model.setEnumList(enumItemList); - if (model.getIsMonitor() == 1 || isOnlyRead == true) { - ReadOnlyModelOutput readonlyModel = new ReadOnlyModelOutput(); - BeanUtils.copyProperties(model, readonlyModel); - device.getReadOnlyList().add(readonlyModel); - } else { - device.getEnumList().add(model); - } - } - } - // 排序 - device.setReadOnlyList(device.getReadOnlyList().stream().sorted(Comparator.comparing(ThingsModelItemBase::getIsMonitor).reversed()).collect(Collectors.toList())); - } - - /** - * 新增设备 - * - * @param device 设备 - * @return 结果 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public Device insertDevice(Device device) { - // 设备编号唯一检查 - Device existDevice = deviceMapper.selectDeviceBySerialNumber(device.getSerialNumber()); - if (existDevice != null) { - log.error("设备编号:" + device.getSerialNumber() + "已经存在了,新增设备失败"); - return device; - } - SysUser sysUser = getLoginUser().getUser(); - //添加设备 - device.setCreateTime(DateUtils.getNowDate()); - device.setThingsModelValue(JSONObject.toJSONString(getThingsModelDefaultValue(device.getProductId()))); - device.setUserId(sysUser.getUserId()); - device.setUserName(sysUser.getUserName()); - device.setRssi(0); - // 设置租户 - Product product = productService.selectProductByProductId(device.getProductId()); - device.setTenantId(product.getTenantId()); - device.setTenantName(product.getTenantName()); - device.setImgUrl(product.getImgUrl()); - // 随机经纬度和地址 - SysUser user = getLoginUser().getUser(); - device.setNetworkIp(user.getLoginIp()); - setLocation(user.getLoginIp(), device); - - deviceMapper.insertDevice(device); - // 添加设备用户 - DeviceUser deviceUser = new DeviceUser(); - deviceUser.setUserId(sysUser.getUserId()); - deviceUser.setUserName(sysUser.getUserName()); - deviceUser.setPhonenumber(sysUser.getPhonenumber()); - deviceUser.setDeviceId(device.getDeviceId()); - deviceUser.setDeviceName(device.getDeviceName()); - deviceUser.setTenantId(product.getTenantId()); - deviceUser.setTenantName(product.getTenantName()); - deviceUser.setIsOwner(1); - deviceUser.setCreateTime(DateUtils.getNowDate()); - deviceUserMapper.insertDeviceUser(deviceUser); - return device; - } - - /** - * 设备关联用户 - * - * @param deviceRelateUserInput - * @return 结果 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public AjaxResult deviceRelateUser(DeviceRelateUserInput deviceRelateUserInput) { - // 查询用户信息 - SysUser sysUser = userService.selectUserById(deviceRelateUserInput.getUserId()); - for (int i = 0; i < deviceRelateUserInput.getDeviceNumberAndProductIds().size(); i++) { - Device existDevice = deviceMapper.selectDeviceBySerialNumber(deviceRelateUserInput.getDeviceNumberAndProductIds().get(i).getDeviceNumber()); - if (existDevice != null) { - if (existDevice.getUserId().longValue() == deviceRelateUserInput.getUserId().longValue()) { - return AjaxResult.error("用户已经拥有设备:" + existDevice.getDeviceName() + ", 设备编号:" + existDevice.getSerialNumber()); - } - // 先删除设备的所有用户 - deviceUserMapper.deleteDeviceUserByDeviceId(new UserIdDeviceIdModel(null, existDevice.getDeviceId())); - // 添加新的设备用户 - DeviceUser deviceUser = new DeviceUser(); - deviceUser.setUserId(sysUser.getUserId()); - deviceUser.setUserName(sysUser.getUserName()); - deviceUser.setPhonenumber(sysUser.getPhonenumber()); - deviceUser.setDeviceId(existDevice.getDeviceId()); - deviceUser.setDeviceName(existDevice.getDeviceName()); - deviceUser.setTenantId(existDevice.getTenantId()); - deviceUser.setTenantName(existDevice.getTenantName()); - deviceUser.setIsOwner(1); - deviceUser.setCreateTime(DateUtils.getNowDate()); - deviceUserMapper.insertDeviceUser(deviceUser); - // 更新设备用户信息 - existDevice.setUserId(deviceRelateUserInput.getUserId()); - existDevice.setUserName(sysUser.getUserName()); - deviceMapper.updateDevice(existDevice); - } else { - // 自动添加设备 - int result = insertDeviceAuto( - deviceRelateUserInput.getDeviceNumberAndProductIds().get(i).getDeviceNumber(), - deviceRelateUserInput.getUserId(), - deviceRelateUserInput.getDeviceNumberAndProductIds().get(i).getProductId()); - if (result == 0) { - return AjaxResult.error("设备不存在,自动添加设备时失败,请检查产品编号是否正确"); - } - } - } - return AjaxResult.success("添加设备成功"); - } - - /** - * 设备认证后自动添加设备 - * - * @return 结果 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public int insertDeviceAuto(String serialNumber, Long userId, Long productId) { - // 设备编号唯一检查 - int count = deviceMapper.selectDeviceCountBySerialNumber(serialNumber); - if (count != 0) { - log.error("设备编号:" + serialNumber + "已经存在了,新增设备失败"); - return 0; - } - Device device = new Device(); - device.setSerialNumber(serialNumber); - SysUser user = userService.selectUserById(userId); - device.setUserId(userId); - device.setUserName(user.getUserName()); - device.setFirmwareVersion(BigDecimal.valueOf(1.0)); - // 设备状态(1-未激活,2-禁用,3-在线,4-离线) - device.setStatus(1); - device.setActiveTime(DateUtils.getNowDate()); - device.setIsShadow(0); - device.setRssi(0); - // 1-自动定位,2-设备定位,3-自定义位置 - device.setLocationWay(1); - device.setCreateTime(DateUtils.getNowDate()); - device.setThingsModelValue(JSONObject.toJSONString(getThingsModelDefaultValue(productId))); - // 随机位置 - device.setLongitude(BigDecimal.valueOf(116.23 - (Math.random() * 15))); - device.setLatitude(BigDecimal.valueOf(39.54 - (Math.random() * 15))); - device.setNetworkAddress("中国"); - device.setNetworkIp("127.0.0.1"); - // 设置租户 - Product product = productService.selectProductByProductId(productId); - if (product == null) { - log.error("自动添加设备时,根据产品ID查找不到对应产品"); - return 0; - } - int random = (int) (Math.random() * (90)) + 10; - device.setDeviceName(product.getProductName() + random); - device.setTenantId(product.getTenantId()); - device.setTenantName(product.getTenantName()); - device.setImgUrl(product.getImgUrl()); - device.setProductId(product.getProductId()); - device.setProductName(product.getProductName()); - deviceMapper.insertDevice(device); - - // 添加设备用户 - DeviceUser deviceUser = new DeviceUser(); - deviceUser.setUserId(userId); - deviceUser.setUserName(user.getUserName()); - deviceUser.setPhonenumber(user.getPhonenumber()); - deviceUser.setDeviceId(device.getDeviceId()); - deviceUser.setDeviceName(device.getDeviceName()); - deviceUser.setTenantId(product.getTenantId()); - deviceUser.setTenantName(product.getTenantName()); - deviceUser.setIsOwner(1); - return deviceUserMapper.insertDeviceUser(deviceUser); - } - - /** - * 获取物模型值 - * - * @param productId - * @return - */ - private List getThingsModelDefaultValue(Long productId) { - // 获取物模型,设置默认值 - String thingsModels = thingsModelService.getCacheThingsModelByProductId(productId); - JSONObject thingsModelObject = JSONObject.parseObject(thingsModels); - JSONArray properties = thingsModelObject.getJSONArray("properties"); - JSONArray functions = thingsModelObject.getJSONArray("functions"); - List valueList = properties.toJavaList(ThingsModelValueItem.class); - valueList.addAll(functions.toJavaList(ThingsModelValueItem.class)); - valueList.forEach(x -> { - x.setValue(""); - x.setShadow(""); - }); - return valueList; - } - - /** - * 获取设备设置的影子 - * - * @param device - * @return - */ - @Override - public ThingsModelShadow getDeviceShadowThingsModel(Device device) { - // 物模型 - String thingsModels = thingsModelService.getCacheThingsModelByProductId(device.getProductId()); - JSONObject thingsModelObject = JSONObject.parseObject(thingsModels); - JSONArray properties = thingsModelObject.getJSONArray("properties"); - JSONArray functions = thingsModelObject.getJSONArray("functions"); - - // 物模型值 - List thingsModelValueItems = JSONObject.parseArray(device.getThingsModelValue(), ThingsModelValueItem.class); - - // 查询出设置的影子值 - List shadowList = new ArrayList<>(); - for (int i = 0; i < thingsModelValueItems.size(); i++) { - if (!thingsModelValueItems.get(i).getValue().equals(thingsModelValueItems.get(i).getShadow())) { - shadowList.add(thingsModelValueItems.get(i)); - System.out.println("添加影子:" + thingsModelValueItems.get(i).getId()); - } - } - ThingsModelShadow shadow = new ThingsModelShadow(); - for (int i = 0; i < shadowList.size(); i++) { - boolean isGetValue = false; - for (int j = 0; j < properties.size(); j++) { - if (properties.getJSONObject(j).getInteger("isMonitor") == 0 && properties.getJSONObject(j).getString("id").equals(shadowList.get(i).getId())) { - IdentityAndName item = new IdentityAndName(shadowList.get(i).getId(), shadowList.get(i).getShadow()); - shadow.getProperties().add(item); - System.out.println("添加影子属性:" + item.getId()); - isGetValue = true; - break; - } - } - if (!isGetValue) { - for (int k = 0; k < functions.size(); k++) { - if (functions.getJSONObject(k).getString("id").equals(shadowList.get(i).getId())) { - IdentityAndName item = new IdentityAndName(shadowList.get(i).getId(), shadowList.get(i).getShadow()); - shadow.getFunctions().add(item); - System.out.println("添加影子功能:" + item.getId()); - break; - } - } - } - } - return shadow; - } - - - /** - * 修改设备 - * - * @param device 设备 - * @return 结果 - */ - @Override - public AjaxResult updateDevice(Device device) { - // 设备编号唯一检查 - Device oldDevice = deviceMapper.selectDeviceByDeviceId(device.getDeviceId()); - if (!oldDevice.getSerialNumber().equals(device.getSerialNumber())) { - Device existDevice = deviceMapper.selectDeviceBySerialNumber(device.getSerialNumber()); - if (existDevice != null) { - log.error("设备编号:" + device.getSerialNumber() + " 已经存在,新增设备失败"); - return AjaxResult.success("设备编号:" + device.getSerialNumber() + " 已经存在,修改失败", 0); - } - } - device.setUpdateTime(DateUtils.getNowDate()); - // 未激活状态,可以修改产品以及物模型值 - if (device.getStatus() == 1) { - device.setThingsModelValue(JSONObject.toJSONString(getThingsModelDefaultValue(device.getProductId()))); - } else { - device.setProductId(null); - device.setProductName(null); - } - deviceMapper.updateDevice(device); - // 设备取消禁用 - if (oldDevice.getStatus() == 2 && device.getStatus() == 4) { - // 发布设备信息 - emqxService.publishInfo(oldDevice.getProductId(), oldDevice.getSerialNumber()); - } - return AjaxResult.success("修改成功", 1); - } - - /** - * 生成设备唯一编号 - * - * @return 结果 - */ - @Override - public String generationDeviceNum() { - // 设备编号:D + userId + 15位随机字母和数字 - SysUser user = getLoginUser().getUser(); - String number = "D" + user.getUserId().toString() + toolService.getStringRandom(10); - int count = deviceMapper.getDeviceNumCount(number); - if (count == 0) { - return number; - } else { - generationDeviceNum(); - } - return ""; - } - - - /** - * @param device 设备状态和定位更新 - * @return 结果 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public int updateDeviceStatusAndLocation(Device device, String ipAddress) { - // 设置自动定位和状态 - if (ipAddress != "") { - if (device.getActiveTime() == null) { - device.setActiveTime(DateUtils.getNowDate()); - } - // 定位方式(1=ip自动定位,2=设备定位,3=自定义) - if (device.getLocationWay() == 1) { - device.setNetworkIp(ipAddress); - setLocation(ipAddress, device); - } - } - int result = deviceMapper.updateDeviceStatus(device); - - // 添加到设备日志 - DeviceLog deviceLog = new DeviceLog(); - deviceLog.setDeviceId(device.getDeviceId()); - deviceLog.setDeviceName(device.getDeviceName()); - deviceLog.setSerialNumber(device.getSerialNumber()); - deviceLog.setIsMonitor(0); - deviceLog.setUserId(device.getUserId()); - deviceLog.setUserName(device.getUserName()); - deviceLog.setTenantId(device.getTenantId()); - deviceLog.setTenantName(device.getTenantName()); - deviceLog.setCreateTime(DateUtils.getNowDate()); - // 日志模式 1=影子模式,2=在线模式,3=其他 - deviceLog.setMode(3); - if (device.getStatus() == 3) { - deviceLog.setLogValue("1"); - deviceLog.setRemark("设备上线"); - deviceLog.setIdentity("online"); - deviceLog.setLogType(5); - } else if (device.getStatus() == 4) { - deviceLog.setLogValue("0"); - deviceLog.setRemark("设备离线"); - deviceLog.setIdentity("offline"); - deviceLog.setLogType(6); - } - logService.saveDeviceLog(deviceLog); - return result; - } - - /** - * @param device 设备状态 - * @return 结果 - */ - @Override - public int updateDeviceStatus(Device device) { - return deviceMapper.updateDeviceStatus(device); - } - - /** - * 根据IP获取地址 - * - * @param ip - * @return - */ - private void setLocation(String ip, Device device) { - String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp"; - String address = "未知地址"; - // 内网不查询 - if (IpUtils.internalIp(ip)) { - device.setNetworkAddress("内网IP"); - } - try { - String rspStr = HttpUtils.sendGet(IP_URL, "ip=" + ip + "&json=true", Constants.GBK); - if (!StringUtils.isEmpty(rspStr)) { - JSONObject obj = JSONObject.parseObject(rspStr); - device.setNetworkAddress(obj.getString("addr")); - System.out.println(device.getSerialNumber() + "- 设置地址:" + obj.getString("addr")); - // 查询经纬度 - setLatitudeAndLongitude(obj.getString("city"), device); - } - } catch (Exception e) { - log.error(e.getMessage()); - } - } - - /** - * 设置经纬度 - * - * @param city - */ - private void setLatitudeAndLongitude(String city, Device device) { - String BAIDU_URL = "https://api.map.baidu.com/geocoder"; - String baiduResponse = HttpUtils.sendGet(BAIDU_URL, "address=" + city + "&output=json", Constants.GBK); - if (!StringUtils.isEmpty(baiduResponse)) { - JSONObject baiduObject = JSONObject.parseObject(baiduResponse); - JSONObject location = baiduObject.getJSONObject("result").getJSONObject("location"); - device.setLongitude(location.getBigDecimal("lng")); - device.setLatitude(location.getBigDecimal("lat")); - System.out.println(device.getSerialNumber() + "- 设置经度:" + location.getBigDecimal("lng") + ",设置纬度:" + location.getBigDecimal("lat")); - } - } - - /** - * 上报设备信息 - * - * @param device 设备 - * @return 结果 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public int reportDevice(Device device, Device deviceEntity) { - // 未采用设备定位则清空定位,定位方式(1=ip自动定位,2=设备定位,3=自定义) - if (deviceEntity.getLocationWay() != 2) { - device.setLatitude(null); - device.setLongitude(null); - } - int result = 0; - if (deviceEntity != null) { - // 联网方式为Wifi的需要更新用户信息(1=wifi、2=蜂窝(2G/3G/4G/5G)、3=以太网、4=其他) - Product product = productService.selectProductByProductId(deviceEntity.getProductId()); - if (product.getNetworkMethod() == 1) { - if (deviceEntity.getUserId().longValue() != device.getUserId().longValue()) { - // 先删除设备的所有用户 - deviceUserMapper.deleteDeviceUserByDeviceId(new UserIdDeviceIdModel(null, deviceEntity.getDeviceId())); - // 添加新的设备用户 - SysUser sysUser = userService.selectUserById(device.getUserId()); - DeviceUser deviceUser = new DeviceUser(); - deviceUser.setUserId(sysUser.getUserId()); - deviceUser.setUserName(sysUser.getUserName()); - deviceUser.setPhonenumber(sysUser.getPhonenumber()); - deviceUser.setDeviceId(deviceEntity.getDeviceId()); - deviceUser.setDeviceName(deviceEntity.getDeviceName()); - deviceUser.setTenantId(deviceEntity.getTenantId()); - deviceUser.setTenantName(deviceEntity.getTenantName()); - deviceUser.setIsOwner(1); - deviceUser.setCreateTime(DateUtils.getNowDate()); - deviceUserMapper.insertDeviceUser(deviceUser); - // 更新设备用户信息 - device.setUserId(device.getUserId()); - device.setUserName(sysUser.getUserName()); - } - }else{ - // 其他联网设备不更新用户信息 - device.setUserId(null); - } - device.setUpdateTime(DateUtils.getNowDate()); - if (deviceEntity.getActiveTime() == null || deviceEntity.getActiveTime().equals("")) { - device.setActiveTime(DateUtils.getNowDate()); - } - // 不更新物模型 - device.setThingsModelValue(null); - result = deviceMapper.updateDeviceBySerialNumber(device); - } - return result; - } - - /** - * 重置设备状态 - * - * @return 结果 - */ - @Override - public int resetDeviceStatus(String deviceNum) { - int result = deviceMapper.resetDeviceStatus(deviceNum); - return result; - } - - /** - * 删除设备 - * - * @param deviceId 需要删除的设备主键 - * @return 结果 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public int deleteDeviceByDeviceId(Long deviceId) throws SchedulerException { - SysUser user = getLoginUser().getUser(); - // 是否为普通用户,普通用户如果不是设备所有者,只能删除设备用户和用户自己的设备关联分组信息 - boolean isGeneralUser = false; - List roles = user.getRoles(); - for (int i = 0; i < roles.size(); i++) { - if (roles.get(i).getRoleKey().equals("general")) { - isGeneralUser = true; - break; - } - } - Device device = deviceMapper.selectDeviceByDeviceId(deviceId); - if (isGeneralUser && device.getUserId().longValue() != user.getUserId()) { - // 删除用户分组中的设备 普通用户,且不是设备所有者。 - deviceMapper.deleteDeviceGroupByDeviceId(new UserIdDeviceIdModel(user.getUserId(), deviceId)); - // 删除用户的设备用户信息。 - deviceUserMapper.deleteDeviceUserByDeviceId(new UserIdDeviceIdModel(user.getUserId(), deviceId)); - } else { - // 删除设备分组。 租户、管理员和设备所有者 - deviceMapper.deleteDeviceGroupByDeviceId(new UserIdDeviceIdModel(null, deviceId)); - // 删除设备用户。 - deviceUserMapper.deleteDeviceUserByDeviceId(new UserIdDeviceIdModel(null, deviceId)); - // 删除定时任务 - deviceJobService.deleteJobByDeviceIds(new Long[]{deviceId}); - // 批量删除设备日志 - logService.deleteDeviceLogByDeviceNumber(device.getSerialNumber()); - // TODO 删除设备告警记录 - - // 删除设备 - deviceMapper.deleteDeviceByDeviceIds(new Long[]{deviceId}); - } - return 1; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/DeviceUserServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/DeviceUserServiceImpl.java deleted file mode 100644 index a829c827..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/DeviceUserServiceImpl.java +++ /dev/null @@ -1,134 +0,0 @@ -package com.ruoyi.iot.service.impl; - -import com.ruoyi.common.core.domain.entity.SysUser; -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.iot.domain.DeviceUser; -import com.ruoyi.iot.mapper.DeviceUserMapper; -import com.ruoyi.iot.model.UserIdDeviceIdModel; -import com.ruoyi.iot.service.IDeviceUserService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.dao.DuplicateKeyException; -import org.springframework.stereotype.Service; - -import java.util.List; - -import static com.ruoyi.common.utils.SecurityUtils.getLoginUser; - -/** - * 设备用户Service业务层处理 - * - * @author kerwincui - * @date 2021-12-16 - */ -@Service -public class DeviceUserServiceImpl implements IDeviceUserService -{ - @Autowired - private DeviceUserMapper deviceUserMapper; - - /** - * 查询设备用户 - * - * @param deviceId 设备用户主键 - * @return 设备用户 - */ - @Override - public List selectDeviceUserByDeviceId(Long deviceId) - { - return deviceUserMapper.selectDeviceUserByDeviceId(deviceId); - } - - /** - * 查询设备用户列表 - * - * @param deviceUser 设备用户 - * @return 设备用户 - */ - @Override - public List selectDeviceUserList(DeviceUser deviceUser) - { - return deviceUserMapper.selectDeviceUserList(deviceUser); - } - - /** - * 新增设备用户 - * - * @param deviceUser 设备用户 - * @return 结果 - */ - @Override - public int insertDeviceUser(DeviceUser deviceUser) - { - List deviceUsers = selectDeviceUserList(deviceUser); - if (!deviceUsers.isEmpty()) { throw new RuntimeException("该用户已添加, 禁止重复添加");} - deviceUser.setCreateTime(DateUtils.getNowDate()); - deviceUser.setIsOwner(0); - SysUser sysUser = getLoginUser().getUser(); - deviceUser.setTenantId(sysUser.getUserId()); - deviceUser.setTenantName(sysUser.getUserName()); - return deviceUserMapper.insertDeviceUser(deviceUser); - } - - /** - * 修改设备用户 - * - * @param deviceUser 设备用户 - * @return 结果 - */ - @Override - public int updateDeviceUser(DeviceUser deviceUser) - { - deviceUser.setUpdateTime(DateUtils.getNowDate()); - return deviceUserMapper.updateDeviceUser(deviceUser); - } - - /** - * 批量删除设备用户 - * - * @param deviceIds 需要删除的设备用户主键 - * @return 结果 - */ - @Override - public int deleteDeviceUserByDeviceIds(Long[] deviceIds) - { - return deviceUserMapper.deleteDeviceUserByDeviceIds(deviceIds); - } - - /** - * 删除设备用户信息 - * - * @param deviceId 设备用户主键 - * @return 结果 - */ - @Override - public int deleteDeviceUserByDeviceId(Long deviceId) - { - return deviceUserMapper.deleteDeviceUserByDeviceId(new UserIdDeviceIdModel(null,deviceId)); - } - - @Override - public int insertDeviceUserList(List deviceUsers) { - try { - deviceUsers.forEach(deviceUser -> { - deviceUser.setCreateTime(DateUtils.getNowDate()); - deviceUser.setIsOwner(0); - SysUser sysUser = getLoginUser().getUser(); - deviceUser.setTenantId(sysUser.getUserId()); - deviceUser.setTenantName(sysUser.getUserName()); - }); - return deviceUserMapper.insertDeviceUserList(deviceUsers); - } catch (DuplicateKeyException e) { - throw new RuntimeException("存在设备已经与用户绑定"); - } - } - - @Override - public DeviceUser selectDeviceUserByDeviceIdAndUserId(Long deviceId, Long userId) { - return deviceUserMapper.selectDeviceUserByDeviceIdAndUserId(deviceId, userId); - } - - @Override - public int deleteDeviceUser(DeviceUser deviceUser) { - return deviceUserMapper.deleteDeviceUser(deviceUser); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/FirmwareServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/FirmwareServiceImpl.java deleted file mode 100644 index 87667814..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/FirmwareServiceImpl.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.ruoyi.iot.service.impl; - -import java.util.List; - -import com.ruoyi.common.core.domain.entity.SysRole; -import com.ruoyi.common.core.domain.entity.SysUser; -import com.ruoyi.common.utils.DateUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import com.ruoyi.iot.mapper.FirmwareMapper; -import com.ruoyi.iot.domain.Firmware; -import com.ruoyi.iot.service.IFirmwareService; - -import static com.ruoyi.common.utils.SecurityUtils.getLoginUser; - -/** - * 产品固件Service业务层处理 - * - * @author kerwincui - * @date 2021-12-16 - */ -@Service -public class FirmwareServiceImpl implements IFirmwareService -{ - @Autowired - private FirmwareMapper firmwareMapper; - - /** - * 查询产品固件 - * - * @param firmwareId 产品固件主键 - * @return 产品固件 - */ - @Override - public Firmware selectFirmwareByFirmwareId(Long firmwareId) - { - return firmwareMapper.selectFirmwareByFirmwareId(firmwareId); - } - - /** - * 查询设备最新固件 - * - * @param deviceId 产品固件主键 - * @return 产品固件 - */ - @Override - public Firmware selectLatestFirmware(Long deviceId) - { - return firmwareMapper.selectLatestFirmware(deviceId); - } - - /** - * 查询产品固件列表 - * - * @param firmware 产品固件 - * @return 产品固件 - */ - @Override - public List selectFirmwareList(Firmware firmware) - { - SysUser user = getLoginUser().getUser(); - List roles=user.getRoles(); - // 租户 - if(roles.stream().anyMatch(a->a.getRoleKey().equals("tenant"))){ - firmware.setTenantId(user.getUserId()); - } - return firmwareMapper.selectFirmwareList(firmware); - } - - /** - * 新增产品固件 - * - * @param firmware 产品固件 - * @return 结果 - */ - @Override - public int insertFirmware(Firmware firmware) - { - // 判断是否为管理员 - firmware.setIsSys(1); - SysUser user = getLoginUser().getUser(); - List roles=user.getRoles(); - for(int i=0;i list=groupMapper.selectDeviceIdsByGroupId(groupId); - Long[] ids=new Long[list.size()]; - for(int i=0;i selectGroupList(Group group) - { - SysUser user = getLoginUser().getUser(); - List roles=user.getRoles(); - if(group.getUserId()!=null && group.getUserId()!=0){ - // 筛选自己分组(主要针对管理员) - group.setUserId(group.getUserId()); - }else { - for (int i = 0; i < roles.size(); i++) { - // 租户和用户,只查看自己分组 - if (roles.get(i).getRoleKey().equals("tenant") || roles.get(i).getRoleKey().equals("general")) { - group.setUserId(user.getUserId()); - break; - } - } - } - return groupMapper.selectGroupList(group); - } - - /** - * 新增设备分组 - * - * @param group 设备分组 - * @return 结果 - */ - @Override - public int insertGroup(Group group) - { - SysUser user = getLoginUser().getUser(); - group.setUserId(user.getUserId()); - group.setUserName(user.getUserName()); - group.setCreateTime(DateUtils.getNowDate()); - return groupMapper.insertGroup(group); - } - - /** - * 修改设备分组 - * - * @param group 设备分组 - * @return 结果 - */ - @Override - public int updateGroup(Group group) - { - group.setUpdateTime(DateUtils.getNowDate()); - return groupMapper.updateGroup(group); - } - - /** - * 分组下批量添加设备分组 - * @return - */ - @Transactional(rollbackFor = Exception.class) - @Override - public int updateDeviceGroups(DeviceGroupInput input){ - //删除分组下的所有关联设备 - groupMapper.deleteDeviceGroupByGroupIds(new Long[]{input.getGroupId()}); - // 分组下添加关联设备 - if(input.getDeviceIds().length>0){ - groupMapper.insertDeviceGroups(input); - } - return 1; - } - - /** - * 批量删除分组和设备分组 - * - * @param groupIds 需要删除的设备分组主键 - * @return 结果 - */ - @Override - @Transactional(rollbackFor = Exception.class) - public int deleteGroupByGroupIds(Long[] groupIds) - { - // 删除设备分组 - groupMapper.deleteDeviceGroupByGroupIds(groupIds); - // 删除分组 - return groupMapper.deleteGroupByGroupIds(groupIds); - } - - /** - * 删除分组信息 - * - * @param groupId 设备分组主键 - * @return 结果 - */ - @Override - public int deleteGroupByGroupId(Long groupId) - { - - return groupMapper.deleteGroupByGroupId(groupId); - } - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/NewsCategoryServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/NewsCategoryServiceImpl.java deleted file mode 100644 index 66f100c0..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/NewsCategoryServiceImpl.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.ruoyi.iot.service.impl; - -import java.util.List; - -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.iot.model.IdAndName; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import com.ruoyi.iot.mapper.NewsCategoryMapper; -import com.ruoyi.iot.domain.NewsCategory; -import com.ruoyi.iot.service.INewsCategoryService; - -/** - * 新闻分类Service业务层处理 - * - * @author kerwincui - * @date 2022-04-09 - */ -@Service -public class NewsCategoryServiceImpl implements INewsCategoryService -{ - @Autowired - private NewsCategoryMapper newsCategoryMapper; - - /** - * 查询新闻分类 - * - * @param categoryId 新闻分类主键 - * @return 新闻分类 - */ - @Override - public NewsCategory selectNewsCategoryByCategoryId(Long categoryId) - { - return newsCategoryMapper.selectNewsCategoryByCategoryId(categoryId); - } - - /** - * 查询新闻分类列表 - * - * @param newsCategory 新闻分类 - * @return 新闻分类 - */ - @Override - public List selectNewsCategoryList(NewsCategory newsCategory) - { - return newsCategoryMapper.selectNewsCategoryList(newsCategory); - } - - /** - * 查询新闻分类简短列表 - * - * @return 新闻分类 - */ - @Override - public List selectNewsCategoryShortList() - { - return newsCategoryMapper.selectNewsCategoryShortList(); - } - - /** - * 新增新闻分类 - * - * @param newsCategory 新闻分类 - * @return 结果 - */ - @Override - public int insertNewsCategory(NewsCategory newsCategory) - { - newsCategory.setCreateTime(DateUtils.getNowDate()); - return newsCategoryMapper.insertNewsCategory(newsCategory); - } - - /** - * 修改新闻分类 - * - * @param newsCategory 新闻分类 - * @return 结果 - */ - @Override - public int updateNewsCategory(NewsCategory newsCategory) - { - newsCategory.setUpdateTime(DateUtils.getNowDate()); - return newsCategoryMapper.updateNewsCategory(newsCategory); - } - - /** - * 批量删除新闻分类 - * - * @param categoryIds 需要删除的新闻分类主键 - * @return 结果 - */ - @Override - public AjaxResult deleteNewsCategoryByCategoryIds(Long[] categoryIds) - { - int productCount=newsCategoryMapper.newsCountInCategorys(categoryIds); - if(productCount>0){ - return AjaxResult.error("删除失败,请先删除对应分类下的新闻资讯"); - } - if(newsCategoryMapper.deleteNewsCategoryByCategoryIds(categoryIds)>0){ - return AjaxResult.success("删除成功"); - } - return AjaxResult.error("删除失败"); - } - - /** - * 删除新闻分类信息 - * - * @param categoryId 新闻分类主键 - * @return 结果 - */ - @Override - public int deleteNewsCategoryByCategoryId(Long categoryId) - { - return newsCategoryMapper.deleteNewsCategoryByCategoryId(categoryId); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/NewsServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/NewsServiceImpl.java deleted file mode 100644 index 28a10e1c..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/NewsServiceImpl.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.ruoyi.iot.service.impl; - -import java.util.ArrayList; -import java.util.List; -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.iot.mapper.NewsCategoryMapper; -import com.ruoyi.iot.model.CategoryNews; -import com.ruoyi.iot.model.IdAndName; -import org.springframework.beans.BeanUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import com.ruoyi.iot.mapper.NewsMapper; -import com.ruoyi.iot.domain.News; -import com.ruoyi.iot.service.INewsService; - -/** - * 新闻资讯Service业务层处理 - * - * @author kerwincui - * @date 2022-04-09 - */ -@Service -public class NewsServiceImpl implements INewsService -{ - @Autowired - private NewsMapper newsMapper; - - /** - * 查询新闻资讯 - * - * @param newsId 新闻资讯主键 - * @return 新闻资讯 - */ - @Override - public News selectNewsByNewsId(Long newsId) - { - return newsMapper.selectNewsByNewsId(newsId); - } - - /** - * 查询新闻资讯列表 - * - * @param news 新闻资讯 - * @return 新闻资讯 - */ - @Override - public List selectNewsList(News news) - { - return newsMapper.selectNewsList(news); - } - - /** - * 查询置顶新闻资讯列表 - * - * @return 新闻资讯 - */ - @Override - public List selectTopNewsList() - { - List categoryNewsList =new ArrayList<>(); - List newsList=newsMapper.selectTopNewsList(); - for(int i=0;i selectOauthClientDetailsList(OauthClientDetails oauthClientDetails) - { - return oauthClientDetailsMapper.selectOauthClientDetailsList(oauthClientDetails); - } - - /** - * 新增云云对接 - * - * @param oauthClientDetails 云云对接 - * @return 结果 - */ - @Override - public int insertOauthClientDetails(OauthClientDetails oauthClientDetails) - { - return oauthClientDetailsMapper.insertOauthClientDetails(oauthClientDetails); - } - - /** - * 修改云云对接 - * - * @param oauthClientDetails 云云对接 - * @return 结果 - */ - @Override - public int updateOauthClientDetails(OauthClientDetails oauthClientDetails) - { - return oauthClientDetailsMapper.updateOauthClientDetails(oauthClientDetails); - } - - /** - * 批量删除云云对接 - * - * @param clientIds 需要删除的云云对接主键 - * @return 结果 - */ - @Override - public int deleteOauthClientDetailsByClientIds(String[] clientIds) - { - return oauthClientDetailsMapper.deleteOauthClientDetailsByClientIds(clientIds); - } - - /** - * 删除云云对接信息 - * - * @param clientId 云云对接主键 - * @return 结果 - */ - @Override - public int deleteOauthClientDetailsByClientId(String clientId) - { - return oauthClientDetailsMapper.deleteOauthClientDetailsByClientId(clientId); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/ProductAuthorizeServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/ProductAuthorizeServiceImpl.java deleted file mode 100644 index 879afe7c..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/ProductAuthorizeServiceImpl.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.ruoyi.iot.service.impl; - -import com.ruoyi.common.constant.HttpStatus; -import com.ruoyi.common.core.domain.entity.SysUser; -import com.ruoyi.common.exception.ServiceException; -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.uuid.IdUtils; -import com.ruoyi.iot.domain.ProductAuthorize; -import com.ruoyi.iot.mapper.ProductAuthorizeMapper; -import com.ruoyi.iot.model.ProductAuthorizeVO; -import com.ruoyi.iot.service.IProductAuthorizeService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.ArrayList; -import java.util.List; - -import static com.ruoyi.common.utils.SecurityUtils.getLoginUser; - -/** - * 产品授权码Service业务层处理 - * - * @author kami - * @date 2022-04-11 - */ -@Service -public class ProductAuthorizeServiceImpl implements IProductAuthorizeService { - @Autowired - private ProductAuthorizeMapper productAuthorizeMapper; - - /** - * 查询产品授权码 - * - * @param authorizeId 产品授权码主键 - * @return 产品授权码 - */ - @Override - public ProductAuthorize selectProductAuthorizeByAuthorizeId(Long authorizeId) { - return productAuthorizeMapper.selectProductAuthorizeByAuthorizeId(authorizeId); - } - - /** - * 查询产品授权码列表 - * - * @param productAuthorize 产品授权码 - * @return 产品授权码 - */ - @Override - public List selectProductAuthorizeList(ProductAuthorize productAuthorize) { - return productAuthorizeMapper.selectProductAuthorizeList(productAuthorize); - } - - /** - * 新增产品授权码 - * - * @param productAuthorize 产品授权码 - * @return 结果 - */ - @Override - public int insertProductAuthorize(ProductAuthorize productAuthorize) { - // 1=未使用,2=使用中 - productAuthorize.setStatus(1); - productAuthorize.setCreateTime(DateUtils.getNowDate()); - return productAuthorizeMapper.insertProductAuthorize(productAuthorize); - } - - /** - * 修改产品授权码 - * - * @param productAuthorize 产品授权码 - * @return 结果 - */ - @Override - public int updateProductAuthorize(ProductAuthorize productAuthorize) { - if(productAuthorize.getDeviceId()!=null && productAuthorize.getDeviceId()!=0){ - // 1=未使用,2=使用中 - productAuthorize.setStatus(2); - productAuthorize.setUpdateTime(DateUtils.getNowDate()); - } - return productAuthorizeMapper.updateProductAuthorize(productAuthorize); - } - - /** - * 批量删除产品授权码 - * - * @param authorizeIds 需要删除的产品授权码主键 - * @return 结果 - */ - @Override - public int deleteProductAuthorizeByAuthorizeIds(Long[] authorizeIds) { - return productAuthorizeMapper.deleteProductAuthorizeByAuthorizeIds(authorizeIds); - } - - /** - * 删除产品授权码信息 - * - * @param authorizeId 产品授权码主键 - * @return 结果 - */ - @Override - public int deleteProductAuthorizeByAuthorizeId(Long authorizeId) { - return productAuthorizeMapper.deleteProductAuthorizeByAuthorizeId(authorizeId); - } - - /** - * 根据数量批量新增产品授权码 - * - * @param productAuthorizeVO - * @return - */ - @Override - @Transactional(rollbackFor = Exception.class) - public int addProductAuthorizeByNum(ProductAuthorizeVO productAuthorizeVO) { - Long productId = productAuthorizeVO.getProductId(); - int createNum = productAuthorizeVO.getCreateNum(); - List list = new ArrayList<>(createNum); - SysUser user = getLoginUser().getUser(); - for (int i = 0; i < createNum; i++) { - ProductAuthorize authorize = new ProductAuthorize(); - // 1=未使用,2=使用中 - authorize.setStatus(1); - authorize.setProductId(productId); - authorize.setCreateBy(user.getUserName()); - authorize.setCreateTime(DateUtils.getNowDate()); - authorize.setAuthorizeCode(IdUtils.fastSimpleUUID().toUpperCase()); - list.add(authorize); - } - return productAuthorizeMapper.insertBatchAuthorize(list); - } - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/ProductServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/ProductServiceImpl.java deleted file mode 100644 index f90b91ec..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/ProductServiceImpl.java +++ /dev/null @@ -1,223 +0,0 @@ -package com.ruoyi.iot.service.impl; - -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.domain.entity.SysRole; -import com.ruoyi.common.core.domain.entity.SysUser; -import com.ruoyi.common.core.redis.RedisCache; -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.iot.domain.Product; -import com.ruoyi.iot.mapper.ProductAuthorizeMapper; -import com.ruoyi.iot.mapper.ProductMapper; -import com.ruoyi.iot.model.ChangeProductStatusModel; -import com.ruoyi.iot.model.IdAndName; -import com.ruoyi.iot.service.IProductService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; - -import static com.ruoyi.common.utils.SecurityUtils.getLoginUser; - -/** - * 产品Service业务层处理 - * - * @author kerwincui - * @date 2021-12-16 - */ -@Service -public class ProductServiceImpl implements IProductService -{ - private String tslPreKey ="tsl"; - - @Autowired - private ProductMapper productMapper; - - @Autowired - private ProductAuthorizeMapper productAuthorizeMapper; - - @Autowired - private RedisCache redisCache; - - @Autowired - private ToolServiceImpl toolService; - - /** - * 查询产品 - * - * @param productId 产品主键 - * @return 产品 - */ - @Override - public Product selectProductByProductId(Long productId) - { - return productMapper.selectProductByProductId(productId); - } - - /** - * 查询产品列表 - * - * @param product 产品 - * @return 产品 - */ - @Override - public List selectProductList(Product product) - { - SysUser user = getLoginUser().getUser(); - List roles=user.getRoles(); - // 租户 - if(roles.stream().anyMatch(a->a.getRoleKey().equals("tenant"))){ - product.setTenantId(user.getUserId()); - } - return productMapper.selectProductList(product); - } - - /** - * 查询产品简短列表 - * - * @return 产品 - */ - @Override - public List selectProductShortList() - { - Product product =new Product(); - SysUser user = getLoginUser().getUser(); - List roles=user.getRoles(); - // 租户 - if(roles.stream().anyMatch(a->a.getRoleKey().equals("tenant"))){ - product.setTenantId(user.getUserId()); - } - return productMapper.selectProductShortList(product); - } - - /** - * 新增产品 - * - * @param product 产品 - * @return 结果 - */ - @Override - public Product insertProduct(Product product) - { - // 判断是否为管理员 - product.setIsSys(1); - SysUser user = getLoginUser().getUser(); - List roles=user.getRoles(); - for(int i=0;i0){ - return AjaxResult.error("取消发布失败,请先删除产品下的设备"); - } - }else if(model.getStatus()==2){ - // 产品下必须包含物模型 - int thingsCount=productMapper.thingsCountInProduct(model.getProductId()); - if(thingsCount==0){ - return AjaxResult.error("发布失败,请先添加产品的物模型"); - } - // 产品下物模型的标识符必须唯一 - int repeatCount=productMapper.thingsRepeatCountInProduct(model.getProductId()); - if(repeatCount>1){ - return AjaxResult.error("发布失败,产品物模型的标识符必须唯一"); - } - }else{ - return AjaxResult.error("状态更新失败,状态值有误"); - } - if(productMapper.changeProductStatus(model)>0){ - return AjaxResult.success("操作成功"); - } - return AjaxResult.error("状态更新失败"); - } - - /** - * 批量删除产品 - * - * @param productIds 需要删除的产品主键 - * @return 结果 - */ - @Override - @Transactional - public AjaxResult deleteProductByProductIds(Long[] productIds) - { - // 删除物模型JSON缓存 - for(int i=0;i0){ - return AjaxResult.error("删除失败,请先删除对应产品下的固件"); - } - // 产品下不能有设备 - int deviceCount=productMapper.deviceCountInProducts(productIds); - if(deviceCount>0){ - return AjaxResult.error("删除失败,请先删除对应产品下的设备"); - } - // 删除产品物模型 - productMapper.deleteProductThingsModelByProductIds(productIds); - // 删除产品的授权码 - productAuthorizeMapper.deleteProductAuthorizeByProductIds(productIds); - // 删除产品 - if(productMapper.deleteProductByProductIds(productIds)>0){ - return AjaxResult.success("删除成功"); - } - return AjaxResult.error("删除失败"); - } - - - /** - * 删除产品信息 - * - * @param productId 产品主键 - * @return 结果 - */ - @Override - public int deleteProductByProductId(Long productId) - { - // 删除物模型JSON缓存 - redisCache.deleteObject(tslPreKey+productId); - return productMapper.deleteProductByProductId(productId); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/SceneServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/SceneServiceImpl.java deleted file mode 100644 index ae203f6f..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/SceneServiceImpl.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.ruoyi.iot.service.impl; - -import java.util.List; -import com.ruoyi.common.utils.DateUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import com.ruoyi.iot.mapper.SceneMapper; -import com.ruoyi.iot.domain.Scene; -import com.ruoyi.iot.service.ISceneService; - -/** - * 场景联动Service业务层处理 - * - * @author kerwincui - * @date 2022-01-13 - */ -@Service -public class SceneServiceImpl implements ISceneService -{ - @Autowired - private SceneMapper sceneMapper; - - /** - * 查询场景联动 - * - * @param sceneId 场景联动主键 - * @return 场景联动 - */ - @Override - public Scene selectSceneBySceneId(Long sceneId) - { - return sceneMapper.selectSceneBySceneId(sceneId); - } - - /** - * 查询场景联动列表 - * - * @param scene 场景联动 - * @return 场景联动 - */ - @Override - public List selectSceneList(Scene scene) - { - return sceneMapper.selectSceneList(scene); - } - - /** - * 新增场景联动 - * - * @param scene 场景联动 - * @return 结果 - */ - @Override - public int insertScene(Scene scene) - { - scene.setCreateTime(DateUtils.getNowDate()); - return sceneMapper.insertScene(scene); - } - - /** - * 修改场景联动 - * - * @param scene 场景联动 - * @return 结果 - */ - @Override - public int updateScene(Scene scene) - { - scene.setUpdateTime(DateUtils.getNowDate()); - return sceneMapper.updateScene(scene); - } - - /** - * 批量删除场景联动 - * - * @param sceneIds 需要删除的场景联动主键 - * @return 结果 - */ - @Override - public int deleteSceneBySceneIds(Long[] sceneIds) - { - return sceneMapper.deleteSceneBySceneIds(sceneIds); - } - - /** - * 删除场景联动信息 - * - * @param sceneId 场景联动主键 - * @return 结果 - */ - @Override - public int deleteSceneBySceneId(Long sceneId) - { - return sceneMapper.deleteSceneBySceneId(sceneId); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/SocialLoginServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/SocialLoginServiceImpl.java deleted file mode 100644 index 194909d7..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/SocialLoginServiceImpl.java +++ /dev/null @@ -1,353 +0,0 @@ -package com.ruoyi.iot.service.impl; - -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.domain.entity.SysUser; -import com.ruoyi.common.core.domain.model.BindLoginBody; -import com.ruoyi.common.core.domain.model.BindRegisterBody; -import com.ruoyi.common.core.domain.model.LoginUser; -import com.ruoyi.common.core.redis.RedisCache; -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.sign.Md5Utils; -import com.ruoyi.framework.web.service.SysLoginService; -import com.ruoyi.framework.web.service.SysRegisterService; -import com.ruoyi.framework.web.service.TokenService; -import com.ruoyi.iot.domain.SocialPlatform; -import com.ruoyi.iot.domain.SocialUser; -import com.ruoyi.iot.model.login.AuthRequestWrap; -import com.ruoyi.iot.model.login.BindIdValue; -import com.ruoyi.iot.model.login.LoginIdValue; -import com.ruoyi.iot.service.IAuthRequestFactory; -import com.ruoyi.iot.service.ISocialLoginService; -import com.ruoyi.iot.service.ISocialUserService; -import com.ruoyi.system.service.ISysConfigService; -import com.ruoyi.system.service.ISysUserService; -import me.zhyd.oauth.exception.AuthException; -import me.zhyd.oauth.model.AuthCallback; -import me.zhyd.oauth.model.AuthResponse; -import me.zhyd.oauth.model.AuthUser; -import me.zhyd.oauth.utils.AuthStateUtils; -import me.zhyd.oauth.utils.RandomUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.servlet.http.HttpServletRequest; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import static com.ruoyi.common.constant.HttpStatus.NO_MESSAGE_ALERT; -import static com.ruoyi.common.core.domain.AjaxResult.error; - -/** - * 第三方登录Service业务层处理 - * - * @author json - * @date 2022-04-12 - */ -@Service -public class SocialLoginServiceImpl implements ISocialLoginService { - - public static final Integer BIND_EXPIRE_TIME = 60 * 60; - public static final Integer LOGIN_SOCIAL_EXPIRE_TIME = 60; - public static final String ONLINE_STATUS = "0"; //1 offline - public static final String DEL_FLAG = "0"; //1 offline - - //redis key: uuid+source - public static final String BIND_REDIS_KEY = "login:bind:user:"; - //redis key : userId+random 32 - public static final String LOGIN_SOCIAL_REDIS_KEY = "login:social:user:"; - //redis key : msg+ code+currentTime - public static final String LOGIN_ERROR_MSG_REDIS_KEY = "login:error:msg:"; - - public static final String HTTPS = "https://"; - - private static final Logger log = LoggerFactory.getLogger(SocialLoginServiceImpl.class); - - @Autowired - private RedisCache redisCache; - - @Autowired - private ISysConfigService iSysConfigService; - - @Autowired - private TokenService tokenService; - - @Autowired - private SysRegisterService sysRegisterService; - - @Autowired - private SysLoginService sysLoginService; - - @Autowired - private ISysUserService iSysUserService; - - @Autowired - private IAuthRequestFactory iAuthRequestFactory; - - @Autowired - private ISocialUserService iSocialUserService; - - - @Override - public String renderAuth(String source, HttpServletRequest httpServletRequest) { - AuthRequestWrap authRequestWrap = null; - try { - authRequestWrap = iAuthRequestFactory.getAuthRequest(source); - checkSocialPlatform(authRequestWrap.getSocialPlatform()); - return authRequestWrap.getAuthRequest().authorize(AuthStateUtils.createState()); - } catch (AuthException authException) { - //返回错误信息 - log.error("", authException); - if (authRequestWrap != null) { - String errorId = genErrorId(authException.getMessage()); - return authRequestWrap.getSocialPlatform().getErrorMsgUri() + errorId; - } else { - return httpServletRequest.getProtocol() + httpServletRequest.getServerName() + httpServletRequest.getServerPort(); - } - } catch (Exception exception) { - //这类错误 直接不返回,重定向到主页 - log.error("", exception); - return HTTPS + httpServletRequest.getServerName(); - } - - } - - @Override - public String callback(String source, AuthCallback authCallback, HttpServletRequest httpServletRequest) { - AuthRequestWrap authRequestWrap = null; - try { - authRequestWrap = iAuthRequestFactory.getAuthRequest(source); - checkSocialPlatform(authRequestWrap.getSocialPlatform()); - AuthResponse authResponse = authRequestWrap.getAuthRequest().login(authCallback); - String bindId = null; - String loginId = null; - if (authResponse.ok()) { - - SocialUser socialUser = findSocialUser(authResponse.getData().getUuid(), authResponse.getData().getSource()); - createOrUpdateSocialUser(socialUser, authResponse.getData()); - if (socialUser == null) { - //第一次登录 - bindId = genBindId(authResponse.getData()); - } else if (socialUser.getSysUserId() == null || socialUser.getSysUserId() <= 0) { - //初次绑定 - bindId = genBindId(authResponse.getData()); - } else { - //查看是否已经绑定 - SysUser sysUser = iSysUserService.selectUserById(socialUser.getSysUserId()); - if (sysUser == null) { - bindId = genBindId(authResponse.getData()); - } else { - //直接登录跳转 - loginId = genLoginId(sysUser); - } - } - if (StringUtils.isNotEmpty(bindId)) { - return authRequestWrap.getSocialPlatform().getBindUri() + bindId; - } else { - return authRequestWrap.getSocialPlatform().getRedirectLoginUri() + loginId; - } - } else { - log.error("登录授权异常,code:{}, msg:{}", authResponse.getCode(), authResponse.getMsg()); - String errorId = genErrorId(authResponse.getMsg()); - return authRequestWrap.getSocialPlatform().getErrorMsgUri() + errorId; - } - } catch (AuthException authException) { - //返回错误信息 - log.error("", authException); - if (authRequestWrap != null) { - String errorId = genErrorId(authException.getMessage()); - return authRequestWrap.getSocialPlatform().getErrorMsgUri() + errorId; - } else { - return httpServletRequest.getServerName() + httpServletRequest.getServerPort(); - } - } catch (Exception exception) { - log.error("", exception); - return HTTPS + httpServletRequest.getServerName(); - } - - } - - @Override - public AjaxResult checkBindId(String bindId) { - AjaxResult ajax = AjaxResult.success(); - ajax.put("bindAccount", false); - if (StringUtils.isEmpty(bindId)) { - return ajax; - } - BindIdValue bindValue = redisCache.getCacheObject(BIND_REDIS_KEY + bindId); - if (bindValue == null) { - return ajax; - } - ajax.put("bindAccount", true); - return AjaxResult.success(bindId); - } - - @Override - public AjaxResult getErrorMsg(String errorId) { - String errorMsg = redisCache.getCacheObject(LOGIN_ERROR_MSG_REDIS_KEY + errorId); - if (StringUtils.isEmpty(errorMsg)) { - return error(NO_MESSAGE_ALERT, ""); - } else { - return error(errorMsg); - } - } - - @Override - public AjaxResult socialLogin(String loginId) { - AjaxResult ajax = AjaxResult.success(); - String loginKey = LOGIN_SOCIAL_REDIS_KEY + loginId; - LoginIdValue loginIdValue = redisCache.getCacheObject(loginKey); - if (loginIdValue != null) { - //login - String token = sysLoginService.redirectLogin(loginIdValue.getUsername(), loginIdValue.getPassword()); - ajax.put(Constants.TOKEN, token); - } else { - log.info("loginId:{} ", loginId); - return error(NO_MESSAGE_ALERT, "数据错误"); - } - return ajax; - } - - @Override - public AjaxResult bindLogin(BindLoginBody bindLoginBody) { - BindIdValue bindValue = redisCache.getCacheObject(BIND_REDIS_KEY + bindLoginBody.getBindId()); - SocialUser socialUser = findSocialUser(bindValue.getUuid(), bindValue.getSource()); - AjaxResult checkAjax = checkSocialUser(socialUser, bindLoginBody.getBindId()); - if (checkAjax != null) { - return checkAjax; - } - AjaxResult ajax = AjaxResult.success(); - // 生成令牌 - String token = sysLoginService.login(bindLoginBody.getUsername(), bindLoginBody.getPassword(), bindLoginBody.getCode(), - bindLoginBody.getUuid()); - LoginUser loginUser = tokenService.getLoginUserByToken(token); - //绑定和更新 - SocialUser updateSocialUser = new SocialUser(); - updateSocialUser.setSysUserId(loginUser.getUserId()); - updateSocialUser.setSocialUserId(socialUser.getSocialUserId()); - iSocialUserService.updateSocialUser(updateSocialUser); - ajax.put(Constants.TOKEN, token); - redisCache.deleteObject(BIND_REDIS_KEY + bindLoginBody.getBindId()); - return ajax; - } - - @Override - public AjaxResult bindRegister(BindRegisterBody bindRegisterBody) { - if (!("true".equals(iSysConfigService.selectConfigByKey("sys.account.registerUser")))) { - return error("当前系统没有开启注册功能!"); - } - BindIdValue bindValue = redisCache.getCacheObject(BIND_REDIS_KEY + bindRegisterBody.getBindId()); - SocialUser socialUser = findSocialUser(bindValue.getUuid(), bindValue.getSource()); - AjaxResult checkAjax = checkSocialUser(socialUser, bindRegisterBody.getBindId()); - if (checkAjax != null) { - return checkAjax; - } - - AjaxResult ajax = AjaxResult.success(); - String msg = sysRegisterService.register(bindRegisterBody); - if (StringUtils.isEmpty(msg)) { - SysUser sysUser = iSysUserService.selectUserByUserName(bindRegisterBody.getUsername()); - //绑定和更新 - SocialUser updateSocialUser = new SocialUser(); - updateSocialUser.setSysUserId(sysUser.getUserId()); - updateSocialUser.setSocialUserId(socialUser.getSocialUserId()); - iSocialUserService.updateSocialUser(updateSocialUser); - redisCache.deleteObject(BIND_REDIS_KEY + bindRegisterBody.getBindId()); - } - return StringUtils.isEmpty(msg) ? ajax : error(msg); - } - - private void checkSocialPlatform(SocialPlatform socialPlatform) { - if (socialPlatform != null && (!socialPlatform.getStatus().equals(ONLINE_STATUS) || !socialPlatform.getDelFlag().equals(DEL_FLAG))) { - throw new AuthException("当前第三方登录平台被禁用"); - } - } - - public SocialUser findSocialUser(String uuid, String source) { - SocialUser socialUser = new SocialUser(); - socialUser.setSource(source); - socialUser.setUuid(uuid); - List socialUserList = iSocialUserService.selectSocialUserList(socialUser); - return socialUserList == null || socialUserList.isEmpty() ? null : socialUserList.get(0); - - } - - public void createOrUpdateSocialUser(SocialUser socialUser, AuthUser authUser) { - if (socialUser != null) { - //更新数据 - SocialUser updateSocialUser = new SocialUser(); - updateSocialUser.setSocialUserId(socialUser.getSocialUserId()); - replaceSocialUser(updateSocialUser, authUser); - updateSocialUser.setUpdateBy("System"); - updateSocialUser.setUpdateTime(DateUtils.getNowDate()); - iSocialUserService.updateSocialUser(updateSocialUser); - } else { - //创建 - SocialUser saveSocialUser = new SocialUser(); - replaceSocialUser(saveSocialUser, authUser); - saveSocialUser.setDelFlag("0"); - saveSocialUser.setStatus("0"); - saveSocialUser.setCreateBy("System"); - saveSocialUser.setCreateTime(DateUtils.getNowDate()); - iSocialUserService.insertSocialUser(saveSocialUser); - } - } - - private void replaceSocialUser(SocialUser socialUser, AuthUser authUser) { - - socialUser.setUuid(authUser.getUuid()); - socialUser.setSource(authUser.getSource()); - socialUser.setAccessToken(authUser.getToken().getAccessToken()); - //nullable - socialUser.setExpireIn((long) authUser.getToken().getExpireIn()); - socialUser.setRefreshToken(authUser.getToken().getRefreshToken()); - socialUser.setOpenId(authUser.getToken().getOpenId()); - socialUser.setUid(authUser.getToken().getUid()); - socialUser.setAccessCode(authUser.getToken().getAccessCode()); - socialUser.setUnionId(authUser.getToken().getUnionId()); - socialUser.setCode(authUser.getToken().getCode()); - socialUser.setAvatar(authUser.getAvatar()); - socialUser.setUsername(authUser.getUsername()); - socialUser.setNickname(authUser.getNickname()); - } - - private String genBindId(AuthUser authUser) { - String bindId = Md5Utils.hash(authUser.getUuid() + authUser.getSource()); - String key = BIND_REDIS_KEY + bindId; - BindIdValue bindIdValue = new BindIdValue(); - bindIdValue.setSource(authUser.getSource()); - bindIdValue.setUuid(authUser.getUuid()); - redisCache.setCacheObject(key, bindIdValue, BIND_EXPIRE_TIME, TimeUnit.SECONDS); - return bindId; - } - - private String genLoginId(SysUser sysUser) { - String loginId = Md5Utils.hash(sysUser.getUserId() + RandomUtil.randomString(32)); - String key = LOGIN_SOCIAL_REDIS_KEY + loginId; - LoginIdValue loginIdValue = new LoginIdValue(); - loginIdValue.setPassword(sysUser.getPassword()); - loginIdValue.setUsername(sysUser.getUserName()); - redisCache.setCacheObject(key, loginIdValue, LOGIN_SOCIAL_EXPIRE_TIME, TimeUnit.SECONDS); - return loginId; - } - - private String genErrorId(String msg) { - String errorId = Md5Utils.hash(msg + RandomUtil.randomString(32)); - String key = LOGIN_ERROR_MSG_REDIS_KEY + errorId; - redisCache.setCacheObject(key, msg, LOGIN_SOCIAL_EXPIRE_TIME, TimeUnit.SECONDS); - return errorId; - } - - private AjaxResult checkSocialUser(SocialUser socialUser, String bindId) { - if (socialUser == null) { - log.info("bindId不存在, bindId: {}", bindId); - return error("绑定账户不存在"); - } else { - return null; - } - } - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/SocialPlatformServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/SocialPlatformServiceImpl.java deleted file mode 100644 index 0ba91040..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/SocialPlatformServiceImpl.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.ruoyi.iot.service.impl; - -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.iot.domain.SocialPlatform; -import com.ruoyi.iot.mapper.SocialPlatformMapper; -import com.ruoyi.iot.service.ISocialPlatformService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; - -/** - * 第三方登录平台控制Service业务层处理 - * - * @author kerwincui - * @date 2022-04-11 - */ -@Service -public class SocialPlatformServiceImpl implements ISocialPlatformService -{ - @Autowired - private SocialPlatformMapper socialPlatformMapper; - - /** - * 查询第三方登录平台控制 - * - * @param socialPlatformId 第三方登录平台控制主键 - * @return 第三方登录平台控制 - */ - @Override - public SocialPlatform selectSocialPlatformBySocialPlatformId(Long socialPlatformId) - { - return socialPlatformMapper.selectSocialPlatformBySocialPlatformId(socialPlatformId); - } - - @Override - public SocialPlatform selectSocialPlatformByPlatform(String platform) { - return socialPlatformMapper.selectSocialPlatformByPlatform(platform); - } - - /** - * 查询第三方登录平台控制列表 - * - * @param socialPlatform 第三方登录平台控制 - * @return 第三方登录平台控制 - */ - @Override - public List selectSocialPlatformList(SocialPlatform socialPlatform) - { - return socialPlatformMapper.selectSocialPlatformList(socialPlatform); - } - - /** - * 新增第三方登录平台控制 - * - * @param socialPlatform 第三方登录平台控制 - * @return 结果 - */ - @Override - public int insertSocialPlatform(SocialPlatform socialPlatform) - { - socialPlatform.setCreateTime(DateUtils.getNowDate()); - socialPlatform.setDelFlag("0"); - return socialPlatformMapper.insertSocialPlatform(socialPlatform); - } - - /** - * 修改第三方登录平台控制 - * - * @param socialPlatform 第三方登录平台控制 - * @return 结果 - */ - @Override - public int updateSocialPlatform(SocialPlatform socialPlatform) - { - socialPlatform.setUpdateTime(DateUtils.getNowDate()); - return socialPlatformMapper.updateSocialPlatform(socialPlatform); - } - - /** - * 批量删除第三方登录平台控制 - * - * @param socialPlatformIds 需要删除的第三方登录平台控制主键 - * @return 结果 - */ - @Override - public int deleteSocialPlatformBySocialPlatformIds(Long[] socialPlatformIds) - { - return socialPlatformMapper.deleteSocialPlatformBySocialPlatformIds(socialPlatformIds); - } - - /** - * 删除第三方登录平台控制信息 - * - * @param socialPlatformId 第三方登录平台控制主键 - * @return 结果 - */ - @Override - public int deleteSocialPlatformBySocialPlatformId(Long socialPlatformId) - { - return socialPlatformMapper.deleteSocialPlatformBySocialPlatformId(socialPlatformId); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/SocialUserServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/SocialUserServiceImpl.java deleted file mode 100644 index 2dc1beec..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/SocialUserServiceImpl.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.ruoyi.iot.service.impl; - -import java.util.List; -import com.ruoyi.common.utils.DateUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import com.ruoyi.iot.mapper.SocialUserMapper; -import com.ruoyi.iot.domain.SocialUser; -import com.ruoyi.iot.service.ISocialUserService; - -/** - * 用户第三方用户信息Service业务层处理 - * - * @author json - * @date 2022-04-18 - */ -@Service -public class SocialUserServiceImpl implements ISocialUserService -{ - @Autowired - private SocialUserMapper socialUserMapper; - - /** - * 查询用户第三方用户信息 - * - * @param socialUserId 用户第三方用户信息主键 - * @return 用户第三方用户信息 - */ - @Override - public SocialUser selectSocialUserBySocialUserId(Long socialUserId) - { - return socialUserMapper.selectSocialUserBySocialUserId(socialUserId); - } - - /** - * 查询用户第三方用户信息列表 - * - * @param socialUser 用户第三方用户信息 - * @return 用户第三方用户信息 - */ - @Override - public List selectSocialUserList(SocialUser socialUser) - { - return socialUserMapper.selectSocialUserList(socialUser); - } - - /** - * 新增用户第三方用户信息 - * - * @param socialUser 用户第三方用户信息 - * @return 结果 - */ - @Override - public int insertSocialUser(SocialUser socialUser) - { - socialUser.setCreateTime(DateUtils.getNowDate()); - return socialUserMapper.insertSocialUser(socialUser); - } - - /** - * 修改用户第三方用户信息 - * - * @param socialUser 用户第三方用户信息 - * @return 结果 - */ - @Override - public int updateSocialUser(SocialUser socialUser) - { - socialUser.setUpdateTime(DateUtils.getNowDate()); - return socialUserMapper.updateSocialUser(socialUser); - } - - /** - * 批量删除用户第三方用户信息 - * - * @param socialUserIds 需要删除的用户第三方用户信息主键 - * @return 结果 - */ - @Override - public int deleteSocialUserBySocialUserIds(Long[] socialUserIds) - { - return socialUserMapper.deleteSocialUserBySocialUserIds(socialUserIds); - } - - /** - * 删除用户第三方用户信息信息 - * - * @param socialUserId 用户第三方用户信息主键 - * @return 结果 - */ - @Override - public int deleteSocialUserBySocialUserId(Long socialUserId) - { - return socialUserMapper.deleteSocialUserBySocialUserId(socialUserId); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/ThingsModelServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/ThingsModelServiceImpl.java deleted file mode 100644 index 7013aae8..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/ThingsModelServiceImpl.java +++ /dev/null @@ -1,265 +0,0 @@ -package com.ruoyi.iot.service.impl; - -import java.util.ArrayList; -import java.util.List; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import com.ruoyi.common.core.domain.entity.SysUser; -import com.ruoyi.common.core.redis.RedisCache; -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.iot.domain.Product; -import com.ruoyi.iot.domain.ThingsModelTemplate; -import com.ruoyi.iot.mapper.ProductMapper; -import com.ruoyi.iot.mapper.ThingsModelTemplateMapper; -import com.ruoyi.iot.model.ImportThingsModelInput; -import com.ruoyi.iot.model.ThingsModels.EventDto; -import com.ruoyi.iot.model.ThingsModels.FunctionDto; -import com.ruoyi.iot.model.ThingsModels.PropertyDto; -import com.ruoyi.iot.model.ThingsModels.ThingsModelsDto; -import org.springframework.beans.BeanUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import com.ruoyi.iot.mapper.ThingsModelMapper; -import com.ruoyi.iot.domain.ThingsModel; -import com.ruoyi.iot.service.IThingsModelService; - -import static com.ruoyi.common.utils.SecurityUtils.getLoginUser; - -/** - * 物模型Service业务层处理 - * - * @author kerwincui - * @date 2021-12-16 - */ -@Service -public class ThingsModelServiceImpl implements IThingsModelService -{ - private String tslPreKey ="things_model:tsl"; - - @Autowired - private ThingsModelMapper thingsModelMapper; - - @Autowired - private ThingsModelTemplateMapper thingsModelTemplateMapper; - - @Autowired - private ProductMapper productMapper; - - @Autowired - private RedisCache redisCache; - - /** - * 查询物模型 - * - * @param modelId 物模型主键 - * @return 物模型 - */ - @Override - public ThingsModel selectThingsModelByModelId(Long modelId) - { - return thingsModelMapper.selectThingsModelByModelId(modelId); - } - - /** - * 查询物模型列表 - * - * @param thingsModel 物模型 - * @return 物模型 - */ - @Override - public List selectThingsModelList(ThingsModel thingsModel) - { - return thingsModelMapper.selectThingsModelList(thingsModel); - } - - /** - * 新增物模型 - * - * @param thingsModel 物模型 - * @return 结果 - */ - @Override - public int insertThingsModel(ThingsModel thingsModel) - { - // 物模型标识符不能重复 TODO 重复查询待优化 - ThingsModel input=new ThingsModel(); - input.setProductId(thingsModel.getProductId()); - List list=thingsModelMapper.selectThingsModelList(input); - Boolean isRepeat=list.stream().anyMatch(x->x.getIdentifier().equals(thingsModel.getIdentifier())); - if(!isRepeat) { - SysUser user = getLoginUser().getUser(); - thingsModel.setTenantId(user.getUserId()); - thingsModel.setTenantName(user.getUserName()); - thingsModel.setCreateTime(DateUtils.getNowDate()); - int result = thingsModelMapper.insertThingsModel(thingsModel); - // 更新redis缓存 - setCacheThingsModelByProductId(thingsModel.getProductId()); - return result; - } - return 2; - } - - /** - * 导入通用物模型 - * @param input - * @return - */ - @Override - public int importByTemplateIds(ImportThingsModelInput input){ - // 物模型标识符不能重复 TODO 重复查询待优化 - ThingsModel inputParameter=new ThingsModel(); - inputParameter.setProductId(input.getProductId()); - List dbList=thingsModelMapper.selectThingsModelList(inputParameter); - - SysUser user = getLoginUser().getUser(); - // 根据ID集合获取通用物模型列表 - List templateList=thingsModelTemplateMapper.selectThingsModelTemplateByTemplateIds(input.getTemplateIds()); - //转换为产品物模型,并批量插入 - List list=new ArrayList<>(); - int repeatCount=0; - for(ThingsModelTemplate template : templateList){ - ThingsModel thingsModel= new ThingsModel(); - BeanUtils.copyProperties(template,thingsModel); - thingsModel.setTenantId(user.getUserId()); - thingsModel.setTenantName(user.getUserName()); - thingsModel.setCreateTime(DateUtils.getNowDate()); - thingsModel.setProductId(input.getProductId()); - thingsModel.setProductName(input.getProductName()); - thingsModel.setModelId(template.getTemplateId()); - thingsModel.setModelName(template.getTemplateName()); - Boolean isRepeat=dbList.stream().anyMatch(x->x.getIdentifier().equals(thingsModel.getIdentifier())); - if(isRepeat){ - repeatCount=repeatCount+1; - }else{ - list.add(thingsModel); - } - } - if(list.size()>0) { - thingsModelMapper.insertBatchThingsModel(list); - //更新redis缓存 - setCacheThingsModelByProductId(input.getProductId()); - } - return repeatCount; - } - - /** - * 修改物模型 - * - * @param thingsModel 物模型 - * @return 结果 - */ - @Override - public int updateThingsModel(ThingsModel thingsModel) - { - // 物模型标识符不能重复 TODO 重复查询待优化 - ThingsModel input=new ThingsModel(); - input.setProductId(thingsModel.getProductId()); - List list=thingsModelMapper.selectThingsModelList(input); - Boolean isRepeat=list.stream().anyMatch(x->x.getIdentifier().equals(thingsModel.getIdentifier()) && x.getModelId().longValue()!=thingsModel.getModelId()); - if(!isRepeat) { - thingsModel.setUpdateTime(DateUtils.getNowDate()); - int result = thingsModelMapper.updateThingsModel(thingsModel); - // 更新redis缓存 - setCacheThingsModelByProductId(thingsModel.getProductId()); - return result; - } - return 2; - } - - /** - * 批量删除物模型 - * - * @param modelIds 需要删除的物模型主键 - * @return 结果 - */ - @Override - public int deleteThingsModelByModelIds(Long[] modelIds) - { - ThingsModel thingsModel=thingsModelMapper.selectThingsModelByModelId(modelIds[0]); - int result=thingsModelMapper.deleteThingsModelByModelIds(modelIds); - // 更新redis缓存 - setCacheThingsModelByProductId(thingsModel.getProductId()); - - return result; - } - - /** - * 删除物模型信息 - * - * @param modelId 物模型主键 - * @return 结果 - */ - @Override - public int deleteThingsModelByModelId(Long modelId) - { - ThingsModel thingsModel=thingsModelMapper.selectThingsModelByModelId(modelId); - int result=thingsModelMapper.deleteThingsModelByModelId(modelId); - // 更新redis缓存 - setCacheThingsModelByProductId(thingsModel.getProductId()); - return result; - } - - /** - * 根据产品ID获取JSON物模型 - * @param productId - * @return - */ - @Override - public String getCacheThingsModelByProductId(Long productId){ - // redis获取物模型 - String thingsModelJson = redisCache.getCacheObject(tslPreKey +productId); - if (thingsModelJson != null){ - return thingsModelJson; - } - return setCacheThingsModelByProductId(productId); - } - - /** - * 根据产品ID更新JSON物模型 - * @param productId - * @return - */ - private String setCacheThingsModelByProductId(Long productId){ - // 数据库查询物模型集合 - ThingsModel model=new ThingsModel(); - model.setProductId(productId); - List thingsModels=thingsModelMapper.selectThingsModelList(model); - // 转换为物模型 - ThingsModelsDto thingsModelsDto=new ThingsModelsDto(); - for(int i=0;i selectThingsModelTemplateList(ThingsModelTemplate thingsModelTemplate) - { - SysUser user = getLoginUser().getUser(); - List roles=user.getRoles(); - // 租户 - if(roles.stream().anyMatch(a->a.getRoleKey().equals("tenant"))){ - thingsModelTemplate.setTenantId(user.getUserId()); - } - return thingsModelTemplateMapper.selectThingsModelTemplateList(thingsModelTemplate); - } - - /** - * 新增通用物模型 - * - * @param thingsModelTemplate 通用物模型 - * @return 结果 - */ - @Override - public int insertThingsModelTemplate(ThingsModelTemplate thingsModelTemplate) - { - // 判断是否为管理员 - thingsModelTemplate.setIsSys(1); - SysUser user = getLoginUser().getUser(); - List roles=user.getRoles(); - for(int i=0;i UserConstants.USERNAME_MAX_LENGTH) - { - msg = "账户长度必须在2到20个字符之间"; - } - else if (password.length() < UserConstants.PASSWORD_MIN_LENGTH - || password.length() > UserConstants.PASSWORD_MAX_LENGTH) - { - msg = "密码长度必须在5到20个字符之间"; - } - else if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(username))) - { - msg = "保存用户'" + username + "'失败,注册账号已存在"; - }else if (UserConstants.NOT_UNIQUE.equals(checkPhoneUnique(phonenumber))) - { - msg = "保存用户'" + username + "'失败,注册手机号码已存在"; - } - else - { - SysUser sysUser = new SysUser(); - sysUser.setUserName(username); - sysUser.setNickName(username); - sysUser.setPhonenumber(phonenumber); - sysUser.setPassword(SecurityUtils.encryptPassword(registerBody.getPassword())); - boolean regFlag = userService.registerUser(sysUser); - //分配普通用户角色(1=超级管理员,2=设备租户,3=普通用户,4=游客) - Long[] roleIds={3L}; - userService.insertUserAuth(sysUser.getUserId(),roleIds); - if (!regFlag) - { - msg = "注册失败,请联系系统管理人员"; - } - else - { - AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.REGISTER, - MessageUtils.message("user.register.success"))); - } - } - return msg; - } - - /** - * 根据条件分页查询用户列表 - * - * @param user 用户信息 - * @return 用户信息集合信息 - */ - @Override - public List selectUserList(SysUser user) - { - return userMapper.selectUserList(user); - } - - /** - * 校验手机号码是否唯一 - * - * @param phonenumber 手机号码 - * @return - */ - public String checkPhoneUnique(String phonenumber) - { - SysUser info = userMapper.checkPhoneUnique(phonenumber); - if (StringUtils.isNotNull(info)) - { - return UserConstants.NOT_UNIQUE; - } - return UserConstants.UNIQUE; - } - - /** - * 校验验证码 - * - * @param username 用户名 - * @param code 验证码 - * @param uuid 唯一标识 - * @return 结果 - */ - public void validateCaptcha(String username, String code, String uuid) - { - String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid; - String captcha = redisCache.getCacheObject(verifyKey); - redisCache.deleteObject(verifyKey); - if (captcha == null) - { - throw new CaptchaExpireException(); - } - if (!code.equalsIgnoreCase(captcha)) - { - throw new CaptchaException(); - } - } - - /** - * 设备简单认证 - */ - @Override - public ResponseEntity simpleMqttAuthentication(MqttAuthenticationModel mqttModel, ProductAuthenticateModel productModel) { - // 1=简单认证,2=加密认证,3=简单+加密认证 - if(productModel.getVertificateMethod()!=1 && productModel.getVertificateMethod()!=3){ - return returnUnauthorized(mqttModel, "设备简单认证,设备对应产品不支持简单认证"); - } - String[] passwordArray = mqttModel.getPassword().split("&"); - if (productModel.getIsAuthorize() == 1 && passwordArray.length != 2) { - return returnUnauthorized(mqttModel, "设备简单认证,产品启用授权码后,密码格式为:密码 & 授权码"); - } - String mqttPassword = passwordArray[0]; - String authCode = passwordArray.length == 2 ? passwordArray[1] : ""; - // 验证用户名 - if (!mqttModel.getUserName().equals(productModel.getMqttAccount())) { - return returnUnauthorized(mqttModel, "设备简单认证,设备mqtt用户名错误"); - } - // 验证密码 - if (!mqttPassword.equals(productModel.getMqttPassword())) { - return returnUnauthorized(mqttModel, "设备简单认证,设备mqtt密码错误"); - } - // 验证授权码 - if (productModel.getIsAuthorize() == 1) { - // 授权码验证和处理 - String resultMessage = authCodeProcess(authCode, mqttModel, productModel); - if (!resultMessage.equals("")) { - return returnUnauthorized(mqttModel, resultMessage); - } - } - if (productModel.getDeviceId() != null && productModel.getDeviceId() != 0) { - if (productModel.getStatus() == 2) { - return returnUnauthorized(mqttModel, "设备简单认证,设备处于禁用状态"); - } - log.info("-----------设备简单认证成功,clientId:" + mqttModel.getClientId() + "---------------"); - return ResponseEntity.ok().body("ok"); - } else { - // 自动添加设备 - int result = deviceService.insertDeviceAuto(mqttModel.getDeviceNumber(), mqttModel.getUserId(), mqttModel.getProductId()); - if (result == 1) { - log.info("-----------设备简单认证成功,并自动添加设备到系统,clientId:" + mqttModel.getClientId() + "---------------"); - return ResponseEntity.ok().body("ok"); - } - return returnUnauthorized(mqttModel, "设备简单认证,自动添加设备失败"); - } - } - - /** - * 设备加密认证 - * - * @return - */ - @Override - public ResponseEntity encryptAuthentication(MqttAuthenticationModel mqttModel, ProductAuthenticateModel productModel) throws Exception { - // 1=简单认证,2=加密认证,3=简单+加密认证 - if(productModel.getVertificateMethod()!=2 && productModel.getVertificateMethod()!=3){ - return returnUnauthorized(mqttModel, "设备加密认证,设备对应产品不支持加密认证"); - } - String decryptPassword = AESUtils.decrypt(mqttModel.getPassword(), productModel.getMqttSecret()); - if (decryptPassword == null || decryptPassword.equals("")) { - return returnUnauthorized(mqttModel, "设备加密认证,mqtt密码解密失败"); - } - String[] passwordArray = decryptPassword.split("&"); - if (passwordArray.length != 2 && passwordArray.length != 3) { - // 密码加密格式 password & expireTime (& authCode 可选) - return returnUnauthorized(mqttModel, "设备加密认证,mqtt密码加密格式为:密码 & 过期时间 & 授权码,其中授权码为可选"); - } - String mqttPassword = passwordArray[0]; - Long expireTime = Long.valueOf(passwordArray[1]); - String authCode = passwordArray.length == 3 ? passwordArray[2] : ""; - // 验证用户名 - if (!mqttModel.getUserName().equals(productModel.getMqttAccount())) { - return returnUnauthorized(mqttModel, "设备加密认证,设备mqtt用户名错误"); - } - // 验证密码 - if (!mqttPassword.equals(productModel.getMqttPassword())) { - return returnUnauthorized(mqttModel, "设备加密认证,设备mqtt密码错误"); - } - // 验证过期时间 - if (expireTime < System.currentTimeMillis()) { - return returnUnauthorized(mqttModel, "设备加密认证,设备mqtt密码已过期"); - } - // 验证授权码 - if (productModel.getIsAuthorize() == 1) { - // 授权码验证和处理 - String resultMessage = authCodeProcess(authCode, mqttModel, productModel); - if (!resultMessage.equals("")) { - return returnUnauthorized(mqttModel, resultMessage); - } - } - // 设备状态验证 (1-未激活,2-禁用,3-在线,4-离线) - if (productModel.getDeviceId() != null && productModel.getDeviceId() != 0) { - if (productModel.getStatus() == 2) { - return returnUnauthorized(mqttModel, "设备加密认证,设备处于禁用状态"); - } - log.info("-----------设备加密认证成功,clientId:" + mqttModel.getClientId() + "---------------"); - return ResponseEntity.ok().body("ok"); - } else { - // 自动添加设备 - int result = deviceService.insertDeviceAuto(mqttModel.getDeviceNumber(), mqttModel.getUserId(), mqttModel.getProductId()); - if (result == 1) { - log.info("-----------设备加密认证成功,并自动添加设备到系统,clientId:" + mqttModel.getClientId() + "---------------"); - return ResponseEntity.ok().body("ok"); - } - return returnUnauthorized(mqttModel, "设备加密认证,自动添加设备失败"); - } - } - - /** - * 授权码认证和处理 - */ - private String authCodeProcess(String authCode, MqttAuthenticationModel mqttModel, ProductAuthenticateModel productModel) { - String message = ""; - if (authCode.equals("")) { - return message = "设备认证,设备授权码不能为空"; - } - // 查询授权码是否存在 - ProductAuthorize authorize = productAuthorizeMapper.selectFirstAuthorizeByAuthorizeCode(new ProductAuthorize(authCode, productModel.getProductId())); - if (authorize == null) { - message = "设备认证,设备授权码错误"; - return message; - } - if (authorize.getSerialNumber() != null && !authorize.getSerialNumber().equals("")) { - // 授权码已关联设备 - if (!authorize.getSerialNumber().equals( productModel.getSerialNumber())) { - message = "设备认证,设备授权码已经分配给其他设备"; - return message; - } - } else { - // 授权码未关联设备 - authorize.setSerialNumber(mqttModel.getDeviceNumber()); - authorize.setUserId(mqttModel.getUserId()); - authorize.setUserName(""); - authorize.setUpdateTime(DateUtils.getNowDate()); - // 状态(1-未使用,2-使用中) - authorize.setStatus(2); - int result = productAuthorizeMapper.updateProductAuthorize(authorize); - if (result != 1) { - message = "设备认证,设备授权码关联失败"; - return message; - } - } - return message; - } - - /** - * 返回认证信息 - */ - @Override - public ResponseEntity returnUnauthorized(MqttAuthenticationModel mqttModel, String message) { - log.warn("认证失败:" + message - + "\nclientid:" + mqttModel.getClientId() - + "\nusername:" + mqttModel.getUserName() - + "\npassword:" + mqttModel.getPassword()); - return ResponseEntity.status(401).body("Unauthorized"); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/UserSocialProfileServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/UserSocialProfileServiceImpl.java deleted file mode 100644 index 598c45b4..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/UserSocialProfileServiceImpl.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.ruoyi.iot.service.impl; - -import com.ruoyi.common.constant.HttpStatus; -import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.redis.RedisCache; -import com.ruoyi.common.enums.SocialPlatformType; -import com.ruoyi.iot.domain.SocialUser; -import com.ruoyi.iot.domain.UserSocialProfile; -import com.ruoyi.iot.model.login.BindIdValue; -import com.ruoyi.iot.service.ISocialPlatformService; -import com.ruoyi.iot.service.ISocialUserService; -import com.ruoyi.iot.service.IUserSocialProfileService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.ArrayList; -import java.util.List; - -import static com.ruoyi.iot.service.impl.SocialLoginServiceImpl.BIND_REDIS_KEY; - -@Service -public class UserSocialProfileServiceImpl implements IUserSocialProfileService { - - @Autowired - private RedisCache redisCache; - @Autowired - private ISocialUserService iSocialUserService; - @Autowired - private ISocialPlatformService iSocialPlatformService; - - @Override - public List selectUserSocialProfile(Long sysUserId) { - SocialUser selectSocialUser = new SocialUser(); - selectSocialUser.setSysUserId(sysUserId); - List socialUserList = iSocialUserService.selectSocialUserList(selectSocialUser); - List userSocialProfileList = new ArrayList<>(); - for (SocialUser socialUser : socialUserList) { - //如果是删除的标记 - if (socialUser.getDelFlag().equals("1")) { - continue; - } - UserSocialProfile userSocialProfile = new UserSocialProfile(); - userSocialProfile.setSocialUserId(socialUser.getSocialUserId()); - userSocialProfile.setAvatar(socialUser.getAvatar()); - userSocialProfile.setSource(socialUser.getSource()); - userSocialProfile.setUsername(socialUser.getUsername()); - userSocialProfile.setNickname(socialUser.getNickname()); - userSocialProfile.setStatus(socialUser.getStatus()); - userSocialProfileList.add(userSocialProfile); - } - return userSocialProfileList; - } - - @Override - public AjaxResult bindUser(String bindId, Long sysUserId) { - BindIdValue bindValue = redisCache.getCacheObject(BIND_REDIS_KEY + bindId); - if (bindValue == null) { - //不作提示 - return AjaxResult.error(HttpStatus.NO_MESSAGE_ALERT, "未知异常"); - } - SocialUser socialUser = findSocialUser(bindValue.getUuid(), bindValue.getSource()); - SocialUser updateSocialUser = new SocialUser(); - updateSocialUser.setSocialUserId(socialUser.getSocialUserId()); - updateSocialUser.setSysUserId(sysUserId); - iSocialUserService.updateSocialUser(updateSocialUser); - redisCache.deleteObject(BIND_REDIS_KEY + bindId); - return AjaxResult.success("绑定成功!"); - } - - @Override - public AjaxResult bindSocialAccount(String platform) { - try { - SocialPlatformType.valueOf(platform); - } catch (Exception e) { - return AjaxResult.error("错误平台类型"); - } - return AjaxResult.success(); - } - - @Override - public AjaxResult unbindSocialAccount(Long socialUserId, Long sysUserId) { - SocialUser socialUser = iSocialUserService.selectSocialUserBySocialUserId(socialUserId); - if (socialUser == null) { - return AjaxResult.error("绑定账户不存在!"); - } else if (!socialUser.getSysUserId().equals(socialUserId)) { - return AjaxResult.error("用户账户和绑定账户不匹配!"); - } else { - SocialUser updateSocialUser = new SocialUser(); - updateSocialUser.setSocialUserId(socialUserId); - updateSocialUser.setSysUserId(-1L); - iSocialUserService.updateSocialUser(updateSocialUser); - return AjaxResult.success("解除绑定成功!"); - } - } - - public SocialUser findSocialUser(String uuid, String source) { - SocialUser socialUser = new SocialUser(); - socialUser.setSource(source); - socialUser.setUuid(uuid); - List socialUserList = iSocialUserService.selectSocialUserList(socialUser); - return socialUserList == null || socialUserList.isEmpty() ? null : socialUserList.get(0); - - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/task/IotAsyncExceptionHander.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/task/IotAsyncExceptionHander.java deleted file mode 100644 index 5073bee0..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/task/IotAsyncExceptionHander.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.ruoyi.iot.task; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; -import org.springframework.stereotype.Component; - -import java.lang.reflect.Method; - - -@Component -public class IotAsyncExceptionHander implements AsyncUncaughtExceptionHandler { - - private static final Logger logger = LoggerFactory.getLogger(IotAsyncExceptionHander.class); - - @Override - public void handleUncaughtException(Throwable ex, Method method, Object... params) { - logger.debug("=======>>>>>捕获线程异常信息"); - logger.error("======>>>>>> error message-{},method-name",ex.getMessage(),method.getName()); - - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/task/TaskConfigurer.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/task/TaskConfigurer.java deleted file mode 100644 index 602dfcce..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/task/TaskConfigurer.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.ruoyi.iot.task; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.scheduling.annotation.AsyncConfigurer; -import org.springframework.scheduling.annotation.EnableAsync; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; - -import java.util.concurrent.Executor; -import java.util.concurrent.ThreadPoolExecutor; - -@Configuration -@ComponentScan("com.ruoyi.iot") -//注解开启异步任务支持 -@EnableAsync -public class TaskConfigurer implements AsyncConfigurer { - - private static final Logger logger = LoggerFactory.getLogger(TaskConfigurer.class); - - @Autowired - private TaskExecutorConfig config; - - @Bean - TaskExecutorConfig config(){ - return new TaskExecutorConfig(); - } - - @Override - public Executor getAsyncExecutor() { - - ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); - taskExecutor.setCorePoolSize(config.getCoreSize()); - taskExecutor.setMaxPoolSize(config.getMaxSize()); - taskExecutor.setQueueCapacity(config.getQueueCapacity()); - taskExecutor.setThreadNamePrefix("iot-mqtt-"); - taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy()); - taskExecutor.initialize(); //数据初始化 - logger.debug("=====>>>>taskExecutor init"); - return taskExecutor; - } - - @Override - public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { - return AsyncConfigurer.super.getAsyncUncaughtExceptionHandler(); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/task/TaskExecutorConfig.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/task/TaskExecutorConfig.java deleted file mode 100644 index bd971d1a..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/task/TaskExecutorConfig.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.ruoyi.iot.task; - - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; - -@Component -@ConfigurationProperties(prefix = "spring.task.execution.pool") -public class TaskExecutorConfig { - - - private int coreSize; - - private int maxSize; - - private int queueCapacity; - - public int getCoreSize() { - return coreSize; - } - - public void setCoreSize(int coreSize) { - this.coreSize = coreSize; - } - - public int getMaxSize() { - return maxSize; - } - - public void setMaxSize(int maxSize) { - this.maxSize = maxSize; - } - - public int getQueueCapacity() { - return queueCapacity; - } - - public void setQueueCapacity(int queueCapacity) { - this.queueCapacity = queueCapacity; - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/config/TDengineConfig.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/config/TDengineConfig.java deleted file mode 100644 index 07ccf9d1..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/config/TDengineConfig.java +++ /dev/null @@ -1,95 +0,0 @@ -package com.ruoyi.iot.tdengine.config; - -import com.alibaba.druid.pool.DruidDataSource; -import com.ruoyi.common.utils.StringUtils; -import org.apache.ibatis.session.SqlSessionFactory; -import org.mybatis.spring.SqlSessionFactoryBean; -import org.mybatis.spring.SqlSessionTemplate; -import org.mybatis.spring.annotation.MapperScan; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.io.Resource; -import org.springframework.core.io.support.PathMatchingResourcePatternResolver; -import org.springframework.core.io.support.ResourcePatternResolver; - -import javax.sql.DataSource; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * 类名: TDengineConfig - * 描述: TDengine配置类 - * 时间: 2022/5/13,0016 1:14 - * 开发人: wxy - */ -@Configuration -@MapperScan(basePackages = {"com.ruoyi.iot.tdengine.dao"}, sqlSessionTemplateRef = "tdengineSqlSessionTemplate") -@ConditionalOnProperty(name = "spring.datasource.druid.tdengine-server.enabled", havingValue = "true") -public class TDengineConfig { - - @Value("${spring.datasource.druid.tdengine-server.dbName}") - private String dbName; - @Value("${spring.datasource.druid.tdengine-server.url}") - private String jdbc; - - - @Bean(name = "tDengineDataSource") - @ConfigurationProperties(prefix = "spring.datasource.druid.tdengine-server") - public DataSource tdengineDataSource() { - return new DruidDataSource(); - } - - - - @Bean(name = "tDengineSqlSessionFactory") - public SqlSessionFactory tDengineSqlSessionFactory(@Qualifier("tDengineDataSource") DataSource dataSource) throws Exception { - SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); - sqlSessionFactoryBean.setMapperLocations(resolveMapperLocations(StringUtils.split("classpath:mapper/tdengine/*Mapper.xml", ","))); - sqlSessionFactoryBean.setDataSource(dataSource); - return sqlSessionFactoryBean.getObject(); - } - - - @Bean(name = "tdengineSqlSessionTemplate") - public SqlSessionTemplate tdengineSqlSessionTemplate(@Qualifier("tDengineSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { - return new SqlSessionTemplate(sqlSessionFactory); - } - - public String getDbName() { - return dbName; - } - - public void setDbName(String dbName) { - this.dbName = dbName; - } - public Resource[] resolveMapperLocations(String[] mapperLocations) - { - ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver(); - List resources = new ArrayList(); - if (mapperLocations != null) - { - for (String mapperLocation : mapperLocations) - { - try - { - Resource[] mappers = resourceResolver.getResources(mapperLocation); - resources.addAll(Arrays.asList(mappers)); - } - catch (IOException e) - { - // ignore - } - } - } - return resources.toArray(new Resource[resources.size()]); - } - - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/dao/TDDeviceLogDAO.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/dao/TDDeviceLogDAO.java deleted file mode 100644 index 585e164c..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/dao/TDDeviceLogDAO.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.ruoyi.iot.tdengine.dao; - -import com.ruoyi.iot.domain.Device; -import com.ruoyi.iot.domain.DeviceLog; -import com.ruoyi.iot.model.DeviceStatistic; -import com.ruoyi.iot.model.MonitorModel; -import org.apache.ibatis.annotations.Param; -import org.springframework.stereotype.Repository; - -import java.util.Date; -import java.util.List; - -/** - * @package com.ruoyi.mysql.mysql.tdengine - * 类名: DatabaseMapper - * 时间: 2022/5/16,0016 1:27 - * 开发人: wxy - */ -@Repository -public interface TDDeviceLogDAO { - - /*** - * 创建数据库 - */ - int createDB( String database); - - /*** - * 创建超级表 - */ - int createSTable(String database); - - - /*** - * 新增设备日志 - */ - int save(@Param("database") String database,@Param("device") DeviceLog deviceLog); - - /*** - * 设备属性数据总数 - */ - Long selectPropertyLogCount(@Param("database") String database,@Param("device") Device device); - - /*** - * 设备功能数据总数 - */ - Long selectFunctionLogCount(@Param("database") String database,@Param("device") Device device); - - /*** - * 设备事件数据总数 - */ - Long selectEventLogCount(@Param("database") String database,@Param("device") Device device); - - /*** - * 设备监测数据总数 - */ - Long selectMonitorLogCount(@Param("database") String database,@Param("device") Device device); - - /*** - * 监测数据列表 - */ - List selectMonitorList(@Param("database") String database, @Param("device") DeviceLog deviceLog); - - /*** - * 日志列表 - */ - List selectDeviceLogList(@Param("database") String database,@Param("device") DeviceLog deviceLog); - - /*** - * 根据设备ID删除设备日志 - */ - int deleteDeviceLogByDeviceNumber(@Param("database")String dbName,@Param("serialNumber") String serialNumber); - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/init/ApplicationStarted.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/init/ApplicationStarted.java deleted file mode 100644 index 3e4691b0..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/init/ApplicationStarted.java +++ /dev/null @@ -1,136 +0,0 @@ -package com.ruoyi.iot.tdengine.init; - - -import com.alibaba.druid.pool.DruidDataSource; -import com.ruoyi.common.annotation.DataSource; -import com.ruoyi.iot.tdengine.config.TDengineConfig; -import com.ruoyi.iot.tdengine.dao.TDDeviceLogDAO; -import com.taosdata.jdbc.TSDBDriver; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.ApplicationArguments; -import org.springframework.boot.ApplicationRunner; -import org.springframework.context.ApplicationContext; -import org.springframework.lang.Nullable; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; -import java.io.*; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.util.Properties; - -/** - * 类名: ApplicationStarted - * 时间: 2022/5/18,0018 1:41 - * 开发人: wxy - */ -@Component -public class ApplicationStarted implements ApplicationRunner { - - private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationStarted.class); - - @Autowired - private ApplicationContext applicationContext; - - private DruidDataSource dataSource; - - private TDengineConfig dengineConfig; - - private TDDeviceLogDAO deviceLogMapper; - - - @Override - public void run(ApplicationArguments args) { - - //先获取TDengine的配置,检测TDengine是否已经配置 - if (containBean(TDengineConfig.class)) { - this.dengineConfig = applicationContext.getBean(TDengineConfig.class); - this.dataSource = applicationContext.getBean("tDengineDataSource", DruidDataSource.class); - this.deviceLogMapper= applicationContext.getBean(TDDeviceLogDAO.class); - initTDengine(this.dengineConfig.getDbName()); - LOGGER.info("使用TDengine存储设备数据,初始化成功"); - }else{ - LOGGER.info("使用MySql存储设备数据,初始化成功"); - } - } - - /** - * @return - * @Method - * @Description 开始初始化加载系统参数, 创建数据库和超级表 - * @Param null - * @date 2022/5/22,0022 14:27 - * @author wxy - */ - public void initTDengine(String dbName) { - try { - createDatabase(); - //创建数据库表 - deviceLogMapper.createSTable(dbName); - LOGGER.info("完成超级表的创建"); - } catch (Exception e) { - LOGGER.error("错误",e.getMessage()); - e.printStackTrace(); - } - - } - - /** - * @Method - * @Description 根据数据库连接自动创建数据库 - * @Param null - * @return - * @date 2022/5/24,0024 14:32 - * @author wxy - * - */ - private void createDatabase(){ - try { - String dbName = dengineConfig.getDbName(); - String jdbcUrl = dataSource.getRawJdbcUrl(); - String username = dataSource.getUsername(); - String password = dataSource.getPassword(); - jdbcUrl += ("&user=" + username); - jdbcUrl += ("&password=" + password); - int startIndex = jdbcUrl.indexOf('/',12); - int endIndex = jdbcUrl.indexOf('?'); - String newJdbcUrl = jdbcUrl.substring(0,startIndex); - newJdbcUrl= newJdbcUrl+jdbcUrl.substring(endIndex); - System.out.println(newJdbcUrl); - - Properties connProps = new Properties(); - connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); - connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); - connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8"); - Connection conn = DriverManager.getConnection(newJdbcUrl, connProps); - conn.createStatement().execute(String.format("create database if not exists %s;",dbName)); - conn.close(); - LOGGER.info("完成数据库创建"); - } catch (Exception e) { - LOGGER.info("错误",e.getMessage()); - e.printStackTrace(); - } - } - - /** - * @return - * @Method containBean - * @Description 根据类判断是否有对应bean - * @Param 类 - * @date 2022/5/22,0022 14:12 - * @author wxy - */ - private boolean containBean(@Nullable Class T) { - String[] beans = applicationContext.getBeanNamesForType(T); - if (beans == null || beans.length == 0) { - return false; - } else { - return true; - } - } - - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/service/ILogService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/service/ILogService.java deleted file mode 100644 index 0155ae9a..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/service/ILogService.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.ruoyi.iot.tdengine.service; - -import com.ruoyi.iot.domain.Device; -import com.ruoyi.iot.domain.DeviceLog; - -import com.ruoyi.iot.model.DeviceStatistic; -import com.ruoyi.iot.model.MonitorModel; -import org.springframework.stereotype.Service; - -import java.util.Date; -import java.util.List; - -/** - * @package iot.iot.log - * 类名: LogService - * 描述: 设备日志记录接口 - * 时间: 2022/5/19,0019 18:04 - * 开发人: admin - */ -public interface ILogService { - - /** 保存设备日志 **/ - int saveDeviceLog(DeviceLog deviceLog); - - /** 根据设备编号删除设备日志 **/ - int deleteDeviceLogByDeviceNumber(String deviceNumber); - - /** 设备属性、功能、事件总数 **/ - DeviceStatistic selectCategoryLogCount(Device device); - - /** 查询物模型日志列表 **/ - List selectDeviceLogList(DeviceLog deviceLog); - - /** 查询监测数据列表 **/ - List selectMonitorList(DeviceLog deviceLog); -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/service/factory/LogServiceFactory.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/service/factory/LogServiceFactory.java deleted file mode 100644 index 9736d9d0..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/service/factory/LogServiceFactory.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.ruoyi.iot.tdengine.service.factory; - -import com.ruoyi.framework.config.MyBatisConfig; -import com.ruoyi.iot.tdengine.service.impl.MySqlLogServiceImpl; -import com.ruoyi.iot.tdengine.service.impl.TdengineLogServiceImpl; -import com.ruoyi.iot.tdengine.config.TDengineConfig; -import com.ruoyi.iot.tdengine.service.ILogService; -import com.ruoyi.iot.mapper.DeviceLogMapper; -import com.ruoyi.iot.tdengine.dao.TDDeviceLogDAO; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.lang.Nullable; -import org.springframework.stereotype.Component; - -/** - * 类名: DeviceLogServiceImpl - * 时间: 2022/5/19,0019 18:09 - * 开发人: wxy - */ -@Component -public class LogServiceFactory { - - @Autowired - private ApplicationContext applicationContext; - - @Bean - public ILogService getLogService() { - //先获取TDengine的配置,检测TDengine是否已经配置 - if (containBean(TDengineConfig.class)) { - TDengineConfig tDengineConfig = applicationContext.getBean(TDengineConfig.class); - TDDeviceLogDAO tDDeviceLogDAO = applicationContext.getBean(TDDeviceLogDAO.class); - ILogService logService = new TdengineLogServiceImpl(tDengineConfig, tDDeviceLogDAO); - return logService; - } else if (containBean(MyBatisConfig.class)) { - //没有配置TDengine,那么使用MySQL的日志配置 - DeviceLogMapper deviceLogMapper = applicationContext.getBean( DeviceLogMapper.class); - ILogService logService = new MySqlLogServiceImpl(deviceLogMapper); - return logService; - } else { - return null; - } - } - - /** - * @Method containBean - * @Description 根据类判断是否有对应bean - * @Param 类 - * @return - * @date 2022/5/22,0022 14:12 - * @author wxy - * - */ - private boolean containBean(@Nullable Class T) { - String[] beans = applicationContext.getBeanNamesForType(T); - if (beans == null || beans.length == 0) { - return false; - } else { - return true; - } - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/service/impl/MySqlLogServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/service/impl/MySqlLogServiceImpl.java deleted file mode 100644 index 2417e13b..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/service/impl/MySqlLogServiceImpl.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.ruoyi.iot.tdengine.service.impl; - -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.iot.domain.Device; -import com.ruoyi.iot.domain.DeviceLog; -import com.ruoyi.iot.model.DeviceStatistic; -import com.ruoyi.iot.tdengine.service.ILogService; -import com.ruoyi.iot.mapper.DeviceLogMapper; -import com.ruoyi.iot.model.MonitorModel; - -import java.util.List; - -/** - * 类名: MySqlLogServiceImpl - * 描述: MySQL存储日志实现类 - * 时间: 2022/5/22,0022 13:37 - * 开发人: admin - */ -public class MySqlLogServiceImpl implements ILogService { - - private DeviceLogMapper deviceLogMapper; - - public MySqlLogServiceImpl(DeviceLogMapper _deviceLogMapper){ - this.deviceLogMapper=_deviceLogMapper; - } - - /*** - * 新增设备日志 - * @return - */ - @Override - public int saveDeviceLog(DeviceLog deviceLog) { - return deviceLogMapper.insertDeviceLog(deviceLog); - } - - /*** - * 根据设备ID删除设备日志 - * @return - */ - @Override - public int deleteDeviceLogByDeviceNumber(String deviceNumber) { - return deviceLogMapper.deleteDeviceLogByDeviceNumber(deviceNumber); - } - - /*** - * 设备属性、功能、事件和监测数据总数 - * @return - */ - @Override - public DeviceStatistic selectCategoryLogCount(Device device){ - return deviceLogMapper.selectCategoryLogCount(device); - } - - /*** - * 日志列表 - * @return - */ - @Override - public List selectDeviceLogList(DeviceLog deviceLog) { - return deviceLogMapper.selectDeviceLogList(deviceLog); - } - - /*** - * 监测数据列表 - * @return - */ - @Override - public List selectMonitorList(DeviceLog deviceLog) { - return deviceLogMapper.selectMonitorList(deviceLog); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/service/impl/TdengineLogServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/service/impl/TdengineLogServiceImpl.java deleted file mode 100644 index 3b248d0a..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/service/impl/TdengineLogServiceImpl.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.ruoyi.iot.tdengine.service.impl; - -import com.ruoyi.iot.domain.Device; -import com.ruoyi.iot.domain.DeviceLog; -import com.ruoyi.iot.model.DeviceStatistic; -import com.ruoyi.iot.tdengine.service.ILogService; -import com.ruoyi.iot.model.MonitorModel; -import com.ruoyi.iot.tdengine.config.TDengineConfig; -import com.ruoyi.iot.tdengine.dao.TDDeviceLogDAO; -import com.ruoyi.iot.util.SnowflakeIdWorker; -import org.springframework.context.ApplicationContext; - -import java.util.List; - -/** - * 类名: TdengineLogServiceImpl - * 描述: TDengine存储日志数据实现类 - * 时间: 2022/5/22,0022 13:38 - * 开发人: admin - */ -public class TdengineLogServiceImpl implements ILogService { - - private ApplicationContext applicationContext; - - private TDDeviceLogDAO tdDeviceLogDAO; - - private TDengineConfig tDengineConfig; - - private SnowflakeIdWorker snowflakeIdWorker; - - private String dbName; - - public TdengineLogServiceImpl(TDengineConfig _tDengineConfig, TDDeviceLogDAO _tdDeviceLogDAO) { - this.tdDeviceLogDAO = _tdDeviceLogDAO; - this.tDengineConfig = _tDengineConfig; - snowflakeIdWorker=new SnowflakeIdWorker(1); - this.dbName=_tDengineConfig.getDbName(); - } - - /*** - * 新增设备日志 - * @return - */ - @Override - public int saveDeviceLog(DeviceLog deviceLog) { - long logId = snowflakeIdWorker.nextId(); - deviceLog.setLogId(logId); - return tdDeviceLogDAO.save(dbName,deviceLog); - } - - /*** - * 设备属性、功能、事件和监测数据总数 - * @return - */ - @Override - public DeviceStatistic selectCategoryLogCount(Device device){ - DeviceStatistic statistic=new DeviceStatistic(); - Long property=tdDeviceLogDAO.selectPropertyLogCount(dbName,device); - Long function=tdDeviceLogDAO.selectFunctionLogCount(dbName,device); - Long event=tdDeviceLogDAO.selectEventLogCount(dbName,device); - Long monitor=tdDeviceLogDAO.selectMonitorLogCount(dbName,device); - statistic.setPropertyCount(property==null?0:property); - statistic.setFunctionCount(function==null?0:function); - statistic.setEventCount(event==null?0:event); - statistic.setMonitorCount(monitor==null?0:monitor); - return statistic; - } - - /*** - * 日志列表 - * @return - */ - @Override - public List selectDeviceLogList(DeviceLog deviceLog) { - return tdDeviceLogDAO.selectDeviceLogList(dbName,deviceLog); - } - - /*** - * 监测数据列表 - * @return - */ - @Override - public List selectMonitorList(DeviceLog deviceLog) { - if(deviceLog.getIdentity()!=null){ - deviceLog.setIdentity("%"+deviceLog.getIdentity()+"%"); - } - return tdDeviceLogDAO.selectMonitorList(dbName,deviceLog); - } - - /*** - * 根据设备ID删除设备日志 - * @return - */ - @Override - public int deleteDeviceLogByDeviceNumber(String deviceNumber) { - return tdDeviceLogDAO.deleteDeviceLogByDeviceNumber(dbName,deviceNumber); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/AESUtils.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/AESUtils.java deleted file mode 100644 index f860c329..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/AESUtils.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.ruoyi.iot.util; - -import javax.crypto.Cipher; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; - -import sun.misc.BASE64Decoder; -import sun.misc.BASE64Encoder; - -import java.security.MessageDigest; - -/** - * - */ -public class AESUtils { - - /** - * 加密用的Key 可以用26个字母和数字组成 使用AES-128-CBC加密模式,key需要为16位。iv 偏移量,长度16 - */ - private static final String ivString = "wumei-smart-open"; - private static final String ENCRYPT_MODE = "CBC"; // ECB和CBC两种模式 - - // 加密 - public static String encrypt(String plainText, String key) { - // 判断Key是否正确 - if (key == null || key.length() != 16) { - System.out.print("Key不能为空,长度不是16位"); - return null; - } - try { - byte[] raw = key.getBytes("utf-8"); - SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); - Cipher cipher = Cipher.getInstance("AES/" + AESUtils.ENCRYPT_MODE + "/PKCS5Padding"); - if (AESUtils.ENCRYPT_MODE.equals("ECB")) { - cipher.init(Cipher.ENCRYPT_MODE, skeySpec); - } else { - IvParameterSpec iv = new IvParameterSpec(ivString.getBytes("utf-8"));//使用CBC模式,需要一个向量iv,可增加加密算法的强度 - cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv); - } - byte[] encrypted = cipher.doFinal(plainText.getBytes("utf-8")); - String encryptedStr = new String(new BASE64Encoder().encode(encrypted)); - //此处使用BASE64做转码功能,同时能起到2次加密的作用。 - return encryptedStr; - } catch (Exception ex) { - System.out.println(ex.toString()); - return null; - } - } - - // 解密 - public static String decrypt(String cipherText, String key) { - // 判断Key是否正确 - if (key == null || key.length() != 16) { - System.out.print("Key不能为空,长度不是16位"); - return null; - } - // 根据html规范,后端接口,接收参数包含+号会被替换为空格。所以这里需要还原回来,不然会造成解密失败 - cipherText=cipherText.replace(' ','+'); - - try { - byte[] raw = key.getBytes("utf-8"); - SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); - Cipher cipher = Cipher.getInstance("AES/" + AESUtils.ENCRYPT_MODE + "/PKCS5Padding"); - if (AESUtils.ENCRYPT_MODE.equals("ECB")) { - cipher.init(Cipher.DECRYPT_MODE, skeySpec); - } else { - //使用CBC模式,需要一个向量iv,可增加加密算法的强度 - IvParameterSpec iv = new IvParameterSpec(ivString.getBytes("utf-8")); - cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); - } - //先用base64解密 - byte[] encrypted = new BASE64Decoder().decodeBuffer(cipherText); - try { - byte[] original = cipher.doFinal(encrypted); - String originalString = new String(original, "utf-8"); - return originalString; - } catch (Exception e) { - System.out.println(e.toString()); - return null; - } - } catch (Exception ex) { - System.out.println(ex.toString()); - return null; - } - } - - /** - * 进行MD5加密 - * - * @param s 要进行MD5转换的字符串 - * @return 该字符串的MD5值的8-24位 - */ - public static String getMD5(String s) { - char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; - - try { - byte[] btInput = s.getBytes(); - // 获得MD5摘要算法的 MessageDigest 对象 - MessageDigest mdInst = MessageDigest.getInstance("MD5"); - // 使用指定的字节更新摘要 - mdInst.update(btInput); - // 获得密文 - byte[] md = mdInst.digest(); - // 把密文转换成十六进制的字符串形式 - int j = md.length; - char str[] = new char[j * 2]; - int k = 0; - for (int i = 0; i < j; i++) { - byte byte0 = md[i]; - str[k++] = hexDigits[byte0 >>> 4 & 0xf]; - str[k++] = hexDigits[byte0 & 0xf]; - } - return new String(str).substring(8, 24); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/SnowflakeIdWorker.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/SnowflakeIdWorker.java deleted file mode 100644 index ff5a11d3..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/SnowflakeIdWorker.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.ruoyi.iot.util; - -public class SnowflakeIdWorker { - /** - * 开始时间:2020-01-01 00:00:00 - */ - private final long beginTs = 1577808000000L; - - private final long workerIdBits = 10; - - /** - * 2^10 - 1 = 1023 - */ - private final long maxWorkerId = -1L ^ (-1L << workerIdBits); - - private final long sequenceBits = 12; - - /** - * 2^12 - 1 = 4095 - */ - private final long maxSequence = -1L ^ (-1L << sequenceBits); - - /** - * 时间戳左移22位 - */ - private final long timestampLeftOffset = workerIdBits + sequenceBits; - - /** - * 业务ID左移12位 - */ - private final long workerIdLeftOffset = sequenceBits; - - /** - * 合并了机器ID和数据标示ID,统称业务ID,10位 - */ - private long workerId; - - /** - * 毫秒内序列,12位,2^12 = 4096个数字 - */ - private long sequence = 0L; - - /** - * 上一次生成的ID的时间戳,同一个worker中 - */ - private long lastTimestamp = -1L; - - public SnowflakeIdWorker(long workerId) { - if (workerId > maxWorkerId || workerId < 0) { - throw new IllegalArgumentException(String.format("WorkerId必须大于或等于0且小于或等于%d", maxWorkerId)); - } - - this.workerId = workerId; - } - - public synchronized long nextId() { - long ts = System.currentTimeMillis(); - if (ts < lastTimestamp) { - throw new RuntimeException(String.format("系统时钟回退了%d毫秒", (lastTimestamp - ts))); - } - - // 同一时间内,则计算序列号 - if (ts == lastTimestamp) { - // 序列号溢出 - if (++sequence > maxSequence) { - ts = tilNextMillis(lastTimestamp); - sequence = 0L; - } - } else { - // 时间戳改变,重置序列号 - sequence = 0L; - } - - lastTimestamp = ts; - - // 0 - 00000000 00000000 00000000 00000000 00000000 0 - 00000000 00 - 00000000 0000 - // 左移后,低位补0,进行按位或运算相当于二进制拼接 - // 本来高位还有个0<<63,0与任何数字按位或都是本身,所以写不写效果一样 - return (ts - beginTs) << timestampLeftOffset | workerId << workerIdLeftOffset | sequence; - } - - /** - * 阻塞到下一个毫秒 - * - * @param lastTimestamp - * @return - */ - private long tilNextMillis(long lastTimestamp) { - long ts = System.currentTimeMillis(); - while (ts <= lastTimestamp) { - ts = System.currentTimeMillis(); - } - - return ts; - } - - public static void main(String[] args) { - SnowflakeIdWorker snowflakeIdWorker = new SnowflakeIdWorker(7); - for (int i = 0; i < 10; i++) { - long id = snowflakeIdWorker.nextId(); - System.out.println(id); - } - } -} \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/VelocityInitializer.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/VelocityInitializer.java deleted file mode 100644 index 29a7bb73..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/VelocityInitializer.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.ruoyi.iot.util; - -import com.ruoyi.common.constant.Constants; -import org.apache.velocity.app.Velocity; - -import java.util.Properties; - -/** - * VelocityEngine工厂 - * - * @author ruoyi - */ -public class VelocityInitializer -{ - /** - * 初始化vm方法 - */ - public static void initVelocity() - { - Properties p = new Properties(); - try - { - // 加载classpath目录下的vm文件 - p.setProperty("resource.loader.file.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); - // 定义字符集 - p.setProperty(Velocity.INPUT_ENCODING, Constants.UTF8); - // 初始化Velocity引擎,指定配置Properties - Velocity.init(p); - } - catch (Exception e) - { - throw new RuntimeException(e); - } - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/VelocityUtils.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/VelocityUtils.java deleted file mode 100644 index 6ac0e1b8..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/VelocityUtils.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.ruoyi.iot.util; - -import com.alibaba.fastjson.JSONObject; -import com.ruoyi.common.constant.GenConstants; -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.common.utils.StringUtils; -import org.apache.velocity.VelocityContext; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; - -/** - * 模板处理工具类 - * - * @author ruoyi - */ -public class VelocityUtils -{ - /** 项目空间路径 */ - private static final String PROJECT_PATH = "main/java"; - - /** mybatis空间路径 */ - private static final String MYBATIS_PATH = "main/resources/mapper"; - - /** 默认上级菜单,系统工具 */ - private static final String DEFAULT_PARENT_MENU_ID = "3"; - - /** - * 设置模板变量信息 - * - * @return 模板列表 - */ - public static VelocityContext prepareContext(int deviceChip) - { - - VelocityContext velocityContext = new VelocityContext(); - return velocityContext; - } - - - /** - * 获取模板信息 - * - * @return 模板列表 - */ - public static List getTemplateList(String tplCategory) - { - List templates = new ArrayList(); - templates.add("vm/java/domain.java.vm"); - templates.add("vm/java/controller.java.vm"); - if (GenConstants.TPL_CRUD.equals(tplCategory)) - { - templates.add("vm/vue/index.vue.vm"); - } - else if (GenConstants.TPL_TREE.equals(tplCategory)) - { - templates.add("vm/vue/index-tree.vue.vm"); - } - else if (GenConstants.TPL_SUB.equals(tplCategory)) - { - templates.add("vm/vue/index.vue.vm"); - templates.add("vm/java/sub-domain.java.vm"); - } - return templates; - } - - /** - * 获取文件名 - */ - public static String getFileName(String template) - { - // 文件名称 - String fileName = ""; - String vuePath = "vue"; - - if (template.contains("domain.java.vm")) - { - fileName = StringUtils.format("{}/domain/{}.java", "test", "test"); - } else if (template.contains("controller.java.vm")) - { - fileName = StringUtils.format("{}/controller/{}Controller.java", "test", "test"); - } - return fileName; - } - - - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/quartz/AbstractQuartzJob.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/quartz/AbstractQuartzJob.java deleted file mode 100644 index bb67f8b9..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/quartz/AbstractQuartzJob.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.ruoyi.iot.util.quartz; - -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.constant.ScheduleConstants; -import com.ruoyi.common.utils.ExceptionUtil; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.bean.BeanUtils; -import com.ruoyi.common.utils.spring.SpringUtils; -import com.ruoyi.iot.domain.DeviceJob; -import com.ruoyi.quartz.domain.SysJobLog; -import com.ruoyi.quartz.service.ISysJobLogService; -import org.quartz.Job; -import org.quartz.JobExecutionContext; -import org.quartz.JobExecutionException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Date; - -/** - * 抽象quartz调用 - * - * @author ruoyi - */ -public abstract class AbstractQuartzJob implements Job -{ - private static final Logger log = LoggerFactory.getLogger(AbstractQuartzJob.class); - - /** - * 线程本地变量 - */ - private static ThreadLocal threadLocal = new ThreadLocal<>(); - - @Override - public void execute(JobExecutionContext context) throws JobExecutionException - { - DeviceJob deviceJob = new DeviceJob(); - BeanUtils.copyBeanProp(deviceJob, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES)); - try - { - before(context, deviceJob); - if (deviceJob != null) - { - doExecute(context, deviceJob); - } - after(context, deviceJob, null); - } - catch (Exception e) - { - log.error("任务执行异常 - :", e); - after(context, deviceJob, e); - } - } - - /** - * 执行前 - * - * @param context 工作执行上下文对象 - * @param deviceJob 系统计划任务 - */ - protected void before(JobExecutionContext context, DeviceJob deviceJob) - { - threadLocal.set(new Date()); - } - - /** - * 执行后 - * - * @param context 工作执行上下文对象 - * @param deviceJob 系统计划任务 - */ - protected void after(JobExecutionContext context, DeviceJob deviceJob, Exception e) - { - Date startTime = threadLocal.get(); - threadLocal.remove(); - - final SysJobLog sysJobLog = new SysJobLog(); - sysJobLog.setJobName(deviceJob.getJobName()); - sysJobLog.setJobGroup(deviceJob.getJobGroup()); - sysJobLog.setInvokeTarget(deviceJob.getDeviceName()); - sysJobLog.setStartTime(startTime); - sysJobLog.setStopTime(new Date()); - long runMs = sysJobLog.getStopTime().getTime() - sysJobLog.getStartTime().getTime(); - sysJobLog.setJobMessage(sysJobLog.getJobName() + " 总共耗时:" + runMs + "毫秒"); - if (e != null) - { - sysJobLog.setStatus(Constants.FAIL); - String errorMsg = StringUtils.substring(ExceptionUtil.getExceptionMessage(e), 0, 2000); - sysJobLog.setExceptionInfo(errorMsg); - } - else - { - sysJobLog.setStatus(Constants.SUCCESS); - } - - // 写入数据库当中 - SpringUtils.getBean(ISysJobLogService.class).addJobLog(sysJobLog); - } - - /** - * 执行方法,由子类重载 - * - * @param context 工作执行上下文对象 - * @param deviceJob 系统计划任务 - * @throws Exception 执行过程中的异常 - */ - protected abstract void doExecute(JobExecutionContext context, DeviceJob deviceJob) throws Exception; -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/quartz/CronUtils.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/quartz/CronUtils.java deleted file mode 100644 index 37c506a8..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/quartz/CronUtils.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.ruoyi.iot.util.quartz; - -import org.quartz.CronExpression; - -import java.text.ParseException; -import java.util.Date; - -/** - * cron表达式工具类 - * - * @author ruoyi - * - */ -public class CronUtils -{ - /** - * 返回一个布尔值代表一个给定的Cron表达式的有效性 - * - * @param cronExpression Cron表达式 - * @return boolean 表达式是否有效 - */ - public static boolean isValid(String cronExpression) - { - return CronExpression.isValidExpression(cronExpression); - } - - /** - * 返回一个字符串值,表示该消息无效Cron表达式给出有效性 - * - * @param cronExpression Cron表达式 - * @return String 无效时返回表达式错误描述,如果有效返回null - */ - public static String getInvalidMessage(String cronExpression) - { - try - { - new CronExpression(cronExpression); - return null; - } - catch (ParseException pe) - { - return pe.getMessage(); - } - } - - /** - * 返回下一个执行时间根据给定的Cron表达式 - * - * @param cronExpression Cron表达式 - * @return Date 下次Cron表达式执行时间 - */ - public static Date getNextExecution(String cronExpression) - { - try - { - CronExpression cron = new CronExpression(cronExpression); - return cron.getNextValidTimeAfter(new Date(System.currentTimeMillis())); - } - catch (ParseException e) - { - throw new IllegalArgumentException(e.getMessage()); - } - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/quartz/JobInvokeUtil.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/quartz/JobInvokeUtil.java deleted file mode 100644 index ad09d1ae..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/quartz/JobInvokeUtil.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.ruoyi.iot.util.quartz; - -import com.alibaba.fastjson.JSON; -import com.ruoyi.common.utils.spring.SpringUtils; -import com.ruoyi.iot.domain.DeviceJob; -import com.ruoyi.iot.model.Action; -import com.ruoyi.iot.model.ThingsModels.IdentityAndName; -import com.ruoyi.iot.mqtt.EmqxService; - -import java.util.ArrayList; -import java.util.List; - -/** - * 任务执行工具 - * - * @author kerwincui - */ -public class JobInvokeUtil -{ - /** - * 执行方法 - * - * @param deviceJob 系统任务 - */ - public static void invokeMethod(DeviceJob deviceJob) throws Exception - { - if(deviceJob.getJobType()==1){ - System.out.println("------------------------执行定时任务-----------------------------"); - List actions= JSON.parseArray(deviceJob.getActions(),Action.class); - List propertys=new ArrayList<>(); - List functions=new ArrayList<>(); - for(int i=0;i0){ - emqxService.publishProperty(deviceJob.getProductId(),deviceJob.getSerialNumber(),propertys); - } - // 发布功能 - if(functions.size()>0){ - emqxService.publishFunction(deviceJob.getProductId(),deviceJob.getSerialNumber(),functions); - } - - }else if(deviceJob.getJobType()==2){ - // 告警 - - System.out.println("------------------------执行告警-----------------------------"); - }else if(deviceJob.getJobType()==3){ - // 场景联动 - - System.out.println("------------------------执行场景联动-----------------------------"); - } - } - - -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/quartz/QuartzDisallowConcurrentExecution.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/quartz/QuartzDisallowConcurrentExecution.java deleted file mode 100644 index 9903064d..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/quartz/QuartzDisallowConcurrentExecution.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.ruoyi.iot.util.quartz; - -import com.ruoyi.iot.domain.DeviceJob; -import org.quartz.DisallowConcurrentExecution; -import org.quartz.JobExecutionContext; - -/** - * 定时任务处理(禁止并发执行) - * - * @author ruoyi - * - */ -@DisallowConcurrentExecution -public class QuartzDisallowConcurrentExecution extends AbstractQuartzJob -{ - @Override - protected void doExecute(JobExecutionContext context, DeviceJob deviceJob) throws Exception - { - JobInvokeUtil.invokeMethod(deviceJob); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/quartz/QuartzJobExecution.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/quartz/QuartzJobExecution.java deleted file mode 100644 index 8a0e8957..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/quartz/QuartzJobExecution.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.ruoyi.iot.util.quartz; - -import com.ruoyi.iot.domain.DeviceJob; -import org.quartz.JobExecutionContext; - -/** - * 定时任务处理(允许并发执行) - * - * @author ruoyi - * - */ -public class QuartzJobExecution extends AbstractQuartzJob -{ - @Override - protected void doExecute(JobExecutionContext context, DeviceJob deviceJob) throws Exception - { - JobInvokeUtil.invokeMethod(deviceJob); - } -} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/quartz/ScheduleUtils.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/quartz/ScheduleUtils.java deleted file mode 100644 index 0db772b9..00000000 --- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/quartz/ScheduleUtils.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.ruoyi.iot.util.quartz; - -import com.ruoyi.common.constant.ScheduleConstants; -import com.ruoyi.common.exception.job.TaskException; -import com.ruoyi.common.exception.job.TaskException.Code; -import com.ruoyi.iot.domain.DeviceJob; -import org.quartz.*; - -/** - * 定时任务工具类 - * - * @author ruoyi - * - */ -public class ScheduleUtils -{ - /** - * 得到quartz任务类 - * - * @param deviceJob 执行计划 - * @return 具体执行任务类 - */ - private static Class getQuartzJobClass(DeviceJob deviceJob) - { - boolean isConcurrent = "0".equals(deviceJob.getConcurrent()); - return isConcurrent ? QuartzJobExecution.class : QuartzDisallowConcurrentExecution.class; - } - - /** - * 构建任务触发对象 - */ - public static TriggerKey getTriggerKey(Long jobId, String jobGroup) - { - return TriggerKey.triggerKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup); - } - - /** - * 构建任务键对象 - */ - public static JobKey getJobKey(Long jobId, String jobGroup) - { - return JobKey.jobKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup); - } - - /** - * 创建定时任务 - */ - public static void createScheduleJob(Scheduler scheduler, DeviceJob job) throws SchedulerException, TaskException - { - Class jobClass = getQuartzJobClass(job); - // 1.创建任务 - Long jobId = job.getJobId(); - String jobGroup = job.getJobGroup(); - JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(getJobKey(jobId, jobGroup)).build(); - - // 表达式调度构建器 - CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression()); - cronScheduleBuilder = handleCronScheduleMisfirePolicy(job, cronScheduleBuilder); - - // 2.创建触发器, 按新的cronExpression表达式构建一个新的trigger - CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(jobId, jobGroup)) - .withSchedule(cronScheduleBuilder).build(); - - // 放入参数,运行时的方法可以获取 - jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job); - - // 判断是否存在 - if (scheduler.checkExists(getJobKey(jobId, jobGroup))) - { - // 防止创建时存在数据问题 先移除,然后在执行创建操作 - scheduler.deleteJob(getJobKey(jobId, jobGroup)); - } - - // 3.任务和触发器添加到调度器 - scheduler.scheduleJob(jobDetail, trigger); - - // 暂停任务 - if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue())) - { - scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup)); - } - } - - /** - * 设置定时任务策略 - */ - public static CronScheduleBuilder handleCronScheduleMisfirePolicy(DeviceJob job, CronScheduleBuilder cb) - throws TaskException - { - switch (job.getMisfirePolicy()) - { - case ScheduleConstants.MISFIRE_DEFAULT: - return cb; - case ScheduleConstants.MISFIRE_IGNORE_MISFIRES: - return cb.withMisfireHandlingInstructionIgnoreMisfires(); - case ScheduleConstants.MISFIRE_FIRE_AND_PROCEED: - return cb.withMisfireHandlingInstructionFireAndProceed(); - case ScheduleConstants.MISFIRE_DO_NOTHING: - return cb.withMisfireHandlingInstructionDoNothing(); - default: - throw new TaskException("The task misfire policy '" + job.getMisfirePolicy() - + "' cannot be used in cron schedule tasks", Code.CONFIG_ERROR); - } - } -} diff --git a/springboot/wumei-iot/src/main/resources/mapper/iot/AlertLogMapper.xml b/springboot/wumei-iot/src/main/resources/mapper/iot/AlertLogMapper.xml deleted file mode 100644 index 738def9c..00000000 --- a/springboot/wumei-iot/src/main/resources/mapper/iot/AlertLogMapper.xml +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - select alert_log__id, alert_name, alert_level, status, product_id, product_name, device_id, device_name,user_id, user_name, tenant_id, tenant_name, create_by, create_time, update_by, update_time, remark from iot_alert_log - - - - - - - - insert into iot_alert_log - - alert_name, - alert_level, - status, - product_id, - product_name, - device_id, - device_name, - create_by, - create_time, - update_by, - update_time, - remark, - user_id, - user_name, - tenant_id, - tenant_name, - - - #{alertName}, - #{alertLevel}, - #{status}, - #{productId}, - #{productName}, - #{deviceId}, - #{deviceName}, - #{createBy}, - #{createTime}, - #{updateBy}, - #{updateTime}, - #{remark}, - #{userId}, - #{userName}, - #{tenantId}, - #{tenantName}, - - - - - update iot_alert_log - - alert_name = #{alertName}, - alert_level = #{alertLevel}, - status = #{status}, - product_id = #{productId}, - product_name = #{productName}, - device_id = #{deviceId}, - device_name = #{deviceName}, - create_by = #{createBy}, - create_time = #{createTime}, - update_by = #{updateBy}, - update_time = #{updateTime}, - remark = #{remark}, - user_id = #{userId}, - user_name = #{userName}, - tenant_id = #{tenantId}, - tenant_name = #{tenantName}, - - where alert_log__id = #{alertLogId} - - - - delete from iot_alert_log where alert_log__id = #{alertLogId} - - - - delete from iot_alert_log where alert_log__id in - - #{alertLogId} - - - \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/resources/mapper/iot/AlertMapper.xml b/springboot/wumei-iot/src/main/resources/mapper/iot/AlertMapper.xml deleted file mode 100644 index b1a74cd5..00000000 --- a/springboot/wumei-iot/src/main/resources/mapper/iot/AlertMapper.xml +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - select alert_id, alert_name, alert_level,status, product_id, product_name, triggers, actions, create_by, create_time, update_by, update_time, remark from iot_alert - - - - - - - - insert into iot_alert - - alert_name, - alert_level, - status, - product_id, - product_name, - triggers, - actions, - create_by, - create_time, - update_by, - update_time, - remark, - - - #{alertName}, - #{alertLevel}, - #{status}, - #{productId}, - #{productName}, - #{triggers}, - #{actions}, - #{createBy}, - #{createTime}, - #{updateBy}, - #{updateTime}, - #{remark}, - - - - - update iot_alert - - alert_name = #{alertName}, - alert_level = #{alertLevel}, - status = #{status}, - product_id = #{productId}, - product_name = #{productName}, - triggers = #{triggers}, - actions = #{actions}, - create_by = #{createBy}, - create_time = #{createTime}, - update_by = #{updateBy}, - update_time = #{updateTime}, - remark = #{remark}, - - where alert_id = #{alertId} - - - - delete from iot_alert where alert_id = #{alertId} - - - - delete from iot_alert where alert_id in - - #{alertId} - - - \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/resources/mapper/iot/CategoryMapper.xml b/springboot/wumei-iot/src/main/resources/mapper/iot/CategoryMapper.xml deleted file mode 100644 index 1fb0c25b..00000000 --- a/springboot/wumei-iot/src/main/resources/mapper/iot/CategoryMapper.xml +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - select category_id, category_name, tenant_id, tenant_name, is_sys,order_num, create_time, update_time, remark from iot_category - - - - - - - - - - insert into iot_category - - category_name, - tenant_id, - tenant_name, - is_sys, - order_num, - create_by, - create_time, - update_by, - update_time, - remark, - - - #{categoryName}, - #{tenantId}, - #{tenantName}, - #{isSys}, - #{orderNum}, - #{createBy}, - #{createTime}, - #{updateBy}, - #{updateTime}, - #{remark}, - - - - - update iot_category - - category_name = #{categoryName}, - tenant_id = #{tenantId}, - tenant_name = #{tenantName}, - is_sys = #{isSys}, - order_num = #{orderNum}, - create_by = #{createBy}, - create_time = #{createTime}, - update_by = #{updateBy}, - update_time = #{updateTime}, - remark = #{remark}, - - where category_id = #{categoryId} - - - - delete from iot_category where category_id = #{categoryId} - - - - delete from iot_category where category_id in - - #{categoryId} - - - - - \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/resources/mapper/iot/DeviceJobMapper.xml b/springboot/wumei-iot/src/main/resources/mapper/iot/DeviceJobMapper.xml deleted file mode 100644 index b7cbe597..00000000 --- a/springboot/wumei-iot/src/main/resources/mapper/iot/DeviceJobMapper.xml +++ /dev/null @@ -1,160 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - select job_id, job_name, job_group,serial_number, device_id,device_name,actions,is_advance, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark, job_type, product_id, product_name, scene_id, alert_id - from iot_device_job - - - - - - - - - - - - delete from iot_device_job where job_id = #{jobId} - - - - delete from iot_device_job where job_id in - - #{jobId} - - - - - delete from iot_device_job where device_id in - - #{deviceId} - - - - - update iot_device_job - - job_name = #{jobName}, - job_group = #{jobGroup}, - device_id = #{deviceId}, - device_name = #{deviceName}, - serial_number = #{serialNumber}, - actions = #{actions}, - cron_expression = #{cronExpression}, - misfire_policy = #{misfirePolicy}, - concurrent = #{concurrent}, - status = #{status}, - remark = #{remark}, - update_by = #{updateBy}, - job_type = #{jobType}, - product_id = #{productId}, - product_name = #{productName}, - scene_id = #{sceneId}, - alert_id = #{alertId}, - is_advance =#{isAdvance}, - update_time = sysdate() - - where job_id = #{jobId} - - - - insert into iot_device_job( - job_id, - job_name, - job_group, - device_id, - device_name, - serial_number, - actions, - cron_expression, - misfire_policy, - concurrent, - status, - remark, - create_by, - job_type, - product_id, - product_name, - scene_id, - alert_id, - is_advance, - create_time - )values( - #{jobId}, - #{jobName}, - #{jobGroup}, - #{deviceId}, - #{deviceName}, - #{serialNumber}, - #{actions}, - #{cronExpression}, - #{misfirePolicy}, - #{concurrent}, - #{status}, - #{remark}, - #{createBy}, - #{jobType}, - #{productId}, - #{productName}, - #{sceneId}, - #{alertId}, - #{isAdvance}, - sysdate() - ) - - - \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/resources/mapper/iot/DeviceLogMapper.xml b/springboot/wumei-iot/src/main/resources/mapper/iot/DeviceLogMapper.xml deleted file mode 100644 index 7e19f343..00000000 --- a/springboot/wumei-iot/src/main/resources/mapper/iot/DeviceLogMapper.xml +++ /dev/null @@ -1,173 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - select log_id, log_type, log_value, device_id, device_name,serial_number, identity, create_by, is_monitor,mode, user_id, user_name, tenant_id, tenant_name, create_time, remark from iot_device_log - - - - - - - - - - - - insert into iot_device_log - - log_type, - log_value, - device_id, - device_name, - serial_number, - identity, - create_by, - is_monitor, - mode, - create_time, - remark, - user_id, - user_name, - tenant_id, - tenant_name, - - - #{logType}, - #{logValue}, - #{deviceId}, - #{deviceName}, - #{serialNumber}, - #{identity}, - #{createBy}, - #{isMonitor}, - #{mode}, - #{createTime}, - #{remark}, - #{userId}, - #{userName}, - #{tenantId}, - #{tenantName}, - - - - - update iot_device_log - - log_type = #{logType}, - log_value = #{logValue}, - device_id = #{deviceId}, - device_name = #{deviceName}, - serial_number = #{serialNumber}, - identity = #{identity}, - create_by = #{createBy}, - is_monitor = #{isMonitor}, - mode = #{mode}, - create_time = #{createTime}, - remark = #{remark}, - user_id = #{userId}, - user_name = #{userName}, - tenant_id = #{tenantId}, - tenant_name = #{tenantName}, - - where log_id = #{logId} - - - - delete from iot_device_log where log_id = #{logId} - - - - delete from iot_device_log where log_id in - - #{logId} - - - - - delete from iot_device_log where serial_number = #{deviceNumber} - - \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/resources/mapper/iot/DeviceMapper.xml b/springboot/wumei-iot/src/main/resources/mapper/iot/DeviceMapper.xml deleted file mode 100644 index 60e29dc7..00000000 --- a/springboot/wumei-iot/src/main/resources/mapper/iot/DeviceMapper.xml +++ /dev/null @@ -1,466 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - select device_id, device_name, product_id, product_name, user_id, user_name, tenant_id, tenant_name, serial_number, firmware_version, status, rssi,is_shadow ,location_way,things_model_value,network_address, network_ip, longitude, latitude, active_time, create_time, update_time, img_url,summary,remark from iot_device - - - - select device_id, device_name, product_id, product_name, user_id, user_name, tenant_id, tenant_name, serial_number, firmware_version, status,rssi,is_shadow ,location_way,things_model_value, active_time,img_url from iot_device - - - - select device_id, device_name,product_id, serial_number,user_id, user_name, tenant_id, tenant_name, status,is_shadow, rssi ,location_way,things_model_value, active_time from iot_device - - - - - - - - - - - - - - update iot_device set things_model_value=#{stringValue} where device_id = #{deviceId} - - - - - - - - - - - - - - - - - - - - insert into iot_device - - device_name, - product_id, - product_name, - user_id, - user_name, - tenant_id, - tenant_name, - serial_number, - firmware_version, - status, - rssi, - is_shadow, - location_way, - things_model_value, - network_address, - network_ip, - longitude, - latitude, - active_time, - del_flag, - create_by, - create_time, - update_by, - update_time, - remark, - img_url, - summary, - - - #{deviceName}, - #{productId}, - #{productName}, - #{userId}, - #{userName}, - #{tenantId}, - #{tenantName}, - #{serialNumber}, - #{firmwareVersion}, - #{status}, - #{rssi}, - #{isShadow}, - #{locationWay}, - #{thingsModelValue}, - #{networkAddress}, - #{networkIp}, - #{longitude}, - #{latitude}, - #{activeTime}, - #{delFlag}, - #{createBy}, - #{createTime}, - #{updateBy}, - #{updateTime}, - #{remark}, - #{imgUrl}, - #{summary}, - - - - - update iot_device - - device_name = #{deviceName}, - product_id = #{productId}, - product_name = #{productName}, - user_id = #{userId}, - user_name = #{userName}, - tenant_id = #{tenantId}, - tenant_name = #{tenantName}, - serial_number = #{serialNumber}, - firmware_version = #{firmwareVersion}, - status = #{status}, - rssi = #{rssi}, - is_shadow = #{isShadow}, - location_way = #{locationWay}, - things_model_value = #{thingsModelValue}, - network_address = #{networkAddress}, - network_ip = #{networkIp}, - longitude = #{longitude}, - latitude = #{latitude}, - active_time = #{activeTime}, - del_flag = #{delFlag}, - create_by = #{createBy}, - create_time = #{createTime}, - update_by = #{updateBy}, - update_time = #{updateTime}, - remark = #{remark}, - img_url = #{imgUrl}, - summary = #{summary}, - - where device_id = #{deviceId} - - - - update iot_device - - status = #{status}, - network_address = #{networkAddress}, - network_ip = #{networkIp}, - longitude = #{longitude}, - latitude = #{latitude}, - active_time = #{activeTime}, - - where serial_number = #{serialNumber} - - - - -- 设备状态(1-未激活,2-禁用,3-在线,4-离线) - update iot_device set status=4 - where serial_number = #{serialNumber} and status = 3 - - - - update iot_device - - device_name = #{deviceName}, - product_id = #{productId}, - product_name = #{productName}, - user_id = #{userId}, - user_name = #{userName}, - tenant_id = #{tenantId}, - tenant_name = #{tenantName}, - serial_number = #{serialNumber}, - firmware_version = #{firmwareVersion}, - status = #{status}, - rssi = #{rssi}, - is_shadow = #{isShadow}, - location_way = #{locationWay}, - things_model_value = #{thingsModelValue}, - network_address = #{networkAddress}, - network_ip = #{networkIp}, - longitude = #{longitude}, - latitude = #{latitude}, - active_time = #{activeTime}, - del_flag = #{delFlag}, - create_by = #{createBy}, - create_time = #{createTime}, - update_by = #{updateBy}, - update_time = #{updateTime}, - remark = #{remark}, - img_url = #{imgUrl}, - summary = #{summary}, - - where serial_number = #{serialNumber} - - - - delete from iot_device where device_id = #{deviceId} - - - - delete from iot_device where device_id in - - #{deviceId} - - - - - - - delete from iot_device_group - - and device_id = #{deviceId} - and group_id in(select group_id from iot_group where user_id = #{userId}) - - - \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/resources/mapper/iot/DeviceUserMapper.xml b/springboot/wumei-iot/src/main/resources/mapper/iot/DeviceUserMapper.xml deleted file mode 100644 index 33139f4c..00000000 --- a/springboot/wumei-iot/src/main/resources/mapper/iot/DeviceUserMapper.xml +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - - - - - - - - - - - - - select device_id, user_id, device_name, user_name, is_owner,tenant_id,tenant_name,phonenumber, create_time, update_time, remark from iot_device_user - - - - - - - - - - insert into iot_device_user - - device_id, - user_id, - device_name, - user_name, - is_owner, - tenant_id, - tenant_name, - phonenumber, - del_flag, - create_by, - create_time, - update_by, - update_time, - remark, - - - #{deviceId}, - #{userId}, - #{deviceName}, - #{userName}, - #{isOwner}, - #{tenantId}, - #{tenantName}, - #{phonenumber}, - #{delFlag}, - #{createBy}, - #{createTime}, - #{updateBy}, - #{updateTime}, - #{remark}, - - - - - insert into iot_device_user - (device_id, user_id, device_name, user_name, is_owner,tenant_id,tenant_name,phonenumber, create_time) values - - (#{item.deviceId},#{item.userId},#{item.deviceName}, #{item.userName}, #{item.isOwner}, #{item.tenantId},#{item.tenantName},#{item.phonenumber}, #{item.createTime}) - - - - - update iot_device_user - - user_id = #{userId}, - device_name = #{deviceName}, - user_name = #{userName}, - is_owner = #{isOwner}, - tenant_id = #{tenantId}, - tenant_name = #{tenantName}, - phonenumber = #{phonenumber}, - del_flag = #{delFlag}, - create_by = #{createBy}, - create_time = #{createTime}, - update_by = #{updateBy}, - update_time = #{updateTime}, - remark = #{remark}, - - where device_id = #{deviceId} and user_id = #{userId} - - - - delete from iot_device_user - - and device_id = #{deviceId} - and user_id = #{userId} - - - - - delete from iot_device_user where device_id in - - #{deviceId} - - - - delete from iot_device_user where device_id = #{deviceId} and is_owner !=1 and user_id = #{userId} - - \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/resources/mapper/iot/FirmwareMapper.xml b/springboot/wumei-iot/src/main/resources/mapper/iot/FirmwareMapper.xml deleted file mode 100644 index 5cfa1920..00000000 --- a/springboot/wumei-iot/src/main/resources/mapper/iot/FirmwareMapper.xml +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - select firmware_id, firmware_name, product_id, product_name, tenant_id, tenant_name, is_sys,is_latest, version, file_path, create_time, update_time, remark from iot_firmware - - - - - - - - - - insert into iot_firmware - - firmware_name, - product_id, - product_name, - tenant_id, - tenant_name, - is_sys, - is_latest, - version, - file_path, - del_flag, - create_by, - create_time, - update_by, - update_time, - remark, - - - #{firmwareName}, - #{productId}, - #{productName}, - #{tenantId}, - #{tenantName}, - #{isSys}, - #{isLatest}, - #{version}, - #{filePath}, - #{delFlag}, - #{createBy}, - #{createTime}, - #{updateBy}, - #{updateTime}, - #{remark}, - - - - - update iot_firmware - - firmware_name = #{firmwareName}, - product_id = #{productId}, - product_name = #{productName}, - tenant_id = #{tenantId}, - tenant_name = #{tenantName}, - is_sys = #{isSys}, - is_latest = #{isLatest}, - version = #{version}, - file_path = #{filePath}, - del_flag = #{delFlag}, - create_by = #{createBy}, - create_time = #{createTime}, - update_by = #{updateBy}, - update_time = #{updateTime}, - remark = #{remark}, - - where firmware_id = #{firmwareId} - - - - delete from iot_firmware where firmware_id = #{firmwareId} - - - - delete from iot_firmware where firmware_id in - - #{firmwareId} - - - \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/resources/mapper/iot/GroupMapper.xml b/springboot/wumei-iot/src/main/resources/mapper/iot/GroupMapper.xml deleted file mode 100644 index 81acc264..00000000 --- a/springboot/wumei-iot/src/main/resources/mapper/iot/GroupMapper.xml +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - select group_id, group_name, group_order, user_id, user_name, create_time, update_time, remark from iot_group - - - - - - - - - - insert into iot_group - - group_name, - group_order, - user_id, - user_name, - del_flag, - create_by, - create_time, - update_by, - update_time, - remark, - - - #{groupName}, - #{groupOrder}, - #{userId}, - #{userName}, - #{delFlag}, - #{createBy}, - #{createTime}, - #{updateBy}, - #{updateTime}, - #{remark}, - - - - - insert into iot_device_group (device_id,group_id) - values - - - #{deviceId},#{groupId}, - - - - - - update iot_group - - group_name = #{groupName}, - group_order = #{groupOrder}, - user_id = #{userId}, - user_name = #{userName}, - del_flag = #{delFlag}, - create_by = #{createBy}, - create_time = #{createTime}, - update_by = #{updateBy}, - update_time = #{updateTime}, - remark = #{remark}, - - where group_id = #{groupId} - - - - delete from iot_group where group_id = #{groupId} - - - - delete from iot_group where group_id in - - #{groupId} - - - - - delete from iot_device_group where group_id in - - #{groupId} - - - \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/resources/mapper/iot/NewsCategoryMapper.xml b/springboot/wumei-iot/src/main/resources/mapper/iot/NewsCategoryMapper.xml deleted file mode 100644 index 04f84724..00000000 --- a/springboot/wumei-iot/src/main/resources/mapper/iot/NewsCategoryMapper.xml +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - select category_id, category_name, order_num, del_flag, create_by, create_time, update_by, update_time, remark from news_category - - - - - - - - - - insert into news_category - - category_name, - order_num, - del_flag, - create_by, - create_time, - update_by, - update_time, - remark, - - - #{categoryName}, - #{orderNum}, - #{delFlag}, - #{createBy}, - #{createTime}, - #{updateBy}, - #{updateTime}, - #{remark}, - - - - - update news_category - - category_name = #{categoryName}, - order_num = #{orderNum}, - del_flag = #{delFlag}, - create_by = #{createBy}, - create_time = #{createTime}, - update_by = #{updateBy}, - update_time = #{updateTime}, - remark = #{remark}, - - where category_id = #{categoryId} - - - - delete from news_category where category_id = #{categoryId} - - - - delete from news_category where category_id in - - #{categoryId} - - - - - \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/resources/mapper/iot/NewsMapper.xml b/springboot/wumei-iot/src/main/resources/mapper/iot/NewsMapper.xml deleted file mode 100644 index 0871286e..00000000 --- a/springboot/wumei-iot/src/main/resources/mapper/iot/NewsMapper.xml +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - select news_id, title, img_url, is_top, is_banner, category_id, category_name, status, author, del_flag, create_by, create_time, update_by, update_time, remark from news - - - - - - - - - - insert into news - - title, - content, - img_url, - is_top, - is_banner, - category_id, - category_name, - status, - author, - del_flag, - create_by, - create_time, - update_by, - update_time, - remark, - - - #{title}, - #{content}, - #{imgUrl}, - #{isTop}, - #{isBanner}, - #{categoryId}, - #{categoryName}, - #{status}, - #{author}, - #{delFlag}, - #{createBy}, - #{createTime}, - #{updateBy}, - #{updateTime}, - #{remark}, - - - - - update news - - title = #{title}, - content = #{content}, - img_url = #{imgUrl}, - is_top = #{isTop}, - is_banner = #{isBanner}, - category_id = #{categoryId}, - category_name = #{categoryName}, - status = #{status}, - author = #{author}, - del_flag = #{delFlag}, - create_by = #{createBy}, - create_time = #{createTime}, - update_by = #{updateBy}, - update_time = #{updateTime}, - remark = #{remark}, - - where news_id = #{newsId} - - - - delete from news where news_id = #{newsId} - - - - delete from news where news_id in - - #{newsId} - - - \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/resources/mapper/iot/OauthClientDetailsMapper.xml b/springboot/wumei-iot/src/main/resources/mapper/iot/OauthClientDetailsMapper.xml deleted file mode 100644 index b9269d6f..00000000 --- a/springboot/wumei-iot/src/main/resources/mapper/iot/OauthClientDetailsMapper.xml +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - select client_id, resource_ids, client_secret, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove, type from oauth_client_details - - - - - - - - insert into oauth_client_details - - client_id, - resource_ids, - client_secret, - scope, - authorized_grant_types, - web_server_redirect_uri, - authorities, - access_token_validity, - refresh_token_validity, - additional_information, - autoapprove, - type, - - - #{clientId}, - #{resourceIds}, - #{clientSecret}, - #{scope}, - #{authorizedGrantTypes}, - #{webServerRedirectUri}, - #{authorities}, - #{accessTokenValidity}, - #{refreshTokenValidity}, - #{additionalInformation}, - #{autoapprove}, - #{type}, - - - - - update oauth_client_details - - resource_ids = #{resourceIds}, - client_secret = #{clientSecret}, - scope = #{scope}, - authorized_grant_types = #{authorizedGrantTypes}, - web_server_redirect_uri = #{webServerRedirectUri}, - authorities = #{authorities}, - access_token_validity = #{accessTokenValidity}, - refresh_token_validity = #{refreshTokenValidity}, - additional_information = #{additionalInformation}, - autoapprove = #{autoapprove}, - type = #{type}, - - where client_id = #{clientId} - - - - delete from oauth_client_details where client_id = #{clientId} - - - - delete from oauth_client_details where client_id in - - #{clientId} - - - \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/resources/mapper/iot/ProductAuthorizeMapper.xml b/springboot/wumei-iot/src/main/resources/mapper/iot/ProductAuthorizeMapper.xml deleted file mode 100644 index 6082c616..00000000 --- a/springboot/wumei-iot/src/main/resources/mapper/iot/ProductAuthorizeMapper.xml +++ /dev/null @@ -1,135 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - select authorize_id, authorize_code, product_id, device_id, serial_number, user_id, user_name,status, del_flag, create_by, create_time, update_by, update_time, remark from iot_product_authorize - - - - - - - - - - insert into iot_product_authorize - - authorize_code, - product_id, - device_id, - serial_number, - user_id, - user_name, - status, - create_by, - create_time, - update_by, - update_time, - remark, - - - #{authorizeCode}, - #{productId}, - #{deviceId}, - #{serialNumber}, - #{userId}, - #{userName}, - #{status}, - #{createBy}, - #{createTime}, - #{updateBy}, - #{updateTime}, - #{remark}, - - - - - insert into iot_product_authorize (authorize_code,product_id,create_by,create_time,status) - values - - - #{item.authorizeCode},#{item.productId},#{item.createBy},#{item.createTime},#{item.status} - - - - - - update iot_product_authorize - - user_id = #{userId}, - device_id = #{deviceId}, - authorize_code = #{authorizeCode}, - product_id = #{productId}, - serial_number = #{serialNumber}, - user_name = #{userName}, - status = #{status}, - del_flag = #{delFlag}, - create_by = #{createBy}, - create_time = #{createTime}, - update_by = #{updateBy}, - update_time = #{updateTime}, - remark = #{remark}, - - where authorize_id = #{authorizeId} - - - - delete from iot_product_authorize where authorize_id = #{authorizeId} - - - - delete from iot_product_authorize where authorize_id in - - #{authorizeId} - - - - - delete from iot_product_authorize where product_id in - - #{productId} - - - \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/resources/mapper/iot/ProductMapper.xml b/springboot/wumei-iot/src/main/resources/mapper/iot/ProductMapper.xml deleted file mode 100644 index 5dd0ea25..00000000 --- a/springboot/wumei-iot/src/main/resources/mapper/iot/ProductMapper.xml +++ /dev/null @@ -1,199 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - select product_id, product_name, category_id, category_name, tenant_id, tenant_name, is_sys, is_authorize, mqtt_account,mqtt_password,mqtt_secret ,status, device_type, network_method, vertificate_method, create_time, update_time, img_url,remark from iot_product - - - - - - - - - - insert into iot_product - - product_name, - category_id, - category_name, - tenant_id, - tenant_name, - is_sys, - is_authorize, - mqtt_account, - mqtt_password, - mqtt_secret, - status, - device_type, - network_method, - vertificate_method, - del_flag, - create_by, - create_time, - update_by, - update_time, - remark, - img_url, - - - #{productName}, - #{categoryId}, - #{categoryName}, - #{tenantId}, - #{tenantName}, - #{isSys}, - #{isAuthorize}, - #{mqttAccount}, - #{mqttPassword}, - #{mqttSecret}, - #{status}, - #{deviceType}, - #{networkMethod}, - #{vertificateMethod}, - #{delFlag}, - #{createBy}, - #{createTime}, - #{updateBy}, - #{updateTime}, - #{remark}, - #{imgUrl}, - - - - - update iot_product - - product_name = #{productName}, - category_id = #{categoryId}, - category_name = #{categoryName}, - tenant_id = #{tenantId}, - tenant_name = #{tenantName}, - is_sys = #{isSys}, - is_authorize = #{isAuthorize}, - mqtt_account = #{mqttAccount}, - mqtt_password = #{mqttPassword}, - mqtt_secret = #{mqttSecret}, - status = #{status}, - device_type = #{deviceType}, - network_method = #{networkMethod}, - vertificate_method = #{vertificateMethod}, - del_flag = #{delFlag}, - create_by = #{createBy}, - create_time = #{createTime}, - update_by = #{updateBy}, - update_time = #{updateTime}, - remark = #{remark}, - img_url = #{imgUrl}, - - where product_id = #{productId} - - - - update iot_product set status=#{status} - where product_id = #{productId} - - - - update iot_product set things_models_json=#{thingsModelsJson} - where product_id = #{productId} - - - - delete from iot_product where product_id = #{productId} - - - - delete from iot_product where product_id in - - #{productId} - - - - - delete from iot_things_model where product_id in - - #{productId} - - - - - - - - - - - \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/resources/mapper/iot/SceneMapper.xml b/springboot/wumei-iot/src/main/resources/mapper/iot/SceneMapper.xml deleted file mode 100644 index 91eea12e..00000000 --- a/springboot/wumei-iot/src/main/resources/mapper/iot/SceneMapper.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - - - - - - - - - - - - - - select scene_id, scene_name, user_id, user_name, triggers, actions, create_by, create_time, update_by, update_time, remark from iot_scene - - - - - - - - insert into iot_scene - - scene_name, - user_id, - user_name, - triggers, - actions, - create_by, - create_time, - update_by, - update_time, - remark, - - - #{sceneName}, - #{userId}, - #{userName}, - #{triggers}, - #{actions}, - #{createBy}, - #{createTime}, - #{updateBy}, - #{updateTime}, - #{remark}, - - - - - update iot_scene - - scene_name = #{sceneName}, - user_id = #{userId}, - user_name = #{userName}, - triggers = #{triggers}, - actions = #{actions}, - create_by = #{createBy}, - create_time = #{createTime}, - update_by = #{updateBy}, - update_time = #{updateTime}, - remark = #{remark}, - - where scene_id = #{sceneId} - - - - delete from iot_scene where scene_id = #{sceneId} - - - - delete from iot_scene where scene_id in - - #{sceneId} - - - \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/resources/mapper/iot/SocialPlatformMapper.xml b/springboot/wumei-iot/src/main/resources/mapper/iot/SocialPlatformMapper.xml deleted file mode 100644 index 86ebcfea..00000000 --- a/springboot/wumei-iot/src/main/resources/mapper/iot/SocialPlatformMapper.xml +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - select social_platform_id, - platform, - status, - client_id, - secret_key, - redirect_uri, - del_flag, - create_by, - create_time, - update_time, - update_by, - remark, - bind_uri, - redirect_login_uri, - error_msg_uri - from iot_social_platform - - - - - - - - - - insert into iot_social_platform - - platform, - status, - client_id, - secret_key, - redirect_uri, - del_flag, - create_by, - create_time, - update_time, - update_by, - remark, - bind_uri, - redirect_login_uri, - error_msg_uri, - - - #{platform}, - #{status}, - #{clientId}, - #{secretKey}, - #{redirectUri}, - #{delFlag}, - #{createBy}, - #{createTime}, - #{updateTime}, - #{updateBy}, - #{remark}, - #{bindUri}, - #{redirectLoginUri}, - #{errorMsgUri}, - - - - - update iot_social_platform - - platform = #{platform}, - status = #{status}, - client_id = #{clientId}, - secret_key = #{secretKey}, - redirect_uri = #{redirectUri}, - del_flag = #{delFlag}, - create_by = #{createBy}, - create_time = #{createTime}, - update_time = #{updateTime}, - update_by = #{updateBy}, - remark = #{remark}, - bind_uri = #{bindUri}, - redirect_login_uri = #{redirectLoginUri}, - - error_msg_uri = #{errorMsgUri}, - - where social_platform_id = #{socialPlatformId} - - - - delete - from iot_social_platform - where social_platform_id = #{socialPlatformId} - - - - delete from iot_social_platform where social_platform_id in - - #{socialPlatformId} - - - \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/resources/mapper/iot/SocialUserMapper.xml b/springboot/wumei-iot/src/main/resources/mapper/iot/SocialUserMapper.xml deleted file mode 100644 index bc1e1368..00000000 --- a/springboot/wumei-iot/src/main/resources/mapper/iot/SocialUserMapper.xml +++ /dev/null @@ -1,219 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - select social_user_id, - uuid, - source, - access_token, - expire_in, - refresh_token, - open_id, - uid, - access_code, - union_id, - scope, - token_type, - id_token, - mac_algorithm, - mac_key, - code, - oauth_token, - oauth_token_secret, - create_time, - create_by, - update_time, - update_by, - del_flag, - status, - sys_user_id, - username, - nickname, - avatar, - gender - from iot_social_user - - - - - - - - insert into iot_social_user - - uuid, - source, - access_token, - expire_in, - refresh_token, - open_id, - uid, - access_code, - union_id, - scope, - token_type, - id_token, - mac_algorithm, - mac_key, - code, - oauth_token, - oauth_token_secret, - create_time, - create_by, - update_time, - update_by, - del_flag, - status, - sys_user_id, - username, - nickname, - avatar, - gender, - - - #{uuid}, - #{source}, - #{accessToken}, - #{expireIn}, - #{refreshToken}, - #{openId}, - #{uid}, - #{accessCode}, - #{unionId}, - #{scope}, - #{tokenType}, - #{idToken}, - #{macAlgorithm}, - #{macKey}, - #{code}, - #{oauthToken}, - #{oauthTokenSecret}, - #{createTime}, - #{createBy}, - #{updateTime}, - #{updateBy}, - #{delFlag}, - #{status}, - #{sysUserId}, - #{username}, - #{nickname}, - #{avatar}, - #{gender}, - - - - - update iot_social_user - - uuid = #{uuid}, - source = #{source}, - access_token = #{accessToken}, - expire_in = #{expireIn}, - refresh_token = #{refreshToken}, - open_id = #{openId}, - uid = #{uid}, - access_code = #{accessCode}, - union_id = #{unionId}, - scope = #{scope}, - token_type = #{tokenType}, - id_token = #{idToken}, - mac_algorithm = #{macAlgorithm}, - mac_key = #{macKey}, - code = #{code}, - oauth_token = #{oauthToken}, - oauth_token_secret = #{oauthTokenSecret}, - create_time = #{createTime}, - create_by = #{createBy}, - update_time = #{updateTime}, - update_by = #{updateBy}, - del_flag = #{delFlag}, - status = #{status}, - sys_user_id = #{sysUserId}, - username = #{username}, - nickname = #{nickname}, - avatar = #{avatar}, - gender = #{gender}, - - where social_user_id = #{socialUserId} - - - - delete - from iot_social_user - where social_user_id = #{socialUserId} - - - - delete from iot_social_user where social_user_id in - - #{socialUserId} - - - \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/resources/mapper/iot/ThingsModelMapper.xml b/springboot/wumei-iot/src/main/resources/mapper/iot/ThingsModelMapper.xml deleted file mode 100644 index 29522c51..00000000 --- a/springboot/wumei-iot/src/main/resources/mapper/iot/ThingsModelMapper.xml +++ /dev/null @@ -1,133 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - select model_id, model_name, product_id, product_name, tenant_id, tenant_name, identifier, type, datatype, specs, is_Top, is_Monitor from iot_things_model - - - - - - - - - - insert into iot_things_model - - model_name, - product_id, - product_name, - tenant_id, - tenant_name, - identifier, - type, - datatype, - specs, - is_Top, - is_Monitor, - create_by, - create_time, - update_by, - update_time, - remark, - - - #{modelName}, - #{productId}, - #{productName}, - #{tenantId}, - #{tenantName}, - #{identifier}, - #{type}, - #{datatype}, - #{specs}, - #{isTop}, - #{isMonitor}, - #{createBy}, - #{createTime}, - #{updateBy}, - #{updateTime}, - #{remark}, - - - - - insert into iot_things_model (model_name,product_id,product_name,tenant_id,tenant_name,identifier,type,datatype,specs,is_Top,is_Monitor,create_by,create_time) - values - - - #{model.modelName},#{model.productId},#{model.productName},#{model.tenantId},#{model.tenantName},#{model.identifier},#{model.type},#{model.datatype},#{model.specs},#{model.isTop},#{model.isMonitor},#{model.createBy},#{model.createTime}, - - - - - - update iot_things_model - - model_name = #{modelName}, - product_id = #{productId}, - product_name = #{productName}, - tenant_id = #{tenantId}, - tenant_name = #{tenantName}, - identifier = #{identifier}, - type = #{type}, - datatype = #{datatype}, - specs = #{specs}, - is_Top = #{isTop}, - is_Monitor = #{isMonitor}, - create_by = #{createBy}, - create_time = #{createTime}, - update_by = #{updateBy}, - update_time = #{updateTime}, - remark = #{remark}, - - where model_id = #{modelId} - - - - delete from iot_things_model where model_id = #{modelId} - - - - delete from iot_things_model where model_id in - - #{modelId} - - - \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/resources/mapper/iot/ThingsModelTemplateMapper.xml b/springboot/wumei-iot/src/main/resources/mapper/iot/ThingsModelTemplateMapper.xml deleted file mode 100644 index b19444c6..00000000 --- a/springboot/wumei-iot/src/main/resources/mapper/iot/ThingsModelTemplateMapper.xml +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - select template_id, template_name, tenant_id, tenant_name, identifier, type, datatype, specs, is_sys, is_Top, is_Monitor, create_time, update_time, remark from iot_things_model_template - - - - - - - - - - insert into iot_things_model_template - - template_name, - tenant_id, - tenant_name, - identifier, - type, - datatype, - specs, - is_sys, - is_Top, - is_Monitor, - del_flag, - create_by, - create_time, - update_by, - update_time, - remark, - - - #{templateName}, - #{tenantId}, - #{tenantName}, - #{identifier}, - #{type}, - #{datatype}, - #{specs}, - #{isSys}, - #{isTop}, - #{isMonitor}, - #{delFlag}, - #{createBy}, - #{createTime}, - #{updateBy}, - #{updateTime}, - #{remark}, - - - - - update iot_things_model_template - - template_name = #{templateName}, - tenant_id = #{tenantId}, - tenant_name = #{tenantName}, - identifier = #{identifier}, - type = #{type}, - datatype = #{datatype}, - specs = #{specs}, - is_sys = #{isSys}, - is_Top = #{isTop}, - is_Monitor = #{isMonitor}, - del_flag = #{delFlag}, - create_by = #{createBy}, - create_time = #{createTime}, - update_by = #{updateBy}, - update_time = #{updateTime}, - remark = #{remark}, - - where template_id = #{templateId} - - - - delete from iot_things_model_template where template_id = #{templateId} - - - - delete from iot_things_model_template where template_id in - - #{templateId} - - - \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/resources/mapper/tdengine/TDDeviceLogMapper.xml b/springboot/wumei-iot/src/main/resources/mapper/tdengine/TDDeviceLogMapper.xml deleted file mode 100644 index 8758a997..00000000 --- a/springboot/wumei-iot/src/main/resources/mapper/tdengine/TDDeviceLogMapper.xml +++ /dev/null @@ -1,139 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - create database if not exists ${database}; - - - - create STABLE if not exists ${database}.device_log - (ts timestamp, - `log_value` BINARY(100), - is_monitor TINYINT, - log_type TINYINT, - `identity` BINARY(100), - mode TINYINT, - remark BINARY(500)) - - TAGS( - device_id BIGINT, - serial_number BINARY(50), - user_id BIGINT, - tenant_Id BIGINT, - user_name BINARY(100), - tenant_name BINARY(100), - device_name BINARY(100)); - - - - INSERT INTO ${database}.device_${device.serialNumber} USING device_log - TAGS (#{device.deviceId}, - #{device.serialNumber}, - #{device.userId}, - #{device.tenantId}, - #{device.userName}, - #{device.tenantName}, - #{device.deviceName}) - VALUES (now, - #{device.logValue}, - #{device.isMonitor}, - #{device.logType}, - #{device.identity}, - #{device.mode}, - #{device.remark}); - - - - DROP TABLE IF EXISTS ${database}.device_${serialNumber}; - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/resources/static/oauth/css/bootstrap-theme.css b/springboot/wumei-iot/src/main/resources/static/oauth/css/bootstrap-theme.css deleted file mode 100644 index ea33f76a..00000000 --- a/springboot/wumei-iot/src/main/resources/static/oauth/css/bootstrap-theme.css +++ /dev/null @@ -1,587 +0,0 @@ -/*! - * Bootstrap v3.4.1 (https://getbootstrap.com/) - * Copyright 2011-2019 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ -.btn-default, -.btn-primary, -.btn-success, -.btn-info, -.btn-warning, -.btn-danger { - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); -} -.btn-default:active, -.btn-primary:active, -.btn-success:active, -.btn-info:active, -.btn-warning:active, -.btn-danger:active, -.btn-default.active, -.btn-primary.active, -.btn-success.active, -.btn-info.active, -.btn-warning.active, -.btn-danger.active { - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); -} -.btn-default.disabled, -.btn-primary.disabled, -.btn-success.disabled, -.btn-info.disabled, -.btn-warning.disabled, -.btn-danger.disabled, -.btn-default[disabled], -.btn-primary[disabled], -.btn-success[disabled], -.btn-info[disabled], -.btn-warning[disabled], -.btn-danger[disabled], -fieldset[disabled] .btn-default, -fieldset[disabled] .btn-primary, -fieldset[disabled] .btn-success, -fieldset[disabled] .btn-info, -fieldset[disabled] .btn-warning, -fieldset[disabled] .btn-danger { - -webkit-box-shadow: none; - box-shadow: none; -} -.btn-default .badge, -.btn-primary .badge, -.btn-success .badge, -.btn-info .badge, -.btn-warning .badge, -.btn-danger .badge { - text-shadow: none; -} -.btn:active, -.btn.active { - background-image: none; -} -.btn-default { - background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); - background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0)); - background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-color: #dbdbdb; - text-shadow: 0 1px 0 #fff; - border-color: #ccc; -} -.btn-default:hover, -.btn-default:focus { - background-color: #e0e0e0; - background-position: 0 -15px; -} -.btn-default:active, -.btn-default.active { - background-color: #e0e0e0; - border-color: #dbdbdb; -} -.btn-default.disabled, -.btn-default[disabled], -fieldset[disabled] .btn-default, -.btn-default.disabled:hover, -.btn-default[disabled]:hover, -fieldset[disabled] .btn-default:hover, -.btn-default.disabled:focus, -.btn-default[disabled]:focus, -fieldset[disabled] .btn-default:focus, -.btn-default.disabled.focus, -.btn-default[disabled].focus, -fieldset[disabled] .btn-default.focus, -.btn-default.disabled:active, -.btn-default[disabled]:active, -fieldset[disabled] .btn-default:active, -.btn-default.disabled.active, -.btn-default[disabled].active, -fieldset[disabled] .btn-default.active { - background-color: #e0e0e0; - background-image: none; -} -.btn-primary { - background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%); - background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88)); - background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-color: #245580; -} -.btn-primary:hover, -.btn-primary:focus { - background-color: #265a88; - background-position: 0 -15px; -} -.btn-primary:active, -.btn-primary.active { - background-color: #265a88; - border-color: #245580; -} -.btn-primary.disabled, -.btn-primary[disabled], -fieldset[disabled] .btn-primary, -.btn-primary.disabled:hover, -.btn-primary[disabled]:hover, -fieldset[disabled] .btn-primary:hover, -.btn-primary.disabled:focus, -.btn-primary[disabled]:focus, -fieldset[disabled] .btn-primary:focus, -.btn-primary.disabled.focus, -.btn-primary[disabled].focus, -fieldset[disabled] .btn-primary.focus, -.btn-primary.disabled:active, -.btn-primary[disabled]:active, -fieldset[disabled] .btn-primary:active, -.btn-primary.disabled.active, -.btn-primary[disabled].active, -fieldset[disabled] .btn-primary.active { - background-color: #265a88; - background-image: none; -} -.btn-success { - background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); - background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641)); - background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-color: #3e8f3e; -} -.btn-success:hover, -.btn-success:focus { - background-color: #419641; - background-position: 0 -15px; -} -.btn-success:active, -.btn-success.active { - background-color: #419641; - border-color: #3e8f3e; -} -.btn-success.disabled, -.btn-success[disabled], -fieldset[disabled] .btn-success, -.btn-success.disabled:hover, -.btn-success[disabled]:hover, -fieldset[disabled] .btn-success:hover, -.btn-success.disabled:focus, -.btn-success[disabled]:focus, -fieldset[disabled] .btn-success:focus, -.btn-success.disabled.focus, -.btn-success[disabled].focus, -fieldset[disabled] .btn-success.focus, -.btn-success.disabled:active, -.btn-success[disabled]:active, -fieldset[disabled] .btn-success:active, -.btn-success.disabled.active, -.btn-success[disabled].active, -fieldset[disabled] .btn-success.active { - background-color: #419641; - background-image: none; -} -.btn-info { - background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); - background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2)); - background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-color: #28a4c9; -} -.btn-info:hover, -.btn-info:focus { - background-color: #2aabd2; - background-position: 0 -15px; -} -.btn-info:active, -.btn-info.active { - background-color: #2aabd2; - border-color: #28a4c9; -} -.btn-info.disabled, -.btn-info[disabled], -fieldset[disabled] .btn-info, -.btn-info.disabled:hover, -.btn-info[disabled]:hover, -fieldset[disabled] .btn-info:hover, -.btn-info.disabled:focus, -.btn-info[disabled]:focus, -fieldset[disabled] .btn-info:focus, -.btn-info.disabled.focus, -.btn-info[disabled].focus, -fieldset[disabled] .btn-info.focus, -.btn-info.disabled:active, -.btn-info[disabled]:active, -fieldset[disabled] .btn-info:active, -.btn-info.disabled.active, -.btn-info[disabled].active, -fieldset[disabled] .btn-info.active { - background-color: #2aabd2; - background-image: none; -} -.btn-warning { - background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); - background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316)); - background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-color: #e38d13; -} -.btn-warning:hover, -.btn-warning:focus { - background-color: #eb9316; - background-position: 0 -15px; -} -.btn-warning:active, -.btn-warning.active { - background-color: #eb9316; - border-color: #e38d13; -} -.btn-warning.disabled, -.btn-warning[disabled], -fieldset[disabled] .btn-warning, -.btn-warning.disabled:hover, -.btn-warning[disabled]:hover, -fieldset[disabled] .btn-warning:hover, -.btn-warning.disabled:focus, -.btn-warning[disabled]:focus, -fieldset[disabled] .btn-warning:focus, -.btn-warning.disabled.focus, -.btn-warning[disabled].focus, -fieldset[disabled] .btn-warning.focus, -.btn-warning.disabled:active, -.btn-warning[disabled]:active, -fieldset[disabled] .btn-warning:active, -.btn-warning.disabled.active, -.btn-warning[disabled].active, -fieldset[disabled] .btn-warning.active { - background-color: #eb9316; - background-image: none; -} -.btn-danger { - background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); - background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a)); - background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-color: #b92c28; -} -.btn-danger:hover, -.btn-danger:focus { - background-color: #c12e2a; - background-position: 0 -15px; -} -.btn-danger:active, -.btn-danger.active { - background-color: #c12e2a; - border-color: #b92c28; -} -.btn-danger.disabled, -.btn-danger[disabled], -fieldset[disabled] .btn-danger, -.btn-danger.disabled:hover, -.btn-danger[disabled]:hover, -fieldset[disabled] .btn-danger:hover, -.btn-danger.disabled:focus, -.btn-danger[disabled]:focus, -fieldset[disabled] .btn-danger:focus, -.btn-danger.disabled.focus, -.btn-danger[disabled].focus, -fieldset[disabled] .btn-danger.focus, -.btn-danger.disabled:active, -.btn-danger[disabled]:active, -fieldset[disabled] .btn-danger:active, -.btn-danger.disabled.active, -.btn-danger[disabled].active, -fieldset[disabled] .btn-danger.active { - background-color: #c12e2a; - background-image: none; -} -.thumbnail, -.img-thumbnail { - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); -} -.dropdown-menu > li > a:hover, -.dropdown-menu > li > a:focus { - background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); - background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); - background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); - background-repeat: repeat-x; - background-color: #e8e8e8; -} -.dropdown-menu > .active > a, -.dropdown-menu > .active > a:hover, -.dropdown-menu > .active > a:focus { - background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); - background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); - background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); - background-repeat: repeat-x; - background-color: #2e6da4; -} -.navbar-default { - background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%); - background-image: -o-linear-gradient(top, #ffffff 0%, #f8f8f8 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#f8f8f8)); - background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075); -} -.navbar-default .navbar-nav > .open > a, -.navbar-default .navbar-nav > .active > a { - background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); - background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2)); - background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0); - background-repeat: repeat-x; - -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075); -} -.navbar-brand, -.navbar-nav > li > a { - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25); -} -.navbar-inverse { - background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%); - background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222)); - background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - border-radius: 4px; -} -.navbar-inverse .navbar-nav > .open > a, -.navbar-inverse .navbar-nav > .active > a { - background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%); - background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f)); - background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0); - background-repeat: repeat-x; - -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25); - box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25); -} -.navbar-inverse .navbar-brand, -.navbar-inverse .navbar-nav > li > a { - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); -} -.navbar-static-top, -.navbar-fixed-top, -.navbar-fixed-bottom { - border-radius: 0; -} -@media (max-width: 767px) { - .navbar .navbar-nav .open .dropdown-menu > .active > a, - .navbar .navbar-nav .open .dropdown-menu > .active > a:hover, - .navbar .navbar-nav .open .dropdown-menu > .active > a:focus { - color: #fff; - background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); - background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); - background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); - background-repeat: repeat-x; - } -} -.alert { - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2); - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); -} -.alert-success { - background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); - background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc)); - background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); - background-repeat: repeat-x; - border-color: #b2dba1; -} -.alert-info { - background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); - background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0)); - background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); - background-repeat: repeat-x; - border-color: #9acfea; -} -.alert-warning { - background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); - background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0)); - background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); - background-repeat: repeat-x; - border-color: #f5e79e; -} -.alert-danger { - background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); - background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3)); - background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); - background-repeat: repeat-x; - border-color: #dca7a7; -} -.progress { - background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); - background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5)); - background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); - background-repeat: repeat-x; -} -.progress-bar { - background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%); - background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090)); - background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0); - background-repeat: repeat-x; -} -.progress-bar-success { - background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); - background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44)); - background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); - background-repeat: repeat-x; -} -.progress-bar-info { - background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); - background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5)); - background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); - background-repeat: repeat-x; -} -.progress-bar-warning { - background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); - background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f)); - background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); - background-repeat: repeat-x; -} -.progress-bar-danger { - background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); - background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c)); - background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); - background-repeat: repeat-x; -} -.progress-bar-striped { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} -.list-group { - border-radius: 4px; - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); -} -.list-group-item.active, -.list-group-item.active:hover, -.list-group-item.active:focus { - text-shadow: 0 -1px 0 #286090; - background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%); - background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a)); - background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0); - background-repeat: repeat-x; - border-color: #2b669a; -} -.list-group-item.active .badge, -.list-group-item.active:hover .badge, -.list-group-item.active:focus .badge { - text-shadow: none; -} -.panel { - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); -} -.panel-default > .panel-heading { - background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); - background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); - background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); - background-repeat: repeat-x; -} -.panel-primary > .panel-heading { - background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); - background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); - background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); - background-repeat: repeat-x; -} -.panel-success > .panel-heading { - background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); - background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6)); - background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); - background-repeat: repeat-x; -} -.panel-info > .panel-heading { - background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); - background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3)); - background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); - background-repeat: repeat-x; -} -.panel-warning > .panel-heading { - background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); - background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc)); - background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); - background-repeat: repeat-x; -} -.panel-danger > .panel-heading { - background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); - background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc)); - background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); - background-repeat: repeat-x; -} -.well { - background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); - background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5)); - background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); - background-repeat: repeat-x; - border-color: #dcdcdc; - -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1); - box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1); -} -/*# sourceMappingURL=bootstrap-theme.css.map */ \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/resources/static/oauth/css/bootstrap-theme.css.map b/springboot/wumei-iot/src/main/resources/static/oauth/css/bootstrap-theme.css.map deleted file mode 100644 index 949d0973..00000000 --- a/springboot/wumei-iot/src/main/resources/static/oauth/css/bootstrap-theme.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["bootstrap-theme.css","less/theme.less","less/mixins/vendor-prefixes.less","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":"AAAA;;;;GAIG;ACiBH;;;;;;EAME,yCAAA;EC2CA,4FAAA;EACQ,oFAAA;CFzDT;ACkBC;;;;;;;;;;;;ECsCA,yDAAA;EACQ,iDAAA;CF1CT;ACQC;;;;;;;;;;;;;;;;;;ECiCA,yBAAA;EACQ,iBAAA;CFrBT;AC7BD;;;;;;EAuBI,kBAAA;CDcH;AC2BC;;EAEE,uBAAA;CDzBH;AC8BD;EEvEI,sEAAA;EACA,iEAAA;EACA,2FAAA;EAAA,oEAAA;EACA,uHAAA;EClBF,oEAAA;EH8CA,4BAAA;EACA,sBAAA;EAyCA,0BAAA;EACA,mBAAA;CDtBD;AClBC;;EAEE,0BAAA;EACA,6BAAA;CDoBH;ACjBC;;EAEE,0BAAA;EACA,sBAAA;CDmBH;ACbG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CD2BL;ACPD;EE5EI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EClBF,oEAAA;EH8CA,4BAAA;EACA,sBAAA;CD4DD;AC1DC;;EAEE,0BAAA;EACA,6BAAA;CD4DH;ACzDC;;EAEE,0BAAA;EACA,sBAAA;CD2DH;ACrDG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CDmEL;AC9CD;EE7EI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EClBF,oEAAA;EH8CA,4BAAA;EACA,sBAAA;CDoGD;AClGC;;EAEE,0BAAA;EACA,6BAAA;CDoGH;ACjGC;;EAEE,0BAAA;EACA,sBAAA;CDmGH;AC7FG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CD2GL;ACrFD;EE9EI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EClBF,oEAAA;EH8CA,4BAAA;EACA,sBAAA;CD4ID;AC1IC;;EAEE,0BAAA;EACA,6BAAA;CD4IH;ACzIC;;EAEE,0BAAA;EACA,sBAAA;CD2IH;ACrIG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CDmJL;AC5HD;EE/EI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EClBF,oEAAA;EH8CA,4BAAA;EACA,sBAAA;CDoLD;AClLC;;EAEE,0BAAA;EACA,6BAAA;CDoLH;ACjLC;;EAEE,0BAAA;EACA,sBAAA;CDmLH;AC7KG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CD2LL;ACnKD;EEhFI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EClBF,oEAAA;EH8CA,4BAAA;EACA,sBAAA;CD4ND;AC1NC;;EAEE,0BAAA;EACA,6BAAA;CD4NH;ACzNC;;EAEE,0BAAA;EACA,sBAAA;CD2NH;ACrNG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CDmOL;ACpMD;;ECtCE,mDAAA;EACQ,2CAAA;CF8OT;AC/LD;;EEjGI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EACA,4BAAA;EFgGF,0BAAA;CDqMD;ACnMD;;;EEtGI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EACA,4BAAA;EFsGF,0BAAA;CDyMD;AChMD;EEnHI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EACA,4BAAA;ECnBF,oEAAA;EHqIA,mBAAA;ECrEA,4FAAA;EACQ,oFAAA;CF4QT;AC3MD;;EEnHI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EACA,4BAAA;ED6CF,yDAAA;EACQ,iDAAA;CFsRT;ACxMD;;EAEE,+CAAA;CD0MD;ACtMD;EEtII,sEAAA;EACA,iEAAA;EACA,2FAAA;EAAA,oEAAA;EACA,uHAAA;EACA,4BAAA;ECnBF,oEAAA;EHwJA,mBAAA;CD4MD;AC/MD;;EEtII,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EACA,4BAAA;ED6CF,wDAAA;EACQ,gDAAA;CF6ST;ACzND;;EAYI,0CAAA;CDiNH;AC5MD;;;EAGE,iBAAA;CD8MD;AC1MD;EAEI;;;IAGE,YAAA;IEnKF,yEAAA;IACA,oEAAA;IACA,8FAAA;IAAA,uEAAA;IACA,uHAAA;IACA,4BAAA;GH+WD;CACF;ACrMD;EACE,8CAAA;EC/HA,2FAAA;EACQ,mFAAA;CFuUT;AC7LD;EE5LI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EACA,4BAAA;EFoLF,sBAAA;CDyMD;ACpMD;EE7LI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EACA,4BAAA;EFoLF,sBAAA;CDiND;AC3MD;EE9LI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EACA,4BAAA;EFoLF,sBAAA;CDyND;AClND;EE/LI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EACA,4BAAA;EFoLF,sBAAA;CDiOD;AClND;EEvMI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EACA,4BAAA;CH4ZH;AC/MD;EEjNI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EACA,4BAAA;CHmaH;ACrND;EElNI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EACA,4BAAA;CH0aH;AC3ND;EEnNI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EACA,4BAAA;CHibH;ACjOD;EEpNI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EACA,4BAAA;CHwbH;ACvOD;EErNI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EACA,4BAAA;CH+bH;AC1OD;EExLI,8MAAA;EACA,yMAAA;EACA,sMAAA;CHqaH;ACtOD;EACE,mBAAA;EClLA,mDAAA;EACQ,2CAAA;CF2ZT;ACvOD;;;EAGE,8BAAA;EEzOE,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EACA,4BAAA;EFuOF,sBAAA;CD6OD;AClPD;;;EAQI,kBAAA;CD+OH;ACrOD;ECvME,kDAAA;EACQ,0CAAA;CF+aT;AC/ND;EElQI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EACA,4BAAA;CHoeH;ACrOD;EEnQI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EACA,4BAAA;CH2eH;AC3OD;EEpQI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EACA,4BAAA;CHkfH;ACjPD;EErQI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EACA,4BAAA;CHyfH;ACvPD;EEtQI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EACA,4BAAA;CHggBH;AC7PD;EEvQI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EACA,4BAAA;CHugBH;AC7PD;EE9QI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,uHAAA;EACA,4BAAA;EF4QF,sBAAA;EC/NA,0FAAA;EACQ,kFAAA;CFmeT","file":"bootstrap-theme.css","sourcesContent":["/*!\n * Bootstrap v3.4.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.btn-default:active,\n.btn-primary:active,\n.btn-success:active,\n.btn-info:active,\n.btn-warning:active,\n.btn-danger:active,\n.btn-default.active,\n.btn-primary.active,\n.btn-success.active,\n.btn-info.active,\n.btn-warning.active,\n.btn-danger.active {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-default.disabled,\n.btn-primary.disabled,\n.btn-success.disabled,\n.btn-info.disabled,\n.btn-warning.disabled,\n.btn-danger.disabled,\n.btn-default[disabled],\n.btn-primary[disabled],\n.btn-success[disabled],\n.btn-info[disabled],\n.btn-warning[disabled],\n.btn-danger[disabled],\nfieldset[disabled] .btn-default,\nfieldset[disabled] .btn-primary,\nfieldset[disabled] .btn-success,\nfieldset[disabled] .btn-info,\nfieldset[disabled] .btn-warning,\nfieldset[disabled] .btn-danger {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-default .badge,\n.btn-primary .badge,\n.btn-success .badge,\n.btn-info .badge,\n.btn-warning .badge,\n.btn-danger .badge {\n text-shadow: none;\n}\n.btn:active,\n.btn.active {\n background-image: none;\n}\n.btn-default {\n background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);\n background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);\n background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #dbdbdb;\n text-shadow: 0 1px 0 #fff;\n border-color: #ccc;\n}\n.btn-default:hover,\n.btn-default:focus {\n background-color: #e0e0e0;\n background-position: 0 -15px;\n}\n.btn-default:active,\n.btn-default.active {\n background-color: #e0e0e0;\n border-color: #dbdbdb;\n}\n.btn-default.disabled,\n.btn-default[disabled],\nfieldset[disabled] .btn-default,\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus,\n.btn-default.disabled:active,\n.btn-default[disabled]:active,\nfieldset[disabled] .btn-default:active,\n.btn-default.disabled.active,\n.btn-default[disabled].active,\nfieldset[disabled] .btn-default.active {\n background-color: #e0e0e0;\n background-image: none;\n}\n.btn-primary {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #245580;\n}\n.btn-primary:hover,\n.btn-primary:focus {\n background-color: #265a88;\n background-position: 0 -15px;\n}\n.btn-primary:active,\n.btn-primary.active {\n background-color: #265a88;\n border-color: #245580;\n}\n.btn-primary.disabled,\n.btn-primary[disabled],\nfieldset[disabled] .btn-primary,\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus,\n.btn-primary.disabled:active,\n.btn-primary[disabled]:active,\nfieldset[disabled] .btn-primary:active,\n.btn-primary.disabled.active,\n.btn-primary[disabled].active,\nfieldset[disabled] .btn-primary.active {\n background-color: #265a88;\n background-image: none;\n}\n.btn-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #3e8f3e;\n}\n.btn-success:hover,\n.btn-success:focus {\n background-color: #419641;\n background-position: 0 -15px;\n}\n.btn-success:active,\n.btn-success.active {\n background-color: #419641;\n border-color: #3e8f3e;\n}\n.btn-success.disabled,\n.btn-success[disabled],\nfieldset[disabled] .btn-success,\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus,\n.btn-success.disabled:active,\n.btn-success[disabled]:active,\nfieldset[disabled] .btn-success:active,\n.btn-success.disabled.active,\n.btn-success[disabled].active,\nfieldset[disabled] .btn-success.active {\n background-color: #419641;\n background-image: none;\n}\n.btn-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #28a4c9;\n}\n.btn-info:hover,\n.btn-info:focus {\n background-color: #2aabd2;\n background-position: 0 -15px;\n}\n.btn-info:active,\n.btn-info.active {\n background-color: #2aabd2;\n border-color: #28a4c9;\n}\n.btn-info.disabled,\n.btn-info[disabled],\nfieldset[disabled] .btn-info,\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus,\n.btn-info.disabled:active,\n.btn-info[disabled]:active,\nfieldset[disabled] .btn-info:active,\n.btn-info.disabled.active,\n.btn-info[disabled].active,\nfieldset[disabled] .btn-info.active {\n background-color: #2aabd2;\n background-image: none;\n}\n.btn-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #e38d13;\n}\n.btn-warning:hover,\n.btn-warning:focus {\n background-color: #eb9316;\n background-position: 0 -15px;\n}\n.btn-warning:active,\n.btn-warning.active {\n background-color: #eb9316;\n border-color: #e38d13;\n}\n.btn-warning.disabled,\n.btn-warning[disabled],\nfieldset[disabled] .btn-warning,\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus,\n.btn-warning.disabled:active,\n.btn-warning[disabled]:active,\nfieldset[disabled] .btn-warning:active,\n.btn-warning.disabled.active,\n.btn-warning[disabled].active,\nfieldset[disabled] .btn-warning.active {\n background-color: #eb9316;\n background-image: none;\n}\n.btn-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #b92c28;\n}\n.btn-danger:hover,\n.btn-danger:focus {\n background-color: #c12e2a;\n background-position: 0 -15px;\n}\n.btn-danger:active,\n.btn-danger.active {\n background-color: #c12e2a;\n border-color: #b92c28;\n}\n.btn-danger.disabled,\n.btn-danger[disabled],\nfieldset[disabled] .btn-danger,\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus,\n.btn-danger.disabled:active,\n.btn-danger[disabled]:active,\nfieldset[disabled] .btn-danger:active,\n.btn-danger.disabled.active,\n.btn-danger[disabled].active,\nfieldset[disabled] .btn-danger.active {\n background-color: #c12e2a;\n background-image: none;\n}\n.thumbnail,\n.img-thumbnail {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n background-repeat: repeat-x;\n background-color: #e8e8e8;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n background-repeat: repeat-x;\n background-color: #2e6da4;\n}\n.navbar-default {\n background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: -o-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);\n background-repeat: repeat-x;\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);\n}\n.navbar-inverse {\n background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);\n background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);\n background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n border-radius: 4px;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);\n background-repeat: repeat-x;\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n}\n.navbar-inverse .navbar-brand,\n.navbar-inverse .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n@media (max-width: 767px) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n background-repeat: repeat-x;\n }\n}\n.alert {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.alert-success {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);\n background-repeat: repeat-x;\n border-color: #b2dba1;\n}\n.alert-info {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);\n background-repeat: repeat-x;\n border-color: #9acfea;\n}\n.alert-warning {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);\n background-repeat: repeat-x;\n border-color: #f5e79e;\n}\n.alert-danger {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);\n background-repeat: repeat-x;\n border-color: #dca7a7;\n}\n.progress {\n background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.list-group {\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 #286090;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);\n background-repeat: repeat-x;\n border-color: #2b669a;\n}\n.list-group-item.active .badge,\n.list-group-item.active:hover .badge,\n.list-group-item.active:focus .badge {\n text-shadow: none;\n}\n.panel {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.panel-default > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-primary > .panel-heading {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-success > .panel-heading {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-info > .panel-heading {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-warning > .panel-heading {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-danger > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);\n background-repeat: repeat-x;\n}\n.well {\n background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);\n background-repeat: repeat-x;\n border-color: #dcdcdc;\n -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n}\n/*# sourceMappingURL=bootstrap-theme.css.map */","// stylelint-disable selector-no-qualifying-type, selector-max-compound-selectors\n\n/*!\n * Bootstrap v3.4.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);\n @shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);\n .box-shadow(@shadow);\n\n // Reset the shadow\n &:active,\n &.active {\n .box-shadow(inset 0 3px 5px rgba(0, 0, 0, .125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n .box-shadow(none);\n }\n\n .badge {\n text-shadow: none;\n }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners; see https://github.com/twbs/bootstrap/issues/10620\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &,\n &:hover,\n &:focus,\n &.focus,\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n background-image: none;\n }\n }\n}\n\n// Common styles\n.btn {\n // Remove the gradient for the pressed/active state\n &:active,\n &.active {\n background-image: none;\n }\n}\n\n// Apply the mixin to the buttons\n.btn-default {\n .btn-styles(@btn-default-bg);\n text-shadow: 0 1px 0 #fff;\n border-color: #ccc;\n}\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-bg); }\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n .box-shadow(0 1px 2px rgba(0, 0, 0, .075));\n}\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n border-radius: @navbar-border-radius;\n @shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);\n .box-shadow(@shadow);\n\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: darken(@navbar-default-link-active-bg, 5%); @end-color: darken(@navbar-default-link-active-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0, 0, 0, .075));\n }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255, 255, 255, .25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered; see https://github.com/twbs/bootstrap/issues/10257\n border-radius: @navbar-border-radius;\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-link-active-bg; @end-color: lighten(@navbar-inverse-link-active-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0, 0, 0, .25));\n }\n\n .navbar-brand,\n .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);\n }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n\n// Fix active state of dropdown items in collapsed mode\n@media (max-width: @grid-float-breakpoint-max) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: #fff;\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n }\n }\n}\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n text-shadow: 0 1px 0 rgba(255, 255, 255, .2);\n @shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);\n .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success { .alert-styles(@alert-success-bg); }\n.alert-info { .alert-styles(@alert-info-bg); }\n.alert-warning { .alert-styles(@alert-warning-bg); }\n.alert-danger { .alert-styles(@alert-danger-bg); }\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }\n\n// Reset the striped class because our mixins don't do multiple gradients and\n// the above custom styles override the new `.progress-bar-striped` in v3.2.0.\n.progress-bar-striped {\n #gradient > .striped();\n}\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n border-radius: @border-radius-base;\n .box-shadow(0 1px 2px rgba(0, 0, 0, .075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n border-color: darken(@list-group-active-border, 7.5%);\n\n .badge {\n text-shadow: none;\n }\n}\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n .box-shadow(0 1px 2px rgba(0, 0, 0, .05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n border-color: darken(@well-bg, 10%);\n @shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);\n .box-shadow(@shadow);\n}\n","// stylelint-disable indentation, property-no-vendor-prefix, selector-no-vendor-prefix\n\n// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They have been removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility) {\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n word-wrap: break-word;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// stylelint-disable value-no-vendor-prefix, selector-max-id\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\", argb(@start-color), argb(@end-color))); // IE9 and down\n background-repeat: repeat-x;\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\", argb(@start-color), argb(@end-color))); // IE9 and down\n background-repeat: repeat-x;\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\", argb(@start-color), argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n background-repeat: no-repeat;\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\", argb(@start-color), argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n background-repeat: no-repeat;\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255, 255, 255, .15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n"]} \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/resources/static/oauth/css/bootstrap-theme.min.css b/springboot/wumei-iot/src/main/resources/static/oauth/css/bootstrap-theme.min.css deleted file mode 100644 index 2a69f48c..00000000 --- a/springboot/wumei-iot/src/main/resources/static/oauth/css/bootstrap-theme.min.css +++ /dev/null @@ -1,6 +0,0 @@ -/*! - * Bootstrap v3.4.1 (https://getbootstrap.com/) - * Copyright 2011-2019 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger.disabled,.btn-danger[disabled],.btn-default.disabled,.btn-default[disabled],.btn-info.disabled,.btn-info[disabled],.btn-primary.disabled,.btn-primary[disabled],.btn-success.disabled,.btn-success[disabled],.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-default,fieldset[disabled] .btn-info,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-warning{-webkit-box-shadow:none;box-shadow:none}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;text-shadow:0 1px 0 #fff;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x;background-color:#e8e8e8}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x;background-color:#2e6da4}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);border-radius:4px}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} -/*# sourceMappingURL=bootstrap-theme.min.css.map */ \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/resources/static/oauth/css/bootstrap-theme.min.css.map b/springboot/wumei-iot/src/main/resources/static/oauth/css/bootstrap-theme.min.css.map deleted file mode 100644 index 5d75106e..00000000 --- a/springboot/wumei-iot/src/main/resources/static/oauth/css/bootstrap-theme.min.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["bootstrap-theme.css","dist/css/bootstrap-theme.css","less/theme.less","less/mixins/vendor-prefixes.less","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":"AAAA;;;;ACUA,YCWA,aDbA,UAFA,aACA,aAEA,aCkBE,YAAA,EAAA,KAAA,EAAA,eC2CA,mBAAA,MAAA,EAAA,IAAA,EAAA,qBAAA,CAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,EAAA,qBAAA,CAAA,EAAA,IAAA,IAAA,iBF7CV,mBANA,mBACA,oBCWE,oBDRF,iBANA,iBAIA,oBANA,oBAOA,oBANA,oBAQA,oBANA,oBEmDE,mBAAA,MAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,iBFpCV,qBAMA,sBCJE,sBDDF,uBAHA,mBAMA,oBARA,sBAMA,uBALA,sBAMA,uBAJA,sBAMA,uBAOA,+BALA,gCAGA,6BAFA,gCACA,gCAEA,gCEwBE,mBAAA,KACQ,WAAA,KFfV,mBCnCA,oBDiCA,iBAFA,oBACA,oBAEA,oBCXI,YAAA,KDgBJ,YCyBE,YAEE,iBAAA,KAKJ,aEvEI,iBAAA,iDACA,iBAAA,4CACA,iBAAA,qEAAA,iBAAA,+CACA,OAAA,+GClBF,OAAA,0DH8CA,kBAAA,SACA,aAAA,QAyCA,YAAA,EAAA,IAAA,EAAA,KACA,aAAA,KDnBF,mBCrBE,mBAEE,iBAAA,QACA,oBAAA,EAAA,MDuBJ,oBCpBE,oBAEE,iBAAA,QACA,aAAA,QAMA,sBD8BJ,6BANA,4BAGA,6BANA,4BAHA,4BAFA,uBAeA,8BANA,6BAGA,8BANA,6BAHA,6BAFA,gCAeA,uCANA,sCAGA,uCANA,sCAHA,sCCdM,iBAAA,QACA,iBAAA,KAoBN,aE5EI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GClBF,OAAA,0DH8CA,kBAAA,SACA,aAAA,QDgEF,mBC9DE,mBAEE,iBAAA,QACA,oBAAA,EAAA,MDgEJ,oBC7DE,oBAEE,iBAAA,QACA,aAAA,QAMA,sBDuEJ,6BANA,4BAGA,6BANA,4BAHA,4BAFA,uBAeA,8BANA,6BAGA,8BANA,6BAHA,6BAFA,gCAeA,uCANA,sCAGA,uCANA,sCAHA,sCCvDM,iBAAA,QACA,iBAAA,KAqBN,aE7EI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GClBF,OAAA,0DH8CA,kBAAA,SACA,aAAA,QDyGF,mBCvGE,mBAEE,iBAAA,QACA,oBAAA,EAAA,MDyGJ,oBCtGE,oBAEE,iBAAA,QACA,aAAA,QAMA,sBDgHJ,6BANA,4BAGA,6BANA,4BAHA,4BAFA,uBAeA,8BANA,6BAGA,8BANA,6BAHA,6BAFA,gCAeA,uCANA,sCAGA,uCANA,sCAHA,sCChGM,iBAAA,QACA,iBAAA,KAsBN,UE9EI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GClBF,OAAA,0DH8CA,kBAAA,SACA,aAAA,QDkJF,gBChJE,gBAEE,iBAAA,QACA,oBAAA,EAAA,MDkJJ,iBC/IE,iBAEE,iBAAA,QACA,aAAA,QAMA,mBDyJJ,0BANA,yBAGA,0BANA,yBAHA,yBAFA,oBAeA,2BANA,0BAGA,2BANA,0BAHA,0BAFA,6BAeA,oCANA,mCAGA,oCANA,mCAHA,mCCzIM,iBAAA,QACA,iBAAA,KAuBN,aE/EI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GClBF,OAAA,0DH8CA,kBAAA,SACA,aAAA,QD2LF,mBCzLE,mBAEE,iBAAA,QACA,oBAAA,EAAA,MD2LJ,oBCxLE,oBAEE,iBAAA,QACA,aAAA,QAMA,sBDkMJ,6BANA,4BAGA,6BANA,4BAHA,4BAFA,uBAeA,8BANA,6BAGA,8BANA,6BAHA,6BAFA,gCAeA,uCANA,sCAGA,uCANA,sCAHA,sCClLM,iBAAA,QACA,iBAAA,KAwBN,YEhFI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GClBF,OAAA,0DH8CA,kBAAA,SACA,aAAA,QDoOF,kBClOE,kBAEE,iBAAA,QACA,oBAAA,EAAA,MDoOJ,mBCjOE,mBAEE,iBAAA,QACA,aAAA,QAMA,qBD2OJ,4BANA,2BAGA,4BANA,2BAHA,2BAFA,sBAeA,6BANA,4BAGA,6BANA,4BAHA,4BAFA,+BAeA,sCANA,qCAGA,sCANA,qCAHA,qCC3NM,iBAAA,QACA,iBAAA,KD2ON,eC5MA,WCtCE,mBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,EAAA,IAAA,IAAA,iBFsPV,0BCvMA,0BEjGI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFgGF,iBAAA,QAEF,yBD6MA,+BADA,+BGlTI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFsGF,iBAAA,QASF,gBEnHI,iBAAA,iDACA,iBAAA,4CACA,iBAAA,qEAAA,iBAAA,+CACA,OAAA,+GACA,kBAAA,SCnBF,OAAA,0DHqIA,cAAA,ICrEA,mBAAA,MAAA,EAAA,IAAA,EAAA,qBAAA,CAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,EAAA,qBAAA,CAAA,EAAA,IAAA,IAAA,iBFuRV,sCCtNA,oCEnHI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SD6CF,mBAAA,MAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,iBD8EV,cDoNA,iBClNE,YAAA,EAAA,IAAA,EAAA,sBAIF,gBEtII,iBAAA,iDACA,iBAAA,4CACA,iBAAA,qEAAA,iBAAA,+CACA,OAAA,+GACA,kBAAA,SCnBF,OAAA,0DHwJA,cAAA,IDyNF,sCC5NA,oCEtII,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SD6CF,mBAAA,MAAA,EAAA,IAAA,IAAA,gBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,gBDoFV,8BDuOA,iCC3NI,YAAA,EAAA,KAAA,EAAA,gBDgOJ,qBADA,kBC1NA,mBAGE,cAAA,EAIF,yBAEI,mDDwNF,yDADA,yDCpNI,MAAA,KEnKF,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,UF2KJ,OACE,YAAA,EAAA,IAAA,EAAA,qBC/HA,mBAAA,MAAA,EAAA,IAAA,EAAA,qBAAA,CAAA,EAAA,IAAA,IAAA,gBACQ,WAAA,MAAA,EAAA,IAAA,EAAA,qBAAA,CAAA,EAAA,IAAA,IAAA,gBD0IV,eE5LI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFoLF,aAAA,QAKF,YE7LI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFoLF,aAAA,QAMF,eE9LI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFoLF,aAAA,QAOF,cE/LI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFoLF,aAAA,QAeF,UEvMI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF6MJ,cEjNI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8MJ,sBElNI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF+MJ,mBEnNI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFgNJ,sBEpNI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFiNJ,qBErNI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFqNJ,sBExLI,iBAAA,yKACA,iBAAA,oKACA,iBAAA,iKF+LJ,YACE,cAAA,IClLA,mBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,EAAA,IAAA,IAAA,iBDoLV,wBDiQA,8BADA,8BC7PE,YAAA,EAAA,KAAA,EAAA,QEzOE,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFuOF,aAAA,QALF,+BD6QA,qCADA,qCCpQI,YAAA,KAUJ,OCvME,mBAAA,EAAA,IAAA,IAAA,gBACQ,WAAA,EAAA,IAAA,IAAA,gBDgNV,8BElQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF+PJ,8BEnQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFgQJ,8BEpQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFiQJ,2BErQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFkQJ,8BEtQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFmQJ,6BEvQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF0QJ,ME9QI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF4QF,aAAA,QC/NA,mBAAA,MAAA,EAAA,IAAA,IAAA,eAAA,CAAA,EAAA,IAAA,EAAA,qBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,eAAA,CAAA,EAAA,IAAA,EAAA","sourcesContent":["/*!\n * Bootstrap v3.4.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.btn-default:active,\n.btn-primary:active,\n.btn-success:active,\n.btn-info:active,\n.btn-warning:active,\n.btn-danger:active,\n.btn-default.active,\n.btn-primary.active,\n.btn-success.active,\n.btn-info.active,\n.btn-warning.active,\n.btn-danger.active {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-default.disabled,\n.btn-primary.disabled,\n.btn-success.disabled,\n.btn-info.disabled,\n.btn-warning.disabled,\n.btn-danger.disabled,\n.btn-default[disabled],\n.btn-primary[disabled],\n.btn-success[disabled],\n.btn-info[disabled],\n.btn-warning[disabled],\n.btn-danger[disabled],\nfieldset[disabled] .btn-default,\nfieldset[disabled] .btn-primary,\nfieldset[disabled] .btn-success,\nfieldset[disabled] .btn-info,\nfieldset[disabled] .btn-warning,\nfieldset[disabled] .btn-danger {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-default .badge,\n.btn-primary .badge,\n.btn-success .badge,\n.btn-info .badge,\n.btn-warning .badge,\n.btn-danger .badge {\n text-shadow: none;\n}\n.btn:active,\n.btn.active {\n background-image: none;\n}\n.btn-default {\n background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);\n background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);\n background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #dbdbdb;\n text-shadow: 0 1px 0 #fff;\n border-color: #ccc;\n}\n.btn-default:hover,\n.btn-default:focus {\n background-color: #e0e0e0;\n background-position: 0 -15px;\n}\n.btn-default:active,\n.btn-default.active {\n background-color: #e0e0e0;\n border-color: #dbdbdb;\n}\n.btn-default.disabled,\n.btn-default[disabled],\nfieldset[disabled] .btn-default,\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus,\n.btn-default.disabled:active,\n.btn-default[disabled]:active,\nfieldset[disabled] .btn-default:active,\n.btn-default.disabled.active,\n.btn-default[disabled].active,\nfieldset[disabled] .btn-default.active {\n background-color: #e0e0e0;\n background-image: none;\n}\n.btn-primary {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #245580;\n}\n.btn-primary:hover,\n.btn-primary:focus {\n background-color: #265a88;\n background-position: 0 -15px;\n}\n.btn-primary:active,\n.btn-primary.active {\n background-color: #265a88;\n border-color: #245580;\n}\n.btn-primary.disabled,\n.btn-primary[disabled],\nfieldset[disabled] .btn-primary,\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus,\n.btn-primary.disabled:active,\n.btn-primary[disabled]:active,\nfieldset[disabled] .btn-primary:active,\n.btn-primary.disabled.active,\n.btn-primary[disabled].active,\nfieldset[disabled] .btn-primary.active {\n background-color: #265a88;\n background-image: none;\n}\n.btn-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #3e8f3e;\n}\n.btn-success:hover,\n.btn-success:focus {\n background-color: #419641;\n background-position: 0 -15px;\n}\n.btn-success:active,\n.btn-success.active {\n background-color: #419641;\n border-color: #3e8f3e;\n}\n.btn-success.disabled,\n.btn-success[disabled],\nfieldset[disabled] .btn-success,\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus,\n.btn-success.disabled:active,\n.btn-success[disabled]:active,\nfieldset[disabled] .btn-success:active,\n.btn-success.disabled.active,\n.btn-success[disabled].active,\nfieldset[disabled] .btn-success.active {\n background-color: #419641;\n background-image: none;\n}\n.btn-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #28a4c9;\n}\n.btn-info:hover,\n.btn-info:focus {\n background-color: #2aabd2;\n background-position: 0 -15px;\n}\n.btn-info:active,\n.btn-info.active {\n background-color: #2aabd2;\n border-color: #28a4c9;\n}\n.btn-info.disabled,\n.btn-info[disabled],\nfieldset[disabled] .btn-info,\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus,\n.btn-info.disabled:active,\n.btn-info[disabled]:active,\nfieldset[disabled] .btn-info:active,\n.btn-info.disabled.active,\n.btn-info[disabled].active,\nfieldset[disabled] .btn-info.active {\n background-color: #2aabd2;\n background-image: none;\n}\n.btn-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #e38d13;\n}\n.btn-warning:hover,\n.btn-warning:focus {\n background-color: #eb9316;\n background-position: 0 -15px;\n}\n.btn-warning:active,\n.btn-warning.active {\n background-color: #eb9316;\n border-color: #e38d13;\n}\n.btn-warning.disabled,\n.btn-warning[disabled],\nfieldset[disabled] .btn-warning,\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus,\n.btn-warning.disabled:active,\n.btn-warning[disabled]:active,\nfieldset[disabled] .btn-warning:active,\n.btn-warning.disabled.active,\n.btn-warning[disabled].active,\nfieldset[disabled] .btn-warning.active {\n background-color: #eb9316;\n background-image: none;\n}\n.btn-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #b92c28;\n}\n.btn-danger:hover,\n.btn-danger:focus {\n background-color: #c12e2a;\n background-position: 0 -15px;\n}\n.btn-danger:active,\n.btn-danger.active {\n background-color: #c12e2a;\n border-color: #b92c28;\n}\n.btn-danger.disabled,\n.btn-danger[disabled],\nfieldset[disabled] .btn-danger,\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus,\n.btn-danger.disabled:active,\n.btn-danger[disabled]:active,\nfieldset[disabled] .btn-danger:active,\n.btn-danger.disabled.active,\n.btn-danger[disabled].active,\nfieldset[disabled] .btn-danger.active {\n background-color: #c12e2a;\n background-image: none;\n}\n.thumbnail,\n.img-thumbnail {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n background-repeat: repeat-x;\n background-color: #e8e8e8;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n background-repeat: repeat-x;\n background-color: #2e6da4;\n}\n.navbar-default {\n background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: -o-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);\n background-repeat: repeat-x;\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);\n}\n.navbar-inverse {\n background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);\n background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);\n background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n border-radius: 4px;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);\n background-repeat: repeat-x;\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n}\n.navbar-inverse .navbar-brand,\n.navbar-inverse .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n@media (max-width: 767px) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n background-repeat: repeat-x;\n }\n}\n.alert {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.alert-success {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);\n background-repeat: repeat-x;\n border-color: #b2dba1;\n}\n.alert-info {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);\n background-repeat: repeat-x;\n border-color: #9acfea;\n}\n.alert-warning {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);\n background-repeat: repeat-x;\n border-color: #f5e79e;\n}\n.alert-danger {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);\n background-repeat: repeat-x;\n border-color: #dca7a7;\n}\n.progress {\n background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.list-group {\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 #286090;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);\n background-repeat: repeat-x;\n border-color: #2b669a;\n}\n.list-group-item.active .badge,\n.list-group-item.active:hover .badge,\n.list-group-item.active:focus .badge {\n text-shadow: none;\n}\n.panel {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.panel-default > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-primary > .panel-heading {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-success > .panel-heading {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-info > .panel-heading {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-warning > .panel-heading {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-danger > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);\n background-repeat: repeat-x;\n}\n.well {\n background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);\n background-repeat: repeat-x;\n border-color: #dcdcdc;\n -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n}\n/*# sourceMappingURL=bootstrap-theme.css.map */","/*!\n * Bootstrap v3.4.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.btn-default:active,\n.btn-primary:active,\n.btn-success:active,\n.btn-info:active,\n.btn-warning:active,\n.btn-danger:active,\n.btn-default.active,\n.btn-primary.active,\n.btn-success.active,\n.btn-info.active,\n.btn-warning.active,\n.btn-danger.active {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-default.disabled,\n.btn-primary.disabled,\n.btn-success.disabled,\n.btn-info.disabled,\n.btn-warning.disabled,\n.btn-danger.disabled,\n.btn-default[disabled],\n.btn-primary[disabled],\n.btn-success[disabled],\n.btn-info[disabled],\n.btn-warning[disabled],\n.btn-danger[disabled],\nfieldset[disabled] .btn-default,\nfieldset[disabled] .btn-primary,\nfieldset[disabled] .btn-success,\nfieldset[disabled] .btn-info,\nfieldset[disabled] .btn-warning,\nfieldset[disabled] .btn-danger {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-default .badge,\n.btn-primary .badge,\n.btn-success .badge,\n.btn-info .badge,\n.btn-warning .badge,\n.btn-danger .badge {\n text-shadow: none;\n}\n.btn:active,\n.btn.active {\n background-image: none;\n}\n.btn-default {\n background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);\n background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));\n background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #dbdbdb;\n text-shadow: 0 1px 0 #fff;\n border-color: #ccc;\n}\n.btn-default:hover,\n.btn-default:focus {\n background-color: #e0e0e0;\n background-position: 0 -15px;\n}\n.btn-default:active,\n.btn-default.active {\n background-color: #e0e0e0;\n border-color: #dbdbdb;\n}\n.btn-default.disabled,\n.btn-default[disabled],\nfieldset[disabled] .btn-default,\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus,\n.btn-default.disabled:active,\n.btn-default[disabled]:active,\nfieldset[disabled] .btn-default:active,\n.btn-default.disabled.active,\n.btn-default[disabled].active,\nfieldset[disabled] .btn-default.active {\n background-color: #e0e0e0;\n background-image: none;\n}\n.btn-primary {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88));\n background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #245580;\n}\n.btn-primary:hover,\n.btn-primary:focus {\n background-color: #265a88;\n background-position: 0 -15px;\n}\n.btn-primary:active,\n.btn-primary.active {\n background-color: #265a88;\n border-color: #245580;\n}\n.btn-primary.disabled,\n.btn-primary[disabled],\nfieldset[disabled] .btn-primary,\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus,\n.btn-primary.disabled:active,\n.btn-primary[disabled]:active,\nfieldset[disabled] .btn-primary:active,\n.btn-primary.disabled.active,\n.btn-primary[disabled].active,\nfieldset[disabled] .btn-primary.active {\n background-color: #265a88;\n background-image: none;\n}\n.btn-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));\n background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #3e8f3e;\n}\n.btn-success:hover,\n.btn-success:focus {\n background-color: #419641;\n background-position: 0 -15px;\n}\n.btn-success:active,\n.btn-success.active {\n background-color: #419641;\n border-color: #3e8f3e;\n}\n.btn-success.disabled,\n.btn-success[disabled],\nfieldset[disabled] .btn-success,\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus,\n.btn-success.disabled:active,\n.btn-success[disabled]:active,\nfieldset[disabled] .btn-success:active,\n.btn-success.disabled.active,\n.btn-success[disabled].active,\nfieldset[disabled] .btn-success.active {\n background-color: #419641;\n background-image: none;\n}\n.btn-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));\n background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #28a4c9;\n}\n.btn-info:hover,\n.btn-info:focus {\n background-color: #2aabd2;\n background-position: 0 -15px;\n}\n.btn-info:active,\n.btn-info.active {\n background-color: #2aabd2;\n border-color: #28a4c9;\n}\n.btn-info.disabled,\n.btn-info[disabled],\nfieldset[disabled] .btn-info,\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus,\n.btn-info.disabled:active,\n.btn-info[disabled]:active,\nfieldset[disabled] .btn-info:active,\n.btn-info.disabled.active,\n.btn-info[disabled].active,\nfieldset[disabled] .btn-info.active {\n background-color: #2aabd2;\n background-image: none;\n}\n.btn-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #e38d13;\n}\n.btn-warning:hover,\n.btn-warning:focus {\n background-color: #eb9316;\n background-position: 0 -15px;\n}\n.btn-warning:active,\n.btn-warning.active {\n background-color: #eb9316;\n border-color: #e38d13;\n}\n.btn-warning.disabled,\n.btn-warning[disabled],\nfieldset[disabled] .btn-warning,\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus,\n.btn-warning.disabled:active,\n.btn-warning[disabled]:active,\nfieldset[disabled] .btn-warning:active,\n.btn-warning.disabled.active,\n.btn-warning[disabled].active,\nfieldset[disabled] .btn-warning.active {\n background-color: #eb9316;\n background-image: none;\n}\n.btn-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));\n background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #b92c28;\n}\n.btn-danger:hover,\n.btn-danger:focus {\n background-color: #c12e2a;\n background-position: 0 -15px;\n}\n.btn-danger:active,\n.btn-danger.active {\n background-color: #c12e2a;\n border-color: #b92c28;\n}\n.btn-danger.disabled,\n.btn-danger[disabled],\nfieldset[disabled] .btn-danger,\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus,\n.btn-danger.disabled:active,\n.btn-danger[disabled]:active,\nfieldset[disabled] .btn-danger:active,\n.btn-danger.disabled.active,\n.btn-danger[disabled].active,\nfieldset[disabled] .btn-danger.active {\n background-color: #c12e2a;\n background-image: none;\n}\n.thumbnail,\n.img-thumbnail {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n background-repeat: repeat-x;\n background-color: #e8e8e8;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n background-repeat: repeat-x;\n background-color: #2e6da4;\n}\n.navbar-default {\n background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: -o-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#f8f8f8));\n background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2));\n background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);\n background-repeat: repeat-x;\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);\n}\n.navbar-inverse {\n background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);\n background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));\n background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n border-radius: 4px;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f));\n background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);\n background-repeat: repeat-x;\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n}\n.navbar-inverse .navbar-brand,\n.navbar-inverse .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n@media (max-width: 767px) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n background-repeat: repeat-x;\n }\n}\n.alert {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.alert-success {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));\n background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);\n background-repeat: repeat-x;\n border-color: #b2dba1;\n}\n.alert-info {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));\n background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);\n background-repeat: repeat-x;\n border-color: #9acfea;\n}\n.alert-warning {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);\n background-repeat: repeat-x;\n border-color: #f5e79e;\n}\n.alert-danger {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));\n background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);\n background-repeat: repeat-x;\n border-color: #dca7a7;\n}\n.progress {\n background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));\n background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090));\n background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));\n background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));\n background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));\n background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);\n background-repeat: repeat-x;\n}\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.list-group {\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 #286090;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a));\n background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);\n background-repeat: repeat-x;\n border-color: #2b669a;\n}\n.list-group-item.active .badge,\n.list-group-item.active:hover .badge,\n.list-group-item.active:focus .badge {\n text-shadow: none;\n}\n.panel {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.panel-default > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-primary > .panel-heading {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-success > .panel-heading {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));\n background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-info > .panel-heading {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));\n background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-warning > .panel-heading {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);\n background-repeat: repeat-x;\n}\n.panel-danger > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));\n background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);\n background-repeat: repeat-x;\n}\n.well {\n background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));\n background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);\n background-repeat: repeat-x;\n border-color: #dcdcdc;\n -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n}\n/*# sourceMappingURL=bootstrap-theme.css.map */","// stylelint-disable selector-no-qualifying-type, selector-max-compound-selectors\n\n/*!\n * Bootstrap v3.4.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);\n @shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);\n .box-shadow(@shadow);\n\n // Reset the shadow\n &:active,\n &.active {\n .box-shadow(inset 0 3px 5px rgba(0, 0, 0, .125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n .box-shadow(none);\n }\n\n .badge {\n text-shadow: none;\n }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners; see https://github.com/twbs/bootstrap/issues/10620\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &,\n &:hover,\n &:focus,\n &.focus,\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n background-image: none;\n }\n }\n}\n\n// Common styles\n.btn {\n // Remove the gradient for the pressed/active state\n &:active,\n &.active {\n background-image: none;\n }\n}\n\n// Apply the mixin to the buttons\n.btn-default {\n .btn-styles(@btn-default-bg);\n text-shadow: 0 1px 0 #fff;\n border-color: #ccc;\n}\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-bg); }\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n .box-shadow(0 1px 2px rgba(0, 0, 0, .075));\n}\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n border-radius: @navbar-border-radius;\n @shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);\n .box-shadow(@shadow);\n\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: darken(@navbar-default-link-active-bg, 5%); @end-color: darken(@navbar-default-link-active-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0, 0, 0, .075));\n }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255, 255, 255, .25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered; see https://github.com/twbs/bootstrap/issues/10257\n border-radius: @navbar-border-radius;\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-link-active-bg; @end-color: lighten(@navbar-inverse-link-active-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0, 0, 0, .25));\n }\n\n .navbar-brand,\n .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);\n }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n\n// Fix active state of dropdown items in collapsed mode\n@media (max-width: @grid-float-breakpoint-max) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: #fff;\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n }\n }\n}\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n text-shadow: 0 1px 0 rgba(255, 255, 255, .2);\n @shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);\n .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success { .alert-styles(@alert-success-bg); }\n.alert-info { .alert-styles(@alert-info-bg); }\n.alert-warning { .alert-styles(@alert-warning-bg); }\n.alert-danger { .alert-styles(@alert-danger-bg); }\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }\n\n// Reset the striped class because our mixins don't do multiple gradients and\n// the above custom styles override the new `.progress-bar-striped` in v3.2.0.\n.progress-bar-striped {\n #gradient > .striped();\n}\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n border-radius: @border-radius-base;\n .box-shadow(0 1px 2px rgba(0, 0, 0, .075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n border-color: darken(@list-group-active-border, 7.5%);\n\n .badge {\n text-shadow: none;\n }\n}\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n .box-shadow(0 1px 2px rgba(0, 0, 0, .05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n border-color: darken(@well-bg, 10%);\n @shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);\n .box-shadow(@shadow);\n}\n","// stylelint-disable indentation, property-no-vendor-prefix, selector-no-vendor-prefix\n\n// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They have been removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility) {\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n word-wrap: break-word;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// stylelint-disable value-no-vendor-prefix, selector-max-id\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\", argb(@start-color), argb(@end-color))); // IE9 and down\n background-repeat: repeat-x;\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\", argb(@start-color), argb(@end-color))); // IE9 and down\n background-repeat: repeat-x;\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\", argb(@start-color), argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n background-repeat: no-repeat;\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\", argb(@start-color), argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n background-repeat: no-repeat;\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255, 255, 255, .15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n"]} \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/resources/static/oauth/css/bootstrap.css b/springboot/wumei-iot/src/main/resources/static/oauth/css/bootstrap.css deleted file mode 100644 index fcab4155..00000000 --- a/springboot/wumei-iot/src/main/resources/static/oauth/css/bootstrap.css +++ /dev/null @@ -1,6834 +0,0 @@ -/*! - * Bootstrap v3.4.1 (https://getbootstrap.com/) - * Copyright 2011-2019 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ -/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ -html { - font-family: sans-serif; - -ms-text-size-adjust: 100%; - -webkit-text-size-adjust: 100%; -} -body { - margin: 0; -} -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -main, -menu, -nav, -section, -summary { - display: block; -} -audio, -canvas, -progress, -video { - display: inline-block; - vertical-align: baseline; -} -audio:not([controls]) { - display: none; - height: 0; -} -[hidden], -template { - display: none; -} -a { - background-color: transparent; -} -a:active, -a:hover { - outline: 0; -} -abbr[title] { - border-bottom: none; - text-decoration: underline; - -webkit-text-decoration: underline dotted; - -moz-text-decoration: underline dotted; - text-decoration: underline dotted; -} -b, -strong { - font-weight: bold; -} -dfn { - font-style: italic; -} -h1 { - font-size: 2em; - margin: 0.67em 0; -} -mark { - background: #ff0; - color: #000; -} -small { - font-size: 80%; -} -sub, -sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} -sup { - top: -0.5em; -} -sub { - bottom: -0.25em; -} -img { - border: 0; -} -svg:not(:root) { - overflow: hidden; -} -figure { - margin: 1em 40px; -} -hr { - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; - height: 0; -} -pre { - overflow: auto; -} -code, -kbd, -pre, -samp { - font-family: monospace, monospace; - font-size: 1em; -} -button, -input, -optgroup, -select, -textarea { - color: inherit; - font: inherit; - margin: 0; -} -button { - overflow: visible; -} -button, -select { - text-transform: none; -} -button, -html input[type="button"], -input[type="reset"], -input[type="submit"] { - -webkit-appearance: button; - cursor: pointer; -} -button[disabled], -html input[disabled] { - cursor: default; -} -button::-moz-focus-inner, -input::-moz-focus-inner { - border: 0; - padding: 0; -} -input { - line-height: normal; -} -input[type="checkbox"], -input[type="radio"] { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - padding: 0; -} -input[type="number"]::-webkit-inner-spin-button, -input[type="number"]::-webkit-outer-spin-button { - height: auto; -} -input[type="search"] { - -webkit-appearance: textfield; - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; -} -input[type="search"]::-webkit-search-cancel-button, -input[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; -} -fieldset { - border: 1px solid #c0c0c0; - margin: 0 2px; - padding: 0.35em 0.625em 0.75em; -} -legend { - border: 0; - padding: 0; -} -textarea { - overflow: auto; -} -optgroup { - font-weight: bold; -} -table { - border-collapse: collapse; - border-spacing: 0; -} -td, -th { - padding: 0; -} -/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ -@media print { - *, - *:before, - *:after { - color: #000 !important; - text-shadow: none !important; - background: transparent !important; - -webkit-box-shadow: none !important; - box-shadow: none !important; - } - a, - a:visited { - text-decoration: underline; - } - a[href]:after { - content: " (" attr(href) ")"; - } - abbr[title]:after { - content: " (" attr(title) ")"; - } - a[href^="#"]:after, - a[href^="javascript:"]:after { - content: ""; - } - pre, - blockquote { - border: 1px solid #999; - page-break-inside: avoid; - } - thead { - display: table-header-group; - } - tr, - img { - page-break-inside: avoid; - } - img { - max-width: 100% !important; - } - p, - h2, - h3 { - orphans: 3; - widows: 3; - } - h2, - h3 { - page-break-after: avoid; - } - .navbar { - display: none; - } - .btn > .caret, - .dropup > .btn > .caret { - border-top-color: #000 !important; - } - .label { - border: 1px solid #000; - } - .table { - border-collapse: collapse !important; - } - .table td, - .table th { - background-color: #fff !important; - } - .table-bordered th, - .table-bordered td { - border: 1px solid #ddd !important; - } -} -@font-face { - font-family: "Glyphicons Halflings"; - src: url("../fonts/glyphicons-halflings-regular.eot"); - src: url("../fonts/glyphicons-halflings-regular.eot?#iefix") format("embedded-opentype"), url("../fonts/glyphicons-halflings-regular.woff2") format("woff2"), url("../fonts/glyphicons-halflings-regular.woff") format("woff"), url("../fonts/glyphicons-halflings-regular.ttf") format("truetype"), url("../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular") format("svg"); -} -.glyphicon { - position: relative; - top: 1px; - display: inline-block; - font-family: "Glyphicons Halflings"; - font-style: normal; - font-weight: 400; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} -.glyphicon-asterisk:before { - content: "\002a"; -} -.glyphicon-plus:before { - content: "\002b"; -} -.glyphicon-euro:before, -.glyphicon-eur:before { - content: "\20ac"; -} -.glyphicon-minus:before { - content: "\2212"; -} -.glyphicon-cloud:before { - content: "\2601"; -} -.glyphicon-envelope:before { - content: "\2709"; -} -.glyphicon-pencil:before { - content: "\270f"; -} -.glyphicon-glass:before { - content: "\e001"; -} -.glyphicon-music:before { - content: "\e002"; -} -.glyphicon-search:before { - content: "\e003"; -} -.glyphicon-heart:before { - content: "\e005"; -} -.glyphicon-star:before { - content: "\e006"; -} -.glyphicon-star-empty:before { - content: "\e007"; -} -.glyphicon-user:before { - content: "\e008"; -} -.glyphicon-film:before { - content: "\e009"; -} -.glyphicon-th-large:before { - content: "\e010"; -} -.glyphicon-th:before { - content: "\e011"; -} -.glyphicon-th-list:before { - content: "\e012"; -} -.glyphicon-ok:before { - content: "\e013"; -} -.glyphicon-remove:before { - content: "\e014"; -} -.glyphicon-zoom-in:before { - content: "\e015"; -} -.glyphicon-zoom-out:before { - content: "\e016"; -} -.glyphicon-off:before { - content: "\e017"; -} -.glyphicon-signal:before { - content: "\e018"; -} -.glyphicon-cog:before { - content: "\e019"; -} -.glyphicon-trash:before { - content: "\e020"; -} -.glyphicon-home:before { - content: "\e021"; -} -.glyphicon-file:before { - content: "\e022"; -} -.glyphicon-time:before { - content: "\e023"; -} -.glyphicon-road:before { - content: "\e024"; -} -.glyphicon-download-alt:before { - content: "\e025"; -} -.glyphicon-download:before { - content: "\e026"; -} -.glyphicon-upload:before { - content: "\e027"; -} -.glyphicon-inbox:before { - content: "\e028"; -} -.glyphicon-play-circle:before { - content: "\e029"; -} -.glyphicon-repeat:before { - content: "\e030"; -} -.glyphicon-refresh:before { - content: "\e031"; -} -.glyphicon-list-alt:before { - content: "\e032"; -} -.glyphicon-lock:before { - content: "\e033"; -} -.glyphicon-flag:before { - content: "\e034"; -} -.glyphicon-headphones:before { - content: "\e035"; -} -.glyphicon-volume-off:before { - content: "\e036"; -} -.glyphicon-volume-down:before { - content: "\e037"; -} -.glyphicon-volume-up:before { - content: "\e038"; -} -.glyphicon-qrcode:before { - content: "\e039"; -} -.glyphicon-barcode:before { - content: "\e040"; -} -.glyphicon-tag:before { - content: "\e041"; -} -.glyphicon-tags:before { - content: "\e042"; -} -.glyphicon-book:before { - content: "\e043"; -} -.glyphicon-bookmark:before { - content: "\e044"; -} -.glyphicon-print:before { - content: "\e045"; -} -.glyphicon-camera:before { - content: "\e046"; -} -.glyphicon-font:before { - content: "\e047"; -} -.glyphicon-bold:before { - content: "\e048"; -} -.glyphicon-italic:before { - content: "\e049"; -} -.glyphicon-text-height:before { - content: "\e050"; -} -.glyphicon-text-width:before { - content: "\e051"; -} -.glyphicon-align-left:before { - content: "\e052"; -} -.glyphicon-align-center:before { - content: "\e053"; -} -.glyphicon-align-right:before { - content: "\e054"; -} -.glyphicon-align-justify:before { - content: "\e055"; -} -.glyphicon-list:before { - content: "\e056"; -} -.glyphicon-indent-left:before { - content: "\e057"; -} -.glyphicon-indent-right:before { - content: "\e058"; -} -.glyphicon-facetime-video:before { - content: "\e059"; -} -.glyphicon-picture:before { - content: "\e060"; -} -.glyphicon-map-marker:before { - content: "\e062"; -} -.glyphicon-adjust:before { - content: "\e063"; -} -.glyphicon-tint:before { - content: "\e064"; -} -.glyphicon-edit:before { - content: "\e065"; -} -.glyphicon-share:before { - content: "\e066"; -} -.glyphicon-check:before { - content: "\e067"; -} -.glyphicon-move:before { - content: "\e068"; -} -.glyphicon-step-backward:before { - content: "\e069"; -} -.glyphicon-fast-backward:before { - content: "\e070"; -} -.glyphicon-backward:before { - content: "\e071"; -} -.glyphicon-play:before { - content: "\e072"; -} -.glyphicon-pause:before { - content: "\e073"; -} -.glyphicon-stop:before { - content: "\e074"; -} -.glyphicon-forward:before { - content: "\e075"; -} -.glyphicon-fast-forward:before { - content: "\e076"; -} -.glyphicon-step-forward:before { - content: "\e077"; -} -.glyphicon-eject:before { - content: "\e078"; -} -.glyphicon-chevron-left:before { - content: "\e079"; -} -.glyphicon-chevron-right:before { - content: "\e080"; -} -.glyphicon-plus-sign:before { - content: "\e081"; -} -.glyphicon-minus-sign:before { - content: "\e082"; -} -.glyphicon-remove-sign:before { - content: "\e083"; -} -.glyphicon-ok-sign:before { - content: "\e084"; -} -.glyphicon-question-sign:before { - content: "\e085"; -} -.glyphicon-info-sign:before { - content: "\e086"; -} -.glyphicon-screenshot:before { - content: "\e087"; -} -.glyphicon-remove-circle:before { - content: "\e088"; -} -.glyphicon-ok-circle:before { - content: "\e089"; -} -.glyphicon-ban-circle:before { - content: "\e090"; -} -.glyphicon-arrow-left:before { - content: "\e091"; -} -.glyphicon-arrow-right:before { - content: "\e092"; -} -.glyphicon-arrow-up:before { - content: "\e093"; -} -.glyphicon-arrow-down:before { - content: "\e094"; -} -.glyphicon-share-alt:before { - content: "\e095"; -} -.glyphicon-resize-full:before { - content: "\e096"; -} -.glyphicon-resize-small:before { - content: "\e097"; -} -.glyphicon-exclamation-sign:before { - content: "\e101"; -} -.glyphicon-gift:before { - content: "\e102"; -} -.glyphicon-leaf:before { - content: "\e103"; -} -.glyphicon-fire:before { - content: "\e104"; -} -.glyphicon-eye-open:before { - content: "\e105"; -} -.glyphicon-eye-close:before { - content: "\e106"; -} -.glyphicon-warning-sign:before { - content: "\e107"; -} -.glyphicon-plane:before { - content: "\e108"; -} -.glyphicon-calendar:before { - content: "\e109"; -} -.glyphicon-random:before { - content: "\e110"; -} -.glyphicon-comment:before { - content: "\e111"; -} -.glyphicon-magnet:before { - content: "\e112"; -} -.glyphicon-chevron-up:before { - content: "\e113"; -} -.glyphicon-chevron-down:before { - content: "\e114"; -} -.glyphicon-retweet:before { - content: "\e115"; -} -.glyphicon-shopping-cart:before { - content: "\e116"; -} -.glyphicon-folder-close:before { - content: "\e117"; -} -.glyphicon-folder-open:before { - content: "\e118"; -} -.glyphicon-resize-vertical:before { - content: "\e119"; -} -.glyphicon-resize-horizontal:before { - content: "\e120"; -} -.glyphicon-hdd:before { - content: "\e121"; -} -.glyphicon-bullhorn:before { - content: "\e122"; -} -.glyphicon-bell:before { - content: "\e123"; -} -.glyphicon-certificate:before { - content: "\e124"; -} -.glyphicon-thumbs-up:before { - content: "\e125"; -} -.glyphicon-thumbs-down:before { - content: "\e126"; -} -.glyphicon-hand-right:before { - content: "\e127"; -} -.glyphicon-hand-left:before { - content: "\e128"; -} -.glyphicon-hand-up:before { - content: "\e129"; -} -.glyphicon-hand-down:before { - content: "\e130"; -} -.glyphicon-circle-arrow-right:before { - content: "\e131"; -} -.glyphicon-circle-arrow-left:before { - content: "\e132"; -} -.glyphicon-circle-arrow-up:before { - content: "\e133"; -} -.glyphicon-circle-arrow-down:before { - content: "\e134"; -} -.glyphicon-globe:before { - content: "\e135"; -} -.glyphicon-wrench:before { - content: "\e136"; -} -.glyphicon-tasks:before { - content: "\e137"; -} -.glyphicon-filter:before { - content: "\e138"; -} -.glyphicon-briefcase:before { - content: "\e139"; -} -.glyphicon-fullscreen:before { - content: "\e140"; -} -.glyphicon-dashboard:before { - content: "\e141"; -} -.glyphicon-paperclip:before { - content: "\e142"; -} -.glyphicon-heart-empty:before { - content: "\e143"; -} -.glyphicon-link:before { - content: "\e144"; -} -.glyphicon-phone:before { - content: "\e145"; -} -.glyphicon-pushpin:before { - content: "\e146"; -} -.glyphicon-usd:before { - content: "\e148"; -} -.glyphicon-gbp:before { - content: "\e149"; -} -.glyphicon-sort:before { - content: "\e150"; -} -.glyphicon-sort-by-alphabet:before { - content: "\e151"; -} -.glyphicon-sort-by-alphabet-alt:before { - content: "\e152"; -} -.glyphicon-sort-by-order:before { - content: "\e153"; -} -.glyphicon-sort-by-order-alt:before { - content: "\e154"; -} -.glyphicon-sort-by-attributes:before { - content: "\e155"; -} -.glyphicon-sort-by-attributes-alt:before { - content: "\e156"; -} -.glyphicon-unchecked:before { - content: "\e157"; -} -.glyphicon-expand:before { - content: "\e158"; -} -.glyphicon-collapse-down:before { - content: "\e159"; -} -.glyphicon-collapse-up:before { - content: "\e160"; -} -.glyphicon-log-in:before { - content: "\e161"; -} -.glyphicon-flash:before { - content: "\e162"; -} -.glyphicon-log-out:before { - content: "\e163"; -} -.glyphicon-new-window:before { - content: "\e164"; -} -.glyphicon-record:before { - content: "\e165"; -} -.glyphicon-save:before { - content: "\e166"; -} -.glyphicon-open:before { - content: "\e167"; -} -.glyphicon-saved:before { - content: "\e168"; -} -.glyphicon-import:before { - content: "\e169"; -} -.glyphicon-export:before { - content: "\e170"; -} -.glyphicon-send:before { - content: "\e171"; -} -.glyphicon-floppy-disk:before { - content: "\e172"; -} -.glyphicon-floppy-saved:before { - content: "\e173"; -} -.glyphicon-floppy-remove:before { - content: "\e174"; -} -.glyphicon-floppy-save:before { - content: "\e175"; -} -.glyphicon-floppy-open:before { - content: "\e176"; -} -.glyphicon-credit-card:before { - content: "\e177"; -} -.glyphicon-transfer:before { - content: "\e178"; -} -.glyphicon-cutlery:before { - content: "\e179"; -} -.glyphicon-header:before { - content: "\e180"; -} -.glyphicon-compressed:before { - content: "\e181"; -} -.glyphicon-earphone:before { - content: "\e182"; -} -.glyphicon-phone-alt:before { - content: "\e183"; -} -.glyphicon-tower:before { - content: "\e184"; -} -.glyphicon-stats:before { - content: "\e185"; -} -.glyphicon-sd-video:before { - content: "\e186"; -} -.glyphicon-hd-video:before { - content: "\e187"; -} -.glyphicon-subtitles:before { - content: "\e188"; -} -.glyphicon-sound-stereo:before { - content: "\e189"; -} -.glyphicon-sound-dolby:before { - content: "\e190"; -} -.glyphicon-sound-5-1:before { - content: "\e191"; -} -.glyphicon-sound-6-1:before { - content: "\e192"; -} -.glyphicon-sound-7-1:before { - content: "\e193"; -} -.glyphicon-copyright-mark:before { - content: "\e194"; -} -.glyphicon-registration-mark:before { - content: "\e195"; -} -.glyphicon-cloud-download:before { - content: "\e197"; -} -.glyphicon-cloud-upload:before { - content: "\e198"; -} -.glyphicon-tree-conifer:before { - content: "\e199"; -} -.glyphicon-tree-deciduous:before { - content: "\e200"; -} -.glyphicon-cd:before { - content: "\e201"; -} -.glyphicon-save-file:before { - content: "\e202"; -} -.glyphicon-open-file:before { - content: "\e203"; -} -.glyphicon-level-up:before { - content: "\e204"; -} -.glyphicon-copy:before { - content: "\e205"; -} -.glyphicon-paste:before { - content: "\e206"; -} -.glyphicon-alert:before { - content: "\e209"; -} -.glyphicon-equalizer:before { - content: "\e210"; -} -.glyphicon-king:before { - content: "\e211"; -} -.glyphicon-queen:before { - content: "\e212"; -} -.glyphicon-pawn:before { - content: "\e213"; -} -.glyphicon-bishop:before { - content: "\e214"; -} -.glyphicon-knight:before { - content: "\e215"; -} -.glyphicon-baby-formula:before { - content: "\e216"; -} -.glyphicon-tent:before { - content: "\26fa"; -} -.glyphicon-blackboard:before { - content: "\e218"; -} -.glyphicon-bed:before { - content: "\e219"; -} -.glyphicon-apple:before { - content: "\f8ff"; -} -.glyphicon-erase:before { - content: "\e221"; -} -.glyphicon-hourglass:before { - content: "\231b"; -} -.glyphicon-lamp:before { - content: "\e223"; -} -.glyphicon-duplicate:before { - content: "\e224"; -} -.glyphicon-piggy-bank:before { - content: "\e225"; -} -.glyphicon-scissors:before { - content: "\e226"; -} -.glyphicon-bitcoin:before { - content: "\e227"; -} -.glyphicon-btc:before { - content: "\e227"; -} -.glyphicon-xbt:before { - content: "\e227"; -} -.glyphicon-yen:before { - content: "\00a5"; -} -.glyphicon-jpy:before { - content: "\00a5"; -} -.glyphicon-ruble:before { - content: "\20bd"; -} -.glyphicon-rub:before { - content: "\20bd"; -} -.glyphicon-scale:before { - content: "\e230"; -} -.glyphicon-ice-lolly:before { - content: "\e231"; -} -.glyphicon-ice-lolly-tasted:before { - content: "\e232"; -} -.glyphicon-education:before { - content: "\e233"; -} -.glyphicon-option-horizontal:before { - content: "\e234"; -} -.glyphicon-option-vertical:before { - content: "\e235"; -} -.glyphicon-menu-hamburger:before { - content: "\e236"; -} -.glyphicon-modal-window:before { - content: "\e237"; -} -.glyphicon-oil:before { - content: "\e238"; -} -.glyphicon-grain:before { - content: "\e239"; -} -.glyphicon-sunglasses:before { - content: "\e240"; -} -.glyphicon-text-size:before { - content: "\e241"; -} -.glyphicon-text-color:before { - content: "\e242"; -} -.glyphicon-text-background:before { - content: "\e243"; -} -.glyphicon-object-align-top:before { - content: "\e244"; -} -.glyphicon-object-align-bottom:before { - content: "\e245"; -} -.glyphicon-object-align-horizontal:before { - content: "\e246"; -} -.glyphicon-object-align-left:before { - content: "\e247"; -} -.glyphicon-object-align-vertical:before { - content: "\e248"; -} -.glyphicon-object-align-right:before { - content: "\e249"; -} -.glyphicon-triangle-right:before { - content: "\e250"; -} -.glyphicon-triangle-left:before { - content: "\e251"; -} -.glyphicon-triangle-bottom:before { - content: "\e252"; -} -.glyphicon-triangle-top:before { - content: "\e253"; -} -.glyphicon-console:before { - content: "\e254"; -} -.glyphicon-superscript:before { - content: "\e255"; -} -.glyphicon-subscript:before { - content: "\e256"; -} -.glyphicon-menu-left:before { - content: "\e257"; -} -.glyphicon-menu-right:before { - content: "\e258"; -} -.glyphicon-menu-down:before { - content: "\e259"; -} -.glyphicon-menu-up:before { - content: "\e260"; -} -* { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -*:before, -*:after { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -html { - font-size: 10px; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -} -body { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - line-height: 1.42857143; - color: #333333; - background-color: #fff; -} -input, -button, -select, -textarea { - font-family: inherit; - font-size: inherit; - line-height: inherit; -} -a { - color: #337ab7; - text-decoration: none; -} -a:hover, -a:focus { - color: #23527c; - text-decoration: underline; -} -a:focus { - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -figure { - margin: 0; -} -img { - vertical-align: middle; -} -.img-responsive, -.thumbnail > img, -.thumbnail a > img, -.carousel-inner > .item > img, -.carousel-inner > .item > a > img { - display: block; - max-width: 100%; - height: auto; -} -.img-rounded { - border-radius: 6px; -} -.img-thumbnail { - padding: 4px; - line-height: 1.42857143; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 4px; - -webkit-transition: all 0.2s ease-in-out; - -o-transition: all 0.2s ease-in-out; - transition: all 0.2s ease-in-out; - display: inline-block; - max-width: 100%; - height: auto; -} -.img-circle { - border-radius: 50%; -} -hr { - margin-top: 20px; - margin-bottom: 20px; - border: 0; - border-top: 1px solid #eeeeee; -} -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - border: 0; -} -.sr-only-focusable:active, -.sr-only-focusable:focus { - position: static; - width: auto; - height: auto; - margin: 0; - overflow: visible; - clip: auto; -} -[role="button"] { - cursor: pointer; -} -h1, -h2, -h3, -h4, -h5, -h6, -.h1, -.h2, -.h3, -.h4, -.h5, -.h6 { - font-family: inherit; - font-weight: 500; - line-height: 1.1; - color: inherit; -} -h1 small, -h2 small, -h3 small, -h4 small, -h5 small, -h6 small, -.h1 small, -.h2 small, -.h3 small, -.h4 small, -.h5 small, -.h6 small, -h1 .small, -h2 .small, -h3 .small, -h4 .small, -h5 .small, -h6 .small, -.h1 .small, -.h2 .small, -.h3 .small, -.h4 .small, -.h5 .small, -.h6 .small { - font-weight: 400; - line-height: 1; - color: #777777; -} -h1, -.h1, -h2, -.h2, -h3, -.h3 { - margin-top: 20px; - margin-bottom: 10px; -} -h1 small, -.h1 small, -h2 small, -.h2 small, -h3 small, -.h3 small, -h1 .small, -.h1 .small, -h2 .small, -.h2 .small, -h3 .small, -.h3 .small { - font-size: 65%; -} -h4, -.h4, -h5, -.h5, -h6, -.h6 { - margin-top: 10px; - margin-bottom: 10px; -} -h4 small, -.h4 small, -h5 small, -.h5 small, -h6 small, -.h6 small, -h4 .small, -.h4 .small, -h5 .small, -.h5 .small, -h6 .small, -.h6 .small { - font-size: 75%; -} -h1, -.h1 { - font-size: 36px; -} -h2, -.h2 { - font-size: 30px; -} -h3, -.h3 { - font-size: 24px; -} -h4, -.h4 { - font-size: 18px; -} -h5, -.h5 { - font-size: 14px; -} -h6, -.h6 { - font-size: 12px; -} -p { - margin: 0 0 10px; -} -.lead { - margin-bottom: 20px; - font-size: 16px; - font-weight: 300; - line-height: 1.4; -} -@media (min-width: 768px) { - .lead { - font-size: 21px; - } -} -small, -.small { - font-size: 85%; -} -mark, -.mark { - padding: 0.2em; - background-color: #fcf8e3; -} -.text-left { - text-align: left; -} -.text-right { - text-align: right; -} -.text-center { - text-align: center; -} -.text-justify { - text-align: justify; -} -.text-nowrap { - white-space: nowrap; -} -.text-lowercase { - text-transform: lowercase; -} -.text-uppercase { - text-transform: uppercase; -} -.text-capitalize { - text-transform: capitalize; -} -.text-muted { - color: #777777; -} -.text-primary { - color: #337ab7; -} -a.text-primary:hover, -a.text-primary:focus { - color: #286090; -} -.text-success { - color: #3c763d; -} -a.text-success:hover, -a.text-success:focus { - color: #2b542c; -} -.text-info { - color: #31708f; -} -a.text-info:hover, -a.text-info:focus { - color: #245269; -} -.text-warning { - color: #8a6d3b; -} -a.text-warning:hover, -a.text-warning:focus { - color: #66512c; -} -.text-danger { - color: #a94442; -} -a.text-danger:hover, -a.text-danger:focus { - color: #843534; -} -.bg-primary { - color: #fff; - background-color: #337ab7; -} -a.bg-primary:hover, -a.bg-primary:focus { - background-color: #286090; -} -.bg-success { - background-color: #dff0d8; -} -a.bg-success:hover, -a.bg-success:focus { - background-color: #c1e2b3; -} -.bg-info { - background-color: #d9edf7; -} -a.bg-info:hover, -a.bg-info:focus { - background-color: #afd9ee; -} -.bg-warning { - background-color: #fcf8e3; -} -a.bg-warning:hover, -a.bg-warning:focus { - background-color: #f7ecb5; -} -.bg-danger { - background-color: #f2dede; -} -a.bg-danger:hover, -a.bg-danger:focus { - background-color: #e4b9b9; -} -.page-header { - padding-bottom: 9px; - margin: 40px 0 20px; - border-bottom: 1px solid #eeeeee; -} -ul, -ol { - margin-top: 0; - margin-bottom: 10px; -} -ul ul, -ol ul, -ul ol, -ol ol { - margin-bottom: 0; -} -.list-unstyled { - padding-left: 0; - list-style: none; -} -.list-inline { - padding-left: 0; - list-style: none; - margin-left: -5px; -} -.list-inline > li { - display: inline-block; - padding-right: 5px; - padding-left: 5px; -} -dl { - margin-top: 0; - margin-bottom: 20px; -} -dt, -dd { - line-height: 1.42857143; -} -dt { - font-weight: 700; -} -dd { - margin-left: 0; -} -@media (min-width: 768px) { - .dl-horizontal dt { - float: left; - width: 160px; - clear: left; - text-align: right; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - .dl-horizontal dd { - margin-left: 180px; - } -} -abbr[title], -abbr[data-original-title] { - cursor: help; -} -.initialism { - font-size: 90%; - text-transform: uppercase; -} -blockquote { - padding: 10px 20px; - margin: 0 0 20px; - font-size: 17.5px; - border-left: 5px solid #eeeeee; -} -blockquote p:last-child, -blockquote ul:last-child, -blockquote ol:last-child { - margin-bottom: 0; -} -blockquote footer, -blockquote small, -blockquote .small { - display: block; - font-size: 80%; - line-height: 1.42857143; - color: #777777; -} -blockquote footer:before, -blockquote small:before, -blockquote .small:before { - content: "\2014 \00A0"; -} -.blockquote-reverse, -blockquote.pull-right { - padding-right: 15px; - padding-left: 0; - text-align: right; - border-right: 5px solid #eeeeee; - border-left: 0; -} -.blockquote-reverse footer:before, -blockquote.pull-right footer:before, -.blockquote-reverse small:before, -blockquote.pull-right small:before, -.blockquote-reverse .small:before, -blockquote.pull-right .small:before { - content: ""; -} -.blockquote-reverse footer:after, -blockquote.pull-right footer:after, -.blockquote-reverse small:after, -blockquote.pull-right small:after, -.blockquote-reverse .small:after, -blockquote.pull-right .small:after { - content: "\00A0 \2014"; -} -address { - margin-bottom: 20px; - font-style: normal; - line-height: 1.42857143; -} -code, -kbd, -pre, -samp { - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; -} -code { - padding: 2px 4px; - font-size: 90%; - color: #c7254e; - background-color: #f9f2f4; - border-radius: 4px; -} -kbd { - padding: 2px 4px; - font-size: 90%; - color: #fff; - background-color: #333; - border-radius: 3px; - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); -} -kbd kbd { - padding: 0; - font-size: 100%; - font-weight: 700; - -webkit-box-shadow: none; - box-shadow: none; -} -pre { - display: block; - padding: 9.5px; - margin: 0 0 10px; - font-size: 13px; - line-height: 1.42857143; - color: #333333; - word-break: break-all; - word-wrap: break-word; - background-color: #f5f5f5; - border: 1px solid #ccc; - border-radius: 4px; -} -pre code { - padding: 0; - font-size: inherit; - color: inherit; - white-space: pre-wrap; - background-color: transparent; - border-radius: 0; -} -.pre-scrollable { - max-height: 340px; - overflow-y: scroll; -} -.container { - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; -} -@media (min-width: 768px) { - .container { - width: 750px; - } -} -@media (min-width: 992px) { - .container { - width: 970px; - } -} -@media (min-width: 1200px) { - .container { - width: 1170px; - } -} -.container-fluid { - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; -} -.row { - margin-right: -15px; - margin-left: -15px; -} -.row-no-gutters { - margin-right: 0; - margin-left: 0; -} -.row-no-gutters [class*="col-"] { - padding-right: 0; - padding-left: 0; -} -.col-xs-1, -.col-sm-1, -.col-md-1, -.col-lg-1, -.col-xs-2, -.col-sm-2, -.col-md-2, -.col-lg-2, -.col-xs-3, -.col-sm-3, -.col-md-3, -.col-lg-3, -.col-xs-4, -.col-sm-4, -.col-md-4, -.col-lg-4, -.col-xs-5, -.col-sm-5, -.col-md-5, -.col-lg-5, -.col-xs-6, -.col-sm-6, -.col-md-6, -.col-lg-6, -.col-xs-7, -.col-sm-7, -.col-md-7, -.col-lg-7, -.col-xs-8, -.col-sm-8, -.col-md-8, -.col-lg-8, -.col-xs-9, -.col-sm-9, -.col-md-9, -.col-lg-9, -.col-xs-10, -.col-sm-10, -.col-md-10, -.col-lg-10, -.col-xs-11, -.col-sm-11, -.col-md-11, -.col-lg-11, -.col-xs-12, -.col-sm-12, -.col-md-12, -.col-lg-12 { - position: relative; - min-height: 1px; - padding-right: 15px; - padding-left: 15px; -} -.col-xs-1, -.col-xs-2, -.col-xs-3, -.col-xs-4, -.col-xs-5, -.col-xs-6, -.col-xs-7, -.col-xs-8, -.col-xs-9, -.col-xs-10, -.col-xs-11, -.col-xs-12 { - float: left; -} -.col-xs-12 { - width: 100%; -} -.col-xs-11 { - width: 91.66666667%; -} -.col-xs-10 { - width: 83.33333333%; -} -.col-xs-9 { - width: 75%; -} -.col-xs-8 { - width: 66.66666667%; -} -.col-xs-7 { - width: 58.33333333%; -} -.col-xs-6 { - width: 50%; -} -.col-xs-5 { - width: 41.66666667%; -} -.col-xs-4 { - width: 33.33333333%; -} -.col-xs-3 { - width: 25%; -} -.col-xs-2 { - width: 16.66666667%; -} -.col-xs-1 { - width: 8.33333333%; -} -.col-xs-pull-12 { - right: 100%; -} -.col-xs-pull-11 { - right: 91.66666667%; -} -.col-xs-pull-10 { - right: 83.33333333%; -} -.col-xs-pull-9 { - right: 75%; -} -.col-xs-pull-8 { - right: 66.66666667%; -} -.col-xs-pull-7 { - right: 58.33333333%; -} -.col-xs-pull-6 { - right: 50%; -} -.col-xs-pull-5 { - right: 41.66666667%; -} -.col-xs-pull-4 { - right: 33.33333333%; -} -.col-xs-pull-3 { - right: 25%; -} -.col-xs-pull-2 { - right: 16.66666667%; -} -.col-xs-pull-1 { - right: 8.33333333%; -} -.col-xs-pull-0 { - right: auto; -} -.col-xs-push-12 { - left: 100%; -} -.col-xs-push-11 { - left: 91.66666667%; -} -.col-xs-push-10 { - left: 83.33333333%; -} -.col-xs-push-9 { - left: 75%; -} -.col-xs-push-8 { - left: 66.66666667%; -} -.col-xs-push-7 { - left: 58.33333333%; -} -.col-xs-push-6 { - left: 50%; -} -.col-xs-push-5 { - left: 41.66666667%; -} -.col-xs-push-4 { - left: 33.33333333%; -} -.col-xs-push-3 { - left: 25%; -} -.col-xs-push-2 { - left: 16.66666667%; -} -.col-xs-push-1 { - left: 8.33333333%; -} -.col-xs-push-0 { - left: auto; -} -.col-xs-offset-12 { - margin-left: 100%; -} -.col-xs-offset-11 { - margin-left: 91.66666667%; -} -.col-xs-offset-10 { - margin-left: 83.33333333%; -} -.col-xs-offset-9 { - margin-left: 75%; -} -.col-xs-offset-8 { - margin-left: 66.66666667%; -} -.col-xs-offset-7 { - margin-left: 58.33333333%; -} -.col-xs-offset-6 { - margin-left: 50%; -} -.col-xs-offset-5 { - margin-left: 41.66666667%; -} -.col-xs-offset-4 { - margin-left: 33.33333333%; -} -.col-xs-offset-3 { - margin-left: 25%; -} -.col-xs-offset-2 { - margin-left: 16.66666667%; -} -.col-xs-offset-1 { - margin-left: 8.33333333%; -} -.col-xs-offset-0 { - margin-left: 0%; -} -@media (min-width: 768px) { - .col-sm-1, - .col-sm-2, - .col-sm-3, - .col-sm-4, - .col-sm-5, - .col-sm-6, - .col-sm-7, - .col-sm-8, - .col-sm-9, - .col-sm-10, - .col-sm-11, - .col-sm-12 { - float: left; - } - .col-sm-12 { - width: 100%; - } - .col-sm-11 { - width: 91.66666667%; - } - .col-sm-10 { - width: 83.33333333%; - } - .col-sm-9 { - width: 75%; - } - .col-sm-8 { - width: 66.66666667%; - } - .col-sm-7 { - width: 58.33333333%; - } - .col-sm-6 { - width: 50%; - } - .col-sm-5 { - width: 41.66666667%; - } - .col-sm-4 { - width: 33.33333333%; - } - .col-sm-3 { - width: 25%; - } - .col-sm-2 { - width: 16.66666667%; - } - .col-sm-1 { - width: 8.33333333%; - } - .col-sm-pull-12 { - right: 100%; - } - .col-sm-pull-11 { - right: 91.66666667%; - } - .col-sm-pull-10 { - right: 83.33333333%; - } - .col-sm-pull-9 { - right: 75%; - } - .col-sm-pull-8 { - right: 66.66666667%; - } - .col-sm-pull-7 { - right: 58.33333333%; - } - .col-sm-pull-6 { - right: 50%; - } - .col-sm-pull-5 { - right: 41.66666667%; - } - .col-sm-pull-4 { - right: 33.33333333%; - } - .col-sm-pull-3 { - right: 25%; - } - .col-sm-pull-2 { - right: 16.66666667%; - } - .col-sm-pull-1 { - right: 8.33333333%; - } - .col-sm-pull-0 { - right: auto; - } - .col-sm-push-12 { - left: 100%; - } - .col-sm-push-11 { - left: 91.66666667%; - } - .col-sm-push-10 { - left: 83.33333333%; - } - .col-sm-push-9 { - left: 75%; - } - .col-sm-push-8 { - left: 66.66666667%; - } - .col-sm-push-7 { - left: 58.33333333%; - } - .col-sm-push-6 { - left: 50%; - } - .col-sm-push-5 { - left: 41.66666667%; - } - .col-sm-push-4 { - left: 33.33333333%; - } - .col-sm-push-3 { - left: 25%; - } - .col-sm-push-2 { - left: 16.66666667%; - } - .col-sm-push-1 { - left: 8.33333333%; - } - .col-sm-push-0 { - left: auto; - } - .col-sm-offset-12 { - margin-left: 100%; - } - .col-sm-offset-11 { - margin-left: 91.66666667%; - } - .col-sm-offset-10 { - margin-left: 83.33333333%; - } - .col-sm-offset-9 { - margin-left: 75%; - } - .col-sm-offset-8 { - margin-left: 66.66666667%; - } - .col-sm-offset-7 { - margin-left: 58.33333333%; - } - .col-sm-offset-6 { - margin-left: 50%; - } - .col-sm-offset-5 { - margin-left: 41.66666667%; - } - .col-sm-offset-4 { - margin-left: 33.33333333%; - } - .col-sm-offset-3 { - margin-left: 25%; - } - .col-sm-offset-2 { - margin-left: 16.66666667%; - } - .col-sm-offset-1 { - margin-left: 8.33333333%; - } - .col-sm-offset-0 { - margin-left: 0%; - } -} -@media (min-width: 992px) { - .col-md-1, - .col-md-2, - .col-md-3, - .col-md-4, - .col-md-5, - .col-md-6, - .col-md-7, - .col-md-8, - .col-md-9, - .col-md-10, - .col-md-11, - .col-md-12 { - float: left; - } - .col-md-12 { - width: 100%; - } - .col-md-11 { - width: 91.66666667%; - } - .col-md-10 { - width: 83.33333333%; - } - .col-md-9 { - width: 75%; - } - .col-md-8 { - width: 66.66666667%; - } - .col-md-7 { - width: 58.33333333%; - } - .col-md-6 { - width: 50%; - } - .col-md-5 { - width: 41.66666667%; - } - .col-md-4 { - width: 33.33333333%; - } - .col-md-3 { - width: 25%; - } - .col-md-2 { - width: 16.66666667%; - } - .col-md-1 { - width: 8.33333333%; - } - .col-md-pull-12 { - right: 100%; - } - .col-md-pull-11 { - right: 91.66666667%; - } - .col-md-pull-10 { - right: 83.33333333%; - } - .col-md-pull-9 { - right: 75%; - } - .col-md-pull-8 { - right: 66.66666667%; - } - .col-md-pull-7 { - right: 58.33333333%; - } - .col-md-pull-6 { - right: 50%; - } - .col-md-pull-5 { - right: 41.66666667%; - } - .col-md-pull-4 { - right: 33.33333333%; - } - .col-md-pull-3 { - right: 25%; - } - .col-md-pull-2 { - right: 16.66666667%; - } - .col-md-pull-1 { - right: 8.33333333%; - } - .col-md-pull-0 { - right: auto; - } - .col-md-push-12 { - left: 100%; - } - .col-md-push-11 { - left: 91.66666667%; - } - .col-md-push-10 { - left: 83.33333333%; - } - .col-md-push-9 { - left: 75%; - } - .col-md-push-8 { - left: 66.66666667%; - } - .col-md-push-7 { - left: 58.33333333%; - } - .col-md-push-6 { - left: 50%; - } - .col-md-push-5 { - left: 41.66666667%; - } - .col-md-push-4 { - left: 33.33333333%; - } - .col-md-push-3 { - left: 25%; - } - .col-md-push-2 { - left: 16.66666667%; - } - .col-md-push-1 { - left: 8.33333333%; - } - .col-md-push-0 { - left: auto; - } - .col-md-offset-12 { - margin-left: 100%; - } - .col-md-offset-11 { - margin-left: 91.66666667%; - } - .col-md-offset-10 { - margin-left: 83.33333333%; - } - .col-md-offset-9 { - margin-left: 75%; - } - .col-md-offset-8 { - margin-left: 66.66666667%; - } - .col-md-offset-7 { - margin-left: 58.33333333%; - } - .col-md-offset-6 { - margin-left: 50%; - } - .col-md-offset-5 { - margin-left: 41.66666667%; - } - .col-md-offset-4 { - margin-left: 33.33333333%; - } - .col-md-offset-3 { - margin-left: 25%; - } - .col-md-offset-2 { - margin-left: 16.66666667%; - } - .col-md-offset-1 { - margin-left: 8.33333333%; - } - .col-md-offset-0 { - margin-left: 0%; - } -} -@media (min-width: 1200px) { - .col-lg-1, - .col-lg-2, - .col-lg-3, - .col-lg-4, - .col-lg-5, - .col-lg-6, - .col-lg-7, - .col-lg-8, - .col-lg-9, - .col-lg-10, - .col-lg-11, - .col-lg-12 { - float: left; - } - .col-lg-12 { - width: 100%; - } - .col-lg-11 { - width: 91.66666667%; - } - .col-lg-10 { - width: 83.33333333%; - } - .col-lg-9 { - width: 75%; - } - .col-lg-8 { - width: 66.66666667%; - } - .col-lg-7 { - width: 58.33333333%; - } - .col-lg-6 { - width: 50%; - } - .col-lg-5 { - width: 41.66666667%; - } - .col-lg-4 { - width: 33.33333333%; - } - .col-lg-3 { - width: 25%; - } - .col-lg-2 { - width: 16.66666667%; - } - .col-lg-1 { - width: 8.33333333%; - } - .col-lg-pull-12 { - right: 100%; - } - .col-lg-pull-11 { - right: 91.66666667%; - } - .col-lg-pull-10 { - right: 83.33333333%; - } - .col-lg-pull-9 { - right: 75%; - } - .col-lg-pull-8 { - right: 66.66666667%; - } - .col-lg-pull-7 { - right: 58.33333333%; - } - .col-lg-pull-6 { - right: 50%; - } - .col-lg-pull-5 { - right: 41.66666667%; - } - .col-lg-pull-4 { - right: 33.33333333%; - } - .col-lg-pull-3 { - right: 25%; - } - .col-lg-pull-2 { - right: 16.66666667%; - } - .col-lg-pull-1 { - right: 8.33333333%; - } - .col-lg-pull-0 { - right: auto; - } - .col-lg-push-12 { - left: 100%; - } - .col-lg-push-11 { - left: 91.66666667%; - } - .col-lg-push-10 { - left: 83.33333333%; - } - .col-lg-push-9 { - left: 75%; - } - .col-lg-push-8 { - left: 66.66666667%; - } - .col-lg-push-7 { - left: 58.33333333%; - } - .col-lg-push-6 { - left: 50%; - } - .col-lg-push-5 { - left: 41.66666667%; - } - .col-lg-push-4 { - left: 33.33333333%; - } - .col-lg-push-3 { - left: 25%; - } - .col-lg-push-2 { - left: 16.66666667%; - } - .col-lg-push-1 { - left: 8.33333333%; - } - .col-lg-push-0 { - left: auto; - } - .col-lg-offset-12 { - margin-left: 100%; - } - .col-lg-offset-11 { - margin-left: 91.66666667%; - } - .col-lg-offset-10 { - margin-left: 83.33333333%; - } - .col-lg-offset-9 { - margin-left: 75%; - } - .col-lg-offset-8 { - margin-left: 66.66666667%; - } - .col-lg-offset-7 { - margin-left: 58.33333333%; - } - .col-lg-offset-6 { - margin-left: 50%; - } - .col-lg-offset-5 { - margin-left: 41.66666667%; - } - .col-lg-offset-4 { - margin-left: 33.33333333%; - } - .col-lg-offset-3 { - margin-left: 25%; - } - .col-lg-offset-2 { - margin-left: 16.66666667%; - } - .col-lg-offset-1 { - margin-left: 8.33333333%; - } - .col-lg-offset-0 { - margin-left: 0%; - } -} -table { - background-color: transparent; -} -table col[class*="col-"] { - position: static; - display: table-column; - float: none; -} -table td[class*="col-"], -table th[class*="col-"] { - position: static; - display: table-cell; - float: none; -} -caption { - padding-top: 8px; - padding-bottom: 8px; - color: #777777; - text-align: left; -} -th { - text-align: left; -} -.table { - width: 100%; - max-width: 100%; - margin-bottom: 20px; -} -.table > thead > tr > th, -.table > tbody > tr > th, -.table > tfoot > tr > th, -.table > thead > tr > td, -.table > tbody > tr > td, -.table > tfoot > tr > td { - padding: 8px; - line-height: 1.42857143; - vertical-align: top; - border-top: 1px solid #ddd; -} -.table > thead > tr > th { - vertical-align: bottom; - border-bottom: 2px solid #ddd; -} -.table > caption + thead > tr:first-child > th, -.table > colgroup + thead > tr:first-child > th, -.table > thead:first-child > tr:first-child > th, -.table > caption + thead > tr:first-child > td, -.table > colgroup + thead > tr:first-child > td, -.table > thead:first-child > tr:first-child > td { - border-top: 0; -} -.table > tbody + tbody { - border-top: 2px solid #ddd; -} -.table .table { - background-color: #fff; -} -.table-condensed > thead > tr > th, -.table-condensed > tbody > tr > th, -.table-condensed > tfoot > tr > th, -.table-condensed > thead > tr > td, -.table-condensed > tbody > tr > td, -.table-condensed > tfoot > tr > td { - padding: 5px; -} -.table-bordered { - border: 1px solid #ddd; -} -.table-bordered > thead > tr > th, -.table-bordered > tbody > tr > th, -.table-bordered > tfoot > tr > th, -.table-bordered > thead > tr > td, -.table-bordered > tbody > tr > td, -.table-bordered > tfoot > tr > td { - border: 1px solid #ddd; -} -.table-bordered > thead > tr > th, -.table-bordered > thead > tr > td { - border-bottom-width: 2px; -} -.table-striped > tbody > tr:nth-of-type(odd) { - background-color: #f9f9f9; -} -.table-hover > tbody > tr:hover { - background-color: #f5f5f5; -} -.table > thead > tr > td.active, -.table > tbody > tr > td.active, -.table > tfoot > tr > td.active, -.table > thead > tr > th.active, -.table > tbody > tr > th.active, -.table > tfoot > tr > th.active, -.table > thead > tr.active > td, -.table > tbody > tr.active > td, -.table > tfoot > tr.active > td, -.table > thead > tr.active > th, -.table > tbody > tr.active > th, -.table > tfoot > tr.active > th { - background-color: #f5f5f5; -} -.table-hover > tbody > tr > td.active:hover, -.table-hover > tbody > tr > th.active:hover, -.table-hover > tbody > tr.active:hover > td, -.table-hover > tbody > tr:hover > .active, -.table-hover > tbody > tr.active:hover > th { - background-color: #e8e8e8; -} -.table > thead > tr > td.success, -.table > tbody > tr > td.success, -.table > tfoot > tr > td.success, -.table > thead > tr > th.success, -.table > tbody > tr > th.success, -.table > tfoot > tr > th.success, -.table > thead > tr.success > td, -.table > tbody > tr.success > td, -.table > tfoot > tr.success > td, -.table > thead > tr.success > th, -.table > tbody > tr.success > th, -.table > tfoot > tr.success > th { - background-color: #dff0d8; -} -.table-hover > tbody > tr > td.success:hover, -.table-hover > tbody > tr > th.success:hover, -.table-hover > tbody > tr.success:hover > td, -.table-hover > tbody > tr:hover > .success, -.table-hover > tbody > tr.success:hover > th { - background-color: #d0e9c6; -} -.table > thead > tr > td.info, -.table > tbody > tr > td.info, -.table > tfoot > tr > td.info, -.table > thead > tr > th.info, -.table > tbody > tr > th.info, -.table > tfoot > tr > th.info, -.table > thead > tr.info > td, -.table > tbody > tr.info > td, -.table > tfoot > tr.info > td, -.table > thead > tr.info > th, -.table > tbody > tr.info > th, -.table > tfoot > tr.info > th { - background-color: #d9edf7; -} -.table-hover > tbody > tr > td.info:hover, -.table-hover > tbody > tr > th.info:hover, -.table-hover > tbody > tr.info:hover > td, -.table-hover > tbody > tr:hover > .info, -.table-hover > tbody > tr.info:hover > th { - background-color: #c4e3f3; -} -.table > thead > tr > td.warning, -.table > tbody > tr > td.warning, -.table > tfoot > tr > td.warning, -.table > thead > tr > th.warning, -.table > tbody > tr > th.warning, -.table > tfoot > tr > th.warning, -.table > thead > tr.warning > td, -.table > tbody > tr.warning > td, -.table > tfoot > tr.warning > td, -.table > thead > tr.warning > th, -.table > tbody > tr.warning > th, -.table > tfoot > tr.warning > th { - background-color: #fcf8e3; -} -.table-hover > tbody > tr > td.warning:hover, -.table-hover > tbody > tr > th.warning:hover, -.table-hover > tbody > tr.warning:hover > td, -.table-hover > tbody > tr:hover > .warning, -.table-hover > tbody > tr.warning:hover > th { - background-color: #faf2cc; -} -.table > thead > tr > td.danger, -.table > tbody > tr > td.danger, -.table > tfoot > tr > td.danger, -.table > thead > tr > th.danger, -.table > tbody > tr > th.danger, -.table > tfoot > tr > th.danger, -.table > thead > tr.danger > td, -.table > tbody > tr.danger > td, -.table > tfoot > tr.danger > td, -.table > thead > tr.danger > th, -.table > tbody > tr.danger > th, -.table > tfoot > tr.danger > th { - background-color: #f2dede; -} -.table-hover > tbody > tr > td.danger:hover, -.table-hover > tbody > tr > th.danger:hover, -.table-hover > tbody > tr.danger:hover > td, -.table-hover > tbody > tr:hover > .danger, -.table-hover > tbody > tr.danger:hover > th { - background-color: #ebcccc; -} -.table-responsive { - min-height: 0.01%; - overflow-x: auto; -} -@media screen and (max-width: 767px) { - .table-responsive { - width: 100%; - margin-bottom: 15px; - overflow-y: hidden; - -ms-overflow-style: -ms-autohiding-scrollbar; - border: 1px solid #ddd; - } - .table-responsive > .table { - margin-bottom: 0; - } - .table-responsive > .table > thead > tr > th, - .table-responsive > .table > tbody > tr > th, - .table-responsive > .table > tfoot > tr > th, - .table-responsive > .table > thead > tr > td, - .table-responsive > .table > tbody > tr > td, - .table-responsive > .table > tfoot > tr > td { - white-space: nowrap; - } - .table-responsive > .table-bordered { - border: 0; - } - .table-responsive > .table-bordered > thead > tr > th:first-child, - .table-responsive > .table-bordered > tbody > tr > th:first-child, - .table-responsive > .table-bordered > tfoot > tr > th:first-child, - .table-responsive > .table-bordered > thead > tr > td:first-child, - .table-responsive > .table-bordered > tbody > tr > td:first-child, - .table-responsive > .table-bordered > tfoot > tr > td:first-child { - border-left: 0; - } - .table-responsive > .table-bordered > thead > tr > th:last-child, - .table-responsive > .table-bordered > tbody > tr > th:last-child, - .table-responsive > .table-bordered > tfoot > tr > th:last-child, - .table-responsive > .table-bordered > thead > tr > td:last-child, - .table-responsive > .table-bordered > tbody > tr > td:last-child, - .table-responsive > .table-bordered > tfoot > tr > td:last-child { - border-right: 0; - } - .table-responsive > .table-bordered > tbody > tr:last-child > th, - .table-responsive > .table-bordered > tfoot > tr:last-child > th, - .table-responsive > .table-bordered > tbody > tr:last-child > td, - .table-responsive > .table-bordered > tfoot > tr:last-child > td { - border-bottom: 0; - } -} -fieldset { - min-width: 0; - padding: 0; - margin: 0; - border: 0; -} -legend { - display: block; - width: 100%; - padding: 0; - margin-bottom: 20px; - font-size: 21px; - line-height: inherit; - color: #333333; - border: 0; - border-bottom: 1px solid #e5e5e5; -} -label { - display: inline-block; - max-width: 100%; - margin-bottom: 5px; - font-weight: 700; -} -input[type="search"] { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; -} -input[type="radio"], -input[type="checkbox"] { - margin: 4px 0 0; - margin-top: 1px \9; - line-height: normal; -} -input[type="radio"][disabled], -input[type="checkbox"][disabled], -input[type="radio"].disabled, -input[type="checkbox"].disabled, -fieldset[disabled] input[type="radio"], -fieldset[disabled] input[type="checkbox"] { - cursor: not-allowed; -} -input[type="file"] { - display: block; -} -input[type="range"] { - display: block; - width: 100%; -} -select[multiple], -select[size] { - height: auto; -} -input[type="file"]:focus, -input[type="radio"]:focus, -input[type="checkbox"]:focus { - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -output { - display: block; - padding-top: 7px; - font-size: 14px; - line-height: 1.42857143; - color: #555555; -} -.form-control { - display: block; - width: 100%; - height: 34px; - padding: 6px 12px; - font-size: 14px; - line-height: 1.42857143; - color: #555555; - background-color: #fff; - background-image: none; - border: 1px solid #ccc; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; - -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; - -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; - transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; - transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; - transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; -} -.form-control:focus { - border-color: #66afe9; - outline: 0; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.6); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.6); -} -.form-control::-moz-placeholder { - color: #999; - opacity: 1; -} -.form-control:-ms-input-placeholder { - color: #999; -} -.form-control::-webkit-input-placeholder { - color: #999; -} -.form-control::-ms-expand { - background-color: transparent; - border: 0; -} -.form-control[disabled], -.form-control[readonly], -fieldset[disabled] .form-control { - background-color: #eeeeee; - opacity: 1; -} -.form-control[disabled], -fieldset[disabled] .form-control { - cursor: not-allowed; -} -textarea.form-control { - height: auto; -} -@media screen and (-webkit-min-device-pixel-ratio: 0) { - input[type="date"].form-control, - input[type="time"].form-control, - input[type="datetime-local"].form-control, - input[type="month"].form-control { - line-height: 34px; - } - input[type="date"].input-sm, - input[type="time"].input-sm, - input[type="datetime-local"].input-sm, - input[type="month"].input-sm, - .input-group-sm input[type="date"], - .input-group-sm input[type="time"], - .input-group-sm input[type="datetime-local"], - .input-group-sm input[type="month"] { - line-height: 30px; - } - input[type="date"].input-lg, - input[type="time"].input-lg, - input[type="datetime-local"].input-lg, - input[type="month"].input-lg, - .input-group-lg input[type="date"], - .input-group-lg input[type="time"], - .input-group-lg input[type="datetime-local"], - .input-group-lg input[type="month"] { - line-height: 46px; - } -} -.form-group { - margin-bottom: 15px; -} -.radio, -.checkbox { - position: relative; - display: block; - margin-top: 10px; - margin-bottom: 10px; -} -.radio.disabled label, -.checkbox.disabled label, -fieldset[disabled] .radio label, -fieldset[disabled] .checkbox label { - cursor: not-allowed; -} -.radio label, -.checkbox label { - min-height: 20px; - padding-left: 20px; - margin-bottom: 0; - font-weight: 400; - cursor: pointer; -} -.radio input[type="radio"], -.radio-inline input[type="radio"], -.checkbox input[type="checkbox"], -.checkbox-inline input[type="checkbox"] { - position: absolute; - margin-top: 4px \9; - margin-left: -20px; -} -.radio + .radio, -.checkbox + .checkbox { - margin-top: -5px; -} -.radio-inline, -.checkbox-inline { - position: relative; - display: inline-block; - padding-left: 20px; - margin-bottom: 0; - font-weight: 400; - vertical-align: middle; - cursor: pointer; -} -.radio-inline.disabled, -.checkbox-inline.disabled, -fieldset[disabled] .radio-inline, -fieldset[disabled] .checkbox-inline { - cursor: not-allowed; -} -.radio-inline + .radio-inline, -.checkbox-inline + .checkbox-inline { - margin-top: 0; - margin-left: 10px; -} -.form-control-static { - min-height: 34px; - padding-top: 7px; - padding-bottom: 7px; - margin-bottom: 0; -} -.form-control-static.input-lg, -.form-control-static.input-sm { - padding-right: 0; - padding-left: 0; -} -.input-sm { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -select.input-sm { - height: 30px; - line-height: 30px; -} -textarea.input-sm, -select[multiple].input-sm { - height: auto; -} -.form-group-sm .form-control { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -.form-group-sm select.form-control { - height: 30px; - line-height: 30px; -} -.form-group-sm textarea.form-control, -.form-group-sm select[multiple].form-control { - height: auto; -} -.form-group-sm .form-control-static { - height: 30px; - min-height: 32px; - padding: 6px 10px; - font-size: 12px; - line-height: 1.5; -} -.input-lg { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px; -} -select.input-lg { - height: 46px; - line-height: 46px; -} -textarea.input-lg, -select[multiple].input-lg { - height: auto; -} -.form-group-lg .form-control { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px; -} -.form-group-lg select.form-control { - height: 46px; - line-height: 46px; -} -.form-group-lg textarea.form-control, -.form-group-lg select[multiple].form-control { - height: auto; -} -.form-group-lg .form-control-static { - height: 46px; - min-height: 38px; - padding: 11px 16px; - font-size: 18px; - line-height: 1.3333333; -} -.has-feedback { - position: relative; -} -.has-feedback .form-control { - padding-right: 42.5px; -} -.form-control-feedback { - position: absolute; - top: 0; - right: 0; - z-index: 2; - display: block; - width: 34px; - height: 34px; - line-height: 34px; - text-align: center; - pointer-events: none; -} -.input-lg + .form-control-feedback, -.input-group-lg + .form-control-feedback, -.form-group-lg .form-control + .form-control-feedback { - width: 46px; - height: 46px; - line-height: 46px; -} -.input-sm + .form-control-feedback, -.input-group-sm + .form-control-feedback, -.form-group-sm .form-control + .form-control-feedback { - width: 30px; - height: 30px; - line-height: 30px; -} -.has-success .help-block, -.has-success .control-label, -.has-success .radio, -.has-success .checkbox, -.has-success .radio-inline, -.has-success .checkbox-inline, -.has-success.radio label, -.has-success.checkbox label, -.has-success.radio-inline label, -.has-success.checkbox-inline label { - color: #3c763d; -} -.has-success .form-control { - border-color: #3c763d; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} -.has-success .form-control:focus { - border-color: #2b542c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; -} -.has-success .input-group-addon { - color: #3c763d; - background-color: #dff0d8; - border-color: #3c763d; -} -.has-success .form-control-feedback { - color: #3c763d; -} -.has-warning .help-block, -.has-warning .control-label, -.has-warning .radio, -.has-warning .checkbox, -.has-warning .radio-inline, -.has-warning .checkbox-inline, -.has-warning.radio label, -.has-warning.checkbox label, -.has-warning.radio-inline label, -.has-warning.checkbox-inline label { - color: #8a6d3b; -} -.has-warning .form-control { - border-color: #8a6d3b; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} -.has-warning .form-control:focus { - border-color: #66512c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; -} -.has-warning .input-group-addon { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #8a6d3b; -} -.has-warning .form-control-feedback { - color: #8a6d3b; -} -.has-error .help-block, -.has-error .control-label, -.has-error .radio, -.has-error .checkbox, -.has-error .radio-inline, -.has-error .checkbox-inline, -.has-error.radio label, -.has-error.checkbox label, -.has-error.radio-inline label, -.has-error.checkbox-inline label { - color: #a94442; -} -.has-error .form-control { - border-color: #a94442; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} -.has-error .form-control:focus { - border-color: #843534; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; -} -.has-error .input-group-addon { - color: #a94442; - background-color: #f2dede; - border-color: #a94442; -} -.has-error .form-control-feedback { - color: #a94442; -} -.has-feedback label ~ .form-control-feedback { - top: 25px; -} -.has-feedback label.sr-only ~ .form-control-feedback { - top: 0; -} -.help-block { - display: block; - margin-top: 5px; - margin-bottom: 10px; - color: #737373; -} -@media (min-width: 768px) { - .form-inline .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle; - } - .form-inline .form-control { - display: inline-block; - width: auto; - vertical-align: middle; - } - .form-inline .form-control-static { - display: inline-block; - } - .form-inline .input-group { - display: inline-table; - vertical-align: middle; - } - .form-inline .input-group .input-group-addon, - .form-inline .input-group .input-group-btn, - .form-inline .input-group .form-control { - width: auto; - } - .form-inline .input-group > .form-control { - width: 100%; - } - .form-inline .control-label { - margin-bottom: 0; - vertical-align: middle; - } - .form-inline .radio, - .form-inline .checkbox { - display: inline-block; - margin-top: 0; - margin-bottom: 0; - vertical-align: middle; - } - .form-inline .radio label, - .form-inline .checkbox label { - padding-left: 0; - } - .form-inline .radio input[type="radio"], - .form-inline .checkbox input[type="checkbox"] { - position: relative; - margin-left: 0; - } - .form-inline .has-feedback .form-control-feedback { - top: 0; - } -} -.form-horizontal .radio, -.form-horizontal .checkbox, -.form-horizontal .radio-inline, -.form-horizontal .checkbox-inline { - padding-top: 7px; - margin-top: 0; - margin-bottom: 0; -} -.form-horizontal .radio, -.form-horizontal .checkbox { - min-height: 27px; -} -.form-horizontal .form-group { - margin-right: -15px; - margin-left: -15px; -} -@media (min-width: 768px) { - .form-horizontal .control-label { - padding-top: 7px; - margin-bottom: 0; - text-align: right; - } -} -.form-horizontal .has-feedback .form-control-feedback { - right: 15px; -} -@media (min-width: 768px) { - .form-horizontal .form-group-lg .control-label { - padding-top: 11px; - font-size: 18px; - } -} -@media (min-width: 768px) { - .form-horizontal .form-group-sm .control-label { - padding-top: 6px; - font-size: 12px; - } -} -.btn { - display: inline-block; - margin-bottom: 0; - font-weight: normal; - text-align: center; - white-space: nowrap; - vertical-align: middle; - -ms-touch-action: manipulation; - touch-action: manipulation; - cursor: pointer; - background-image: none; - border: 1px solid transparent; - padding: 6px 12px; - font-size: 14px; - line-height: 1.42857143; - border-radius: 4px; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} -.btn:focus, -.btn:active:focus, -.btn.active:focus, -.btn.focus, -.btn:active.focus, -.btn.active.focus { - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -.btn:hover, -.btn:focus, -.btn.focus { - color: #333; - text-decoration: none; -} -.btn:active, -.btn.active { - background-image: none; - outline: 0; - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); -} -.btn.disabled, -.btn[disabled], -fieldset[disabled] .btn { - cursor: not-allowed; - filter: alpha(opacity=65); - opacity: 0.65; - -webkit-box-shadow: none; - box-shadow: none; -} -a.btn.disabled, -fieldset[disabled] a.btn { - pointer-events: none; -} -.btn-default { - color: #333; - background-color: #fff; - border-color: #ccc; -} -.btn-default:focus, -.btn-default.focus { - color: #333; - background-color: #e6e6e6; - border-color: #8c8c8c; -} -.btn-default:hover { - color: #333; - background-color: #e6e6e6; - border-color: #adadad; -} -.btn-default:active, -.btn-default.active, -.open > .dropdown-toggle.btn-default { - color: #333; - background-color: #e6e6e6; - background-image: none; - border-color: #adadad; -} -.btn-default:active:hover, -.btn-default.active:hover, -.open > .dropdown-toggle.btn-default:hover, -.btn-default:active:focus, -.btn-default.active:focus, -.open > .dropdown-toggle.btn-default:focus, -.btn-default:active.focus, -.btn-default.active.focus, -.open > .dropdown-toggle.btn-default.focus { - color: #333; - background-color: #d4d4d4; - border-color: #8c8c8c; -} -.btn-default.disabled:hover, -.btn-default[disabled]:hover, -fieldset[disabled] .btn-default:hover, -.btn-default.disabled:focus, -.btn-default[disabled]:focus, -fieldset[disabled] .btn-default:focus, -.btn-default.disabled.focus, -.btn-default[disabled].focus, -fieldset[disabled] .btn-default.focus { - background-color: #fff; - border-color: #ccc; -} -.btn-default .badge { - color: #fff; - background-color: #333; -} -.btn-primary { - color: #fff; - background-color: #337ab7; - border-color: #2e6da4; -} -.btn-primary:focus, -.btn-primary.focus { - color: #fff; - background-color: #286090; - border-color: #122b40; -} -.btn-primary:hover { - color: #fff; - background-color: #286090; - border-color: #204d74; -} -.btn-primary:active, -.btn-primary.active, -.open > .dropdown-toggle.btn-primary { - color: #fff; - background-color: #286090; - background-image: none; - border-color: #204d74; -} -.btn-primary:active:hover, -.btn-primary.active:hover, -.open > .dropdown-toggle.btn-primary:hover, -.btn-primary:active:focus, -.btn-primary.active:focus, -.open > .dropdown-toggle.btn-primary:focus, -.btn-primary:active.focus, -.btn-primary.active.focus, -.open > .dropdown-toggle.btn-primary.focus { - color: #fff; - background-color: #204d74; - border-color: #122b40; -} -.btn-primary.disabled:hover, -.btn-primary[disabled]:hover, -fieldset[disabled] .btn-primary:hover, -.btn-primary.disabled:focus, -.btn-primary[disabled]:focus, -fieldset[disabled] .btn-primary:focus, -.btn-primary.disabled.focus, -.btn-primary[disabled].focus, -fieldset[disabled] .btn-primary.focus { - background-color: #337ab7; - border-color: #2e6da4; -} -.btn-primary .badge { - color: #337ab7; - background-color: #fff; -} -.btn-success { - color: #fff; - background-color: #5cb85c; - border-color: #4cae4c; -} -.btn-success:focus, -.btn-success.focus { - color: #fff; - background-color: #449d44; - border-color: #255625; -} -.btn-success:hover { - color: #fff; - background-color: #449d44; - border-color: #398439; -} -.btn-success:active, -.btn-success.active, -.open > .dropdown-toggle.btn-success { - color: #fff; - background-color: #449d44; - background-image: none; - border-color: #398439; -} -.btn-success:active:hover, -.btn-success.active:hover, -.open > .dropdown-toggle.btn-success:hover, -.btn-success:active:focus, -.btn-success.active:focus, -.open > .dropdown-toggle.btn-success:focus, -.btn-success:active.focus, -.btn-success.active.focus, -.open > .dropdown-toggle.btn-success.focus { - color: #fff; - background-color: #398439; - border-color: #255625; -} -.btn-success.disabled:hover, -.btn-success[disabled]:hover, -fieldset[disabled] .btn-success:hover, -.btn-success.disabled:focus, -.btn-success[disabled]:focus, -fieldset[disabled] .btn-success:focus, -.btn-success.disabled.focus, -.btn-success[disabled].focus, -fieldset[disabled] .btn-success.focus { - background-color: #5cb85c; - border-color: #4cae4c; -} -.btn-success .badge { - color: #5cb85c; - background-color: #fff; -} -.btn-info { - color: #fff; - background-color: #5bc0de; - border-color: #46b8da; -} -.btn-info:focus, -.btn-info.focus { - color: #fff; - background-color: #31b0d5; - border-color: #1b6d85; -} -.btn-info:hover { - color: #fff; - background-color: #31b0d5; - border-color: #269abc; -} -.btn-info:active, -.btn-info.active, -.open > .dropdown-toggle.btn-info { - color: #fff; - background-color: #31b0d5; - background-image: none; - border-color: #269abc; -} -.btn-info:active:hover, -.btn-info.active:hover, -.open > .dropdown-toggle.btn-info:hover, -.btn-info:active:focus, -.btn-info.active:focus, -.open > .dropdown-toggle.btn-info:focus, -.btn-info:active.focus, -.btn-info.active.focus, -.open > .dropdown-toggle.btn-info.focus { - color: #fff; - background-color: #269abc; - border-color: #1b6d85; -} -.btn-info.disabled:hover, -.btn-info[disabled]:hover, -fieldset[disabled] .btn-info:hover, -.btn-info.disabled:focus, -.btn-info[disabled]:focus, -fieldset[disabled] .btn-info:focus, -.btn-info.disabled.focus, -.btn-info[disabled].focus, -fieldset[disabled] .btn-info.focus { - background-color: #5bc0de; - border-color: #46b8da; -} -.btn-info .badge { - color: #5bc0de; - background-color: #fff; -} -.btn-warning { - color: #fff; - background-color: #f0ad4e; - border-color: #eea236; -} -.btn-warning:focus, -.btn-warning.focus { - color: #fff; - background-color: #ec971f; - border-color: #985f0d; -} -.btn-warning:hover { - color: #fff; - background-color: #ec971f; - border-color: #d58512; -} -.btn-warning:active, -.btn-warning.active, -.open > .dropdown-toggle.btn-warning { - color: #fff; - background-color: #ec971f; - background-image: none; - border-color: #d58512; -} -.btn-warning:active:hover, -.btn-warning.active:hover, -.open > .dropdown-toggle.btn-warning:hover, -.btn-warning:active:focus, -.btn-warning.active:focus, -.open > .dropdown-toggle.btn-warning:focus, -.btn-warning:active.focus, -.btn-warning.active.focus, -.open > .dropdown-toggle.btn-warning.focus { - color: #fff; - background-color: #d58512; - border-color: #985f0d; -} -.btn-warning.disabled:hover, -.btn-warning[disabled]:hover, -fieldset[disabled] .btn-warning:hover, -.btn-warning.disabled:focus, -.btn-warning[disabled]:focus, -fieldset[disabled] .btn-warning:focus, -.btn-warning.disabled.focus, -.btn-warning[disabled].focus, -fieldset[disabled] .btn-warning.focus { - background-color: #f0ad4e; - border-color: #eea236; -} -.btn-warning .badge { - color: #f0ad4e; - background-color: #fff; -} -.btn-danger { - color: #fff; - background-color: #d9534f; - border-color: #d43f3a; -} -.btn-danger:focus, -.btn-danger.focus { - color: #fff; - background-color: #c9302c; - border-color: #761c19; -} -.btn-danger:hover { - color: #fff; - background-color: #c9302c; - border-color: #ac2925; -} -.btn-danger:active, -.btn-danger.active, -.open > .dropdown-toggle.btn-danger { - color: #fff; - background-color: #c9302c; - background-image: none; - border-color: #ac2925; -} -.btn-danger:active:hover, -.btn-danger.active:hover, -.open > .dropdown-toggle.btn-danger:hover, -.btn-danger:active:focus, -.btn-danger.active:focus, -.open > .dropdown-toggle.btn-danger:focus, -.btn-danger:active.focus, -.btn-danger.active.focus, -.open > .dropdown-toggle.btn-danger.focus { - color: #fff; - background-color: #ac2925; - border-color: #761c19; -} -.btn-danger.disabled:hover, -.btn-danger[disabled]:hover, -fieldset[disabled] .btn-danger:hover, -.btn-danger.disabled:focus, -.btn-danger[disabled]:focus, -fieldset[disabled] .btn-danger:focus, -.btn-danger.disabled.focus, -.btn-danger[disabled].focus, -fieldset[disabled] .btn-danger.focus { - background-color: #d9534f; - border-color: #d43f3a; -} -.btn-danger .badge { - color: #d9534f; - background-color: #fff; -} -.btn-link { - font-weight: 400; - color: #337ab7; - border-radius: 0; -} -.btn-link, -.btn-link:active, -.btn-link.active, -.btn-link[disabled], -fieldset[disabled] .btn-link { - background-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; -} -.btn-link, -.btn-link:hover, -.btn-link:focus, -.btn-link:active { - border-color: transparent; -} -.btn-link:hover, -.btn-link:focus { - color: #23527c; - text-decoration: underline; - background-color: transparent; -} -.btn-link[disabled]:hover, -fieldset[disabled] .btn-link:hover, -.btn-link[disabled]:focus, -fieldset[disabled] .btn-link:focus { - color: #777777; - text-decoration: none; -} -.btn-lg, -.btn-group-lg > .btn { - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px; -} -.btn-sm, -.btn-group-sm > .btn { - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -.btn-xs, -.btn-group-xs > .btn { - padding: 1px 5px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -.btn-block { - display: block; - width: 100%; -} -.btn-block + .btn-block { - margin-top: 5px; -} -input[type="submit"].btn-block, -input[type="reset"].btn-block, -input[type="button"].btn-block { - width: 100%; -} -.fade { - opacity: 0; - -webkit-transition: opacity 0.15s linear; - -o-transition: opacity 0.15s linear; - transition: opacity 0.15s linear; -} -.fade.in { - opacity: 1; -} -.collapse { - display: none; -} -.collapse.in { - display: block; -} -tr.collapse.in { - display: table-row; -} -tbody.collapse.in { - display: table-row-group; -} -.collapsing { - position: relative; - height: 0; - overflow: hidden; - -webkit-transition-property: height, visibility; - -o-transition-property: height, visibility; - transition-property: height, visibility; - -webkit-transition-duration: 0.35s; - -o-transition-duration: 0.35s; - transition-duration: 0.35s; - -webkit-transition-timing-function: ease; - -o-transition-timing-function: ease; - transition-timing-function: ease; -} -.caret { - display: inline-block; - width: 0; - height: 0; - margin-left: 2px; - vertical-align: middle; - border-top: 4px dashed; - border-top: 4px solid \9; - border-right: 4px solid transparent; - border-left: 4px solid transparent; -} -.dropup, -.dropdown { - position: relative; -} -.dropdown-toggle:focus { - outline: 0; -} -.dropdown-menu { - position: absolute; - top: 100%; - left: 0; - z-index: 1000; - display: none; - float: left; - min-width: 160px; - padding: 5px 0; - margin: 2px 0 0; - font-size: 14px; - text-align: left; - list-style: none; - background-color: #fff; - background-clip: padding-box; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.15); - border-radius: 4px; - -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); - box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); -} -.dropdown-menu.pull-right { - right: 0; - left: auto; -} -.dropdown-menu .divider { - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5; -} -.dropdown-menu > li > a { - display: block; - padding: 3px 20px; - clear: both; - font-weight: 400; - line-height: 1.42857143; - color: #333333; - white-space: nowrap; -} -.dropdown-menu > li > a:hover, -.dropdown-menu > li > a:focus { - color: #262626; - text-decoration: none; - background-color: #f5f5f5; -} -.dropdown-menu > .active > a, -.dropdown-menu > .active > a:hover, -.dropdown-menu > .active > a:focus { - color: #fff; - text-decoration: none; - background-color: #337ab7; - outline: 0; -} -.dropdown-menu > .disabled > a, -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - color: #777777; -} -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - text-decoration: none; - cursor: not-allowed; - background-color: transparent; - background-image: none; - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); -} -.open > .dropdown-menu { - display: block; -} -.open > a { - outline: 0; -} -.dropdown-menu-right { - right: 0; - left: auto; -} -.dropdown-menu-left { - right: auto; - left: 0; -} -.dropdown-header { - display: block; - padding: 3px 20px; - font-size: 12px; - line-height: 1.42857143; - color: #777777; - white-space: nowrap; -} -.dropdown-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 990; -} -.pull-right > .dropdown-menu { - right: 0; - left: auto; -} -.dropup .caret, -.navbar-fixed-bottom .dropdown .caret { - content: ""; - border-top: 0; - border-bottom: 4px dashed; - border-bottom: 4px solid \9; -} -.dropup .dropdown-menu, -.navbar-fixed-bottom .dropdown .dropdown-menu { - top: auto; - bottom: 100%; - margin-bottom: 2px; -} -@media (min-width: 768px) { - .navbar-right .dropdown-menu { - right: 0; - left: auto; - } - .navbar-right .dropdown-menu-left { - right: auto; - left: 0; - } -} -.btn-group, -.btn-group-vertical { - position: relative; - display: inline-block; - vertical-align: middle; -} -.btn-group > .btn, -.btn-group-vertical > .btn { - position: relative; - float: left; -} -.btn-group > .btn:hover, -.btn-group-vertical > .btn:hover, -.btn-group > .btn:focus, -.btn-group-vertical > .btn:focus, -.btn-group > .btn:active, -.btn-group-vertical > .btn:active, -.btn-group > .btn.active, -.btn-group-vertical > .btn.active { - z-index: 2; -} -.btn-group .btn + .btn, -.btn-group .btn + .btn-group, -.btn-group .btn-group + .btn, -.btn-group .btn-group + .btn-group { - margin-left: -1px; -} -.btn-toolbar { - margin-left: -5px; -} -.btn-toolbar .btn, -.btn-toolbar .btn-group, -.btn-toolbar .input-group { - float: left; -} -.btn-toolbar > .btn, -.btn-toolbar > .btn-group, -.btn-toolbar > .input-group { - margin-left: 5px; -} -.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { - border-radius: 0; -} -.btn-group > .btn:first-child { - margin-left: 0; -} -.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} -.btn-group > .btn:last-child:not(:first-child), -.btn-group > .dropdown-toggle:not(:first-child) { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} -.btn-group > .btn-group { - float: left; -} -.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { - border-radius: 0; -} -.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, -.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} -.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} -.btn-group .dropdown-toggle:active, -.btn-group.open .dropdown-toggle { - outline: 0; -} -.btn-group > .btn + .dropdown-toggle { - padding-right: 8px; - padding-left: 8px; -} -.btn-group > .btn-lg + .dropdown-toggle { - padding-right: 12px; - padding-left: 12px; -} -.btn-group.open .dropdown-toggle { - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); -} -.btn-group.open .dropdown-toggle.btn-link { - -webkit-box-shadow: none; - box-shadow: none; -} -.btn .caret { - margin-left: 0; -} -.btn-lg .caret { - border-width: 5px 5px 0; - border-bottom-width: 0; -} -.dropup .btn-lg .caret { - border-width: 0 5px 5px; -} -.btn-group-vertical > .btn, -.btn-group-vertical > .btn-group, -.btn-group-vertical > .btn-group > .btn { - display: block; - float: none; - width: 100%; - max-width: 100%; -} -.btn-group-vertical > .btn-group > .btn { - float: none; -} -.btn-group-vertical > .btn + .btn, -.btn-group-vertical > .btn + .btn-group, -.btn-group-vertical > .btn-group + .btn, -.btn-group-vertical > .btn-group + .btn-group { - margin-top: -1px; - margin-left: 0; -} -.btn-group-vertical > .btn:not(:first-child):not(:last-child) { - border-radius: 0; -} -.btn-group-vertical > .btn:first-child:not(:last-child) { - border-top-left-radius: 4px; - border-top-right-radius: 4px; - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} -.btn-group-vertical > .btn:last-child:not(:first-child) { - border-top-left-radius: 0; - border-top-right-radius: 0; - border-bottom-right-radius: 4px; - border-bottom-left-radius: 4px; -} -.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { - border-radius: 0; -} -.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, -.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} -.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { - border-top-left-radius: 0; - border-top-right-radius: 0; -} -.btn-group-justified { - display: table; - width: 100%; - table-layout: fixed; - border-collapse: separate; -} -.btn-group-justified > .btn, -.btn-group-justified > .btn-group { - display: table-cell; - float: none; - width: 1%; -} -.btn-group-justified > .btn-group .btn { - width: 100%; -} -.btn-group-justified > .btn-group .dropdown-menu { - left: auto; -} -[data-toggle="buttons"] > .btn input[type="radio"], -[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], -[data-toggle="buttons"] > .btn input[type="checkbox"], -[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { - position: absolute; - clip: rect(0, 0, 0, 0); - pointer-events: none; -} -.input-group { - position: relative; - display: table; - border-collapse: separate; -} -.input-group[class*="col-"] { - float: none; - padding-right: 0; - padding-left: 0; -} -.input-group .form-control { - position: relative; - z-index: 2; - float: left; - width: 100%; - margin-bottom: 0; -} -.input-group .form-control:focus { - z-index: 3; -} -.input-group-lg > .form-control, -.input-group-lg > .input-group-addon, -.input-group-lg > .input-group-btn > .btn { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px; -} -select.input-group-lg > .form-control, -select.input-group-lg > .input-group-addon, -select.input-group-lg > .input-group-btn > .btn { - height: 46px; - line-height: 46px; -} -textarea.input-group-lg > .form-control, -textarea.input-group-lg > .input-group-addon, -textarea.input-group-lg > .input-group-btn > .btn, -select[multiple].input-group-lg > .form-control, -select[multiple].input-group-lg > .input-group-addon, -select[multiple].input-group-lg > .input-group-btn > .btn { - height: auto; -} -.input-group-sm > .form-control, -.input-group-sm > .input-group-addon, -.input-group-sm > .input-group-btn > .btn { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -select.input-group-sm > .form-control, -select.input-group-sm > .input-group-addon, -select.input-group-sm > .input-group-btn > .btn { - height: 30px; - line-height: 30px; -} -textarea.input-group-sm > .form-control, -textarea.input-group-sm > .input-group-addon, -textarea.input-group-sm > .input-group-btn > .btn, -select[multiple].input-group-sm > .form-control, -select[multiple].input-group-sm > .input-group-addon, -select[multiple].input-group-sm > .input-group-btn > .btn { - height: auto; -} -.input-group-addon, -.input-group-btn, -.input-group .form-control { - display: table-cell; -} -.input-group-addon:not(:first-child):not(:last-child), -.input-group-btn:not(:first-child):not(:last-child), -.input-group .form-control:not(:first-child):not(:last-child) { - border-radius: 0; -} -.input-group-addon, -.input-group-btn { - width: 1%; - white-space: nowrap; - vertical-align: middle; -} -.input-group-addon { - padding: 6px 12px; - font-size: 14px; - font-weight: 400; - line-height: 1; - color: #555555; - text-align: center; - background-color: #eeeeee; - border: 1px solid #ccc; - border-radius: 4px; -} -.input-group-addon.input-sm { - padding: 5px 10px; - font-size: 12px; - border-radius: 3px; -} -.input-group-addon.input-lg { - padding: 10px 16px; - font-size: 18px; - border-radius: 6px; -} -.input-group-addon input[type="radio"], -.input-group-addon input[type="checkbox"] { - margin-top: 0; -} -.input-group .form-control:first-child, -.input-group-addon:first-child, -.input-group-btn:first-child > .btn, -.input-group-btn:first-child > .btn-group > .btn, -.input-group-btn:first-child > .dropdown-toggle, -.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), -.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} -.input-group-addon:first-child { - border-right: 0; -} -.input-group .form-control:last-child, -.input-group-addon:last-child, -.input-group-btn:last-child > .btn, -.input-group-btn:last-child > .btn-group > .btn, -.input-group-btn:last-child > .dropdown-toggle, -.input-group-btn:first-child > .btn:not(:first-child), -.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} -.input-group-addon:last-child { - border-left: 0; -} -.input-group-btn { - position: relative; - font-size: 0; - white-space: nowrap; -} -.input-group-btn > .btn { - position: relative; -} -.input-group-btn > .btn + .btn { - margin-left: -1px; -} -.input-group-btn > .btn:hover, -.input-group-btn > .btn:focus, -.input-group-btn > .btn:active { - z-index: 2; -} -.input-group-btn:first-child > .btn, -.input-group-btn:first-child > .btn-group { - margin-right: -1px; -} -.input-group-btn:last-child > .btn, -.input-group-btn:last-child > .btn-group { - z-index: 2; - margin-left: -1px; -} -.nav { - padding-left: 0; - margin-bottom: 0; - list-style: none; -} -.nav > li { - position: relative; - display: block; -} -.nav > li > a { - position: relative; - display: block; - padding: 10px 15px; -} -.nav > li > a:hover, -.nav > li > a:focus { - text-decoration: none; - background-color: #eeeeee; -} -.nav > li.disabled > a { - color: #777777; -} -.nav > li.disabled > a:hover, -.nav > li.disabled > a:focus { - color: #777777; - text-decoration: none; - cursor: not-allowed; - background-color: transparent; -} -.nav .open > a, -.nav .open > a:hover, -.nav .open > a:focus { - background-color: #eeeeee; - border-color: #337ab7; -} -.nav .nav-divider { - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5; -} -.nav > li > a > img { - max-width: none; -} -.nav-tabs { - border-bottom: 1px solid #ddd; -} -.nav-tabs > li { - float: left; - margin-bottom: -1px; -} -.nav-tabs > li > a { - margin-right: 2px; - line-height: 1.42857143; - border: 1px solid transparent; - border-radius: 4px 4px 0 0; -} -.nav-tabs > li > a:hover { - border-color: #eeeeee #eeeeee #ddd; -} -.nav-tabs > li.active > a, -.nav-tabs > li.active > a:hover, -.nav-tabs > li.active > a:focus { - color: #555555; - cursor: default; - background-color: #fff; - border: 1px solid #ddd; - border-bottom-color: transparent; -} -.nav-tabs.nav-justified { - width: 100%; - border-bottom: 0; -} -.nav-tabs.nav-justified > li { - float: none; -} -.nav-tabs.nav-justified > li > a { - margin-bottom: 5px; - text-align: center; -} -.nav-tabs.nav-justified > .dropdown .dropdown-menu { - top: auto; - left: auto; -} -@media (min-width: 768px) { - .nav-tabs.nav-justified > li { - display: table-cell; - width: 1%; - } - .nav-tabs.nav-justified > li > a { - margin-bottom: 0; - } -} -.nav-tabs.nav-justified > li > a { - margin-right: 0; - border-radius: 4px; -} -.nav-tabs.nav-justified > .active > a, -.nav-tabs.nav-justified > .active > a:hover, -.nav-tabs.nav-justified > .active > a:focus { - border: 1px solid #ddd; -} -@media (min-width: 768px) { - .nav-tabs.nav-justified > li > a { - border-bottom: 1px solid #ddd; - border-radius: 4px 4px 0 0; - } - .nav-tabs.nav-justified > .active > a, - .nav-tabs.nav-justified > .active > a:hover, - .nav-tabs.nav-justified > .active > a:focus { - border-bottom-color: #fff; - } -} -.nav-pills > li { - float: left; -} -.nav-pills > li > a { - border-radius: 4px; -} -.nav-pills > li + li { - margin-left: 2px; -} -.nav-pills > li.active > a, -.nav-pills > li.active > a:hover, -.nav-pills > li.active > a:focus { - color: #fff; - background-color: #337ab7; -} -.nav-stacked > li { - float: none; -} -.nav-stacked > li + li { - margin-top: 2px; - margin-left: 0; -} -.nav-justified { - width: 100%; -} -.nav-justified > li { - float: none; -} -.nav-justified > li > a { - margin-bottom: 5px; - text-align: center; -} -.nav-justified > .dropdown .dropdown-menu { - top: auto; - left: auto; -} -@media (min-width: 768px) { - .nav-justified > li { - display: table-cell; - width: 1%; - } - .nav-justified > li > a { - margin-bottom: 0; - } -} -.nav-tabs-justified { - border-bottom: 0; -} -.nav-tabs-justified > li > a { - margin-right: 0; - border-radius: 4px; -} -.nav-tabs-justified > .active > a, -.nav-tabs-justified > .active > a:hover, -.nav-tabs-justified > .active > a:focus { - border: 1px solid #ddd; -} -@media (min-width: 768px) { - .nav-tabs-justified > li > a { - border-bottom: 1px solid #ddd; - border-radius: 4px 4px 0 0; - } - .nav-tabs-justified > .active > a, - .nav-tabs-justified > .active > a:hover, - .nav-tabs-justified > .active > a:focus { - border-bottom-color: #fff; - } -} -.tab-content > .tab-pane { - display: none; -} -.tab-content > .active { - display: block; -} -.nav-tabs .dropdown-menu { - margin-top: -1px; - border-top-left-radius: 0; - border-top-right-radius: 0; -} -.navbar { - position: relative; - min-height: 50px; - margin-bottom: 20px; - border: 1px solid transparent; -} -@media (min-width: 768px) { - .navbar { - border-radius: 4px; - } -} -@media (min-width: 768px) { - .navbar-header { - float: left; - } -} -.navbar-collapse { - padding-right: 15px; - padding-left: 15px; - overflow-x: visible; - border-top: 1px solid transparent; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); - -webkit-overflow-scrolling: touch; -} -.navbar-collapse.in { - overflow-y: auto; -} -@media (min-width: 768px) { - .navbar-collapse { - width: auto; - border-top: 0; - -webkit-box-shadow: none; - box-shadow: none; - } - .navbar-collapse.collapse { - display: block !important; - height: auto !important; - padding-bottom: 0; - overflow: visible !important; - } - .navbar-collapse.in { - overflow-y: visible; - } - .navbar-fixed-top .navbar-collapse, - .navbar-static-top .navbar-collapse, - .navbar-fixed-bottom .navbar-collapse { - padding-right: 0; - padding-left: 0; - } -} -.navbar-fixed-top, -.navbar-fixed-bottom { - position: fixed; - right: 0; - left: 0; - z-index: 1030; -} -.navbar-fixed-top .navbar-collapse, -.navbar-fixed-bottom .navbar-collapse { - max-height: 340px; -} -@media (max-device-width: 480px) and (orientation: landscape) { - .navbar-fixed-top .navbar-collapse, - .navbar-fixed-bottom .navbar-collapse { - max-height: 200px; - } -} -@media (min-width: 768px) { - .navbar-fixed-top, - .navbar-fixed-bottom { - border-radius: 0; - } -} -.navbar-fixed-top { - top: 0; - border-width: 0 0 1px; -} -.navbar-fixed-bottom { - bottom: 0; - margin-bottom: 0; - border-width: 1px 0 0; -} -.container > .navbar-header, -.container-fluid > .navbar-header, -.container > .navbar-collapse, -.container-fluid > .navbar-collapse { - margin-right: -15px; - margin-left: -15px; -} -@media (min-width: 768px) { - .container > .navbar-header, - .container-fluid > .navbar-header, - .container > .navbar-collapse, - .container-fluid > .navbar-collapse { - margin-right: 0; - margin-left: 0; - } -} -.navbar-static-top { - z-index: 1000; - border-width: 0 0 1px; -} -@media (min-width: 768px) { - .navbar-static-top { - border-radius: 0; - } -} -.navbar-brand { - float: left; - height: 50px; - padding: 15px 15px; - font-size: 18px; - line-height: 20px; -} -.navbar-brand:hover, -.navbar-brand:focus { - text-decoration: none; -} -.navbar-brand > img { - display: block; -} -@media (min-width: 768px) { - .navbar > .container .navbar-brand, - .navbar > .container-fluid .navbar-brand { - margin-left: -15px; - } -} -.navbar-toggle { - position: relative; - float: right; - padding: 9px 10px; - margin-right: 15px; - margin-top: 8px; - margin-bottom: 8px; - background-color: transparent; - background-image: none; - border: 1px solid transparent; - border-radius: 4px; -} -.navbar-toggle:focus { - outline: 0; -} -.navbar-toggle .icon-bar { - display: block; - width: 22px; - height: 2px; - border-radius: 1px; -} -.navbar-toggle .icon-bar + .icon-bar { - margin-top: 4px; -} -@media (min-width: 768px) { - .navbar-toggle { - display: none; - } -} -.navbar-nav { - margin: 7.5px -15px; -} -.navbar-nav > li > a { - padding-top: 10px; - padding-bottom: 10px; - line-height: 20px; -} -@media (max-width: 767px) { - .navbar-nav .open .dropdown-menu { - position: static; - float: none; - width: auto; - margin-top: 0; - background-color: transparent; - border: 0; - -webkit-box-shadow: none; - box-shadow: none; - } - .navbar-nav .open .dropdown-menu > li > a, - .navbar-nav .open .dropdown-menu .dropdown-header { - padding: 5px 15px 5px 25px; - } - .navbar-nav .open .dropdown-menu > li > a { - line-height: 20px; - } - .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-nav .open .dropdown-menu > li > a:focus { - background-image: none; - } -} -@media (min-width: 768px) { - .navbar-nav { - float: left; - margin: 0; - } - .navbar-nav > li { - float: left; - } - .navbar-nav > li > a { - padding-top: 15px; - padding-bottom: 15px; - } -} -.navbar-form { - padding: 10px 15px; - margin-right: -15px; - margin-left: -15px; - border-top: 1px solid transparent; - border-bottom: 1px solid transparent; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); - margin-top: 8px; - margin-bottom: 8px; -} -@media (min-width: 768px) { - .navbar-form .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle; - } - .navbar-form .form-control { - display: inline-block; - width: auto; - vertical-align: middle; - } - .navbar-form .form-control-static { - display: inline-block; - } - .navbar-form .input-group { - display: inline-table; - vertical-align: middle; - } - .navbar-form .input-group .input-group-addon, - .navbar-form .input-group .input-group-btn, - .navbar-form .input-group .form-control { - width: auto; - } - .navbar-form .input-group > .form-control { - width: 100%; - } - .navbar-form .control-label { - margin-bottom: 0; - vertical-align: middle; - } - .navbar-form .radio, - .navbar-form .checkbox { - display: inline-block; - margin-top: 0; - margin-bottom: 0; - vertical-align: middle; - } - .navbar-form .radio label, - .navbar-form .checkbox label { - padding-left: 0; - } - .navbar-form .radio input[type="radio"], - .navbar-form .checkbox input[type="checkbox"] { - position: relative; - margin-left: 0; - } - .navbar-form .has-feedback .form-control-feedback { - top: 0; - } -} -@media (max-width: 767px) { - .navbar-form .form-group { - margin-bottom: 5px; - } - .navbar-form .form-group:last-child { - margin-bottom: 0; - } -} -@media (min-width: 768px) { - .navbar-form { - width: auto; - padding-top: 0; - padding-bottom: 0; - margin-right: 0; - margin-left: 0; - border: 0; - -webkit-box-shadow: none; - box-shadow: none; - } -} -.navbar-nav > li > .dropdown-menu { - margin-top: 0; - border-top-left-radius: 0; - border-top-right-radius: 0; -} -.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { - margin-bottom: 0; - border-top-left-radius: 4px; - border-top-right-radius: 4px; - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} -.navbar-btn { - margin-top: 8px; - margin-bottom: 8px; -} -.navbar-btn.btn-sm { - margin-top: 10px; - margin-bottom: 10px; -} -.navbar-btn.btn-xs { - margin-top: 14px; - margin-bottom: 14px; -} -.navbar-text { - margin-top: 15px; - margin-bottom: 15px; -} -@media (min-width: 768px) { - .navbar-text { - float: left; - margin-right: 15px; - margin-left: 15px; - } -} -@media (min-width: 768px) { - .navbar-left { - float: left !important; - } - .navbar-right { - float: right !important; - margin-right: -15px; - } - .navbar-right ~ .navbar-right { - margin-right: 0; - } -} -.navbar-default { - background-color: #f8f8f8; - border-color: #e7e7e7; -} -.navbar-default .navbar-brand { - color: #777; -} -.navbar-default .navbar-brand:hover, -.navbar-default .navbar-brand:focus { - color: #5e5e5e; - background-color: transparent; -} -.navbar-default .navbar-text { - color: #777; -} -.navbar-default .navbar-nav > li > a { - color: #777; -} -.navbar-default .navbar-nav > li > a:hover, -.navbar-default .navbar-nav > li > a:focus { - color: #333; - background-color: transparent; -} -.navbar-default .navbar-nav > .active > a, -.navbar-default .navbar-nav > .active > a:hover, -.navbar-default .navbar-nav > .active > a:focus { - color: #555; - background-color: #e7e7e7; -} -.navbar-default .navbar-nav > .disabled > a, -.navbar-default .navbar-nav > .disabled > a:hover, -.navbar-default .navbar-nav > .disabled > a:focus { - color: #ccc; - background-color: transparent; -} -.navbar-default .navbar-nav > .open > a, -.navbar-default .navbar-nav > .open > a:hover, -.navbar-default .navbar-nav > .open > a:focus { - color: #555; - background-color: #e7e7e7; -} -@media (max-width: 767px) { - .navbar-default .navbar-nav .open .dropdown-menu > li > a { - color: #777; - } - .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { - color: #333; - background-color: transparent; - } - .navbar-default .navbar-nav .open .dropdown-menu > .active > a, - .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { - color: #555; - background-color: #e7e7e7; - } - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { - color: #ccc; - background-color: transparent; - } -} -.navbar-default .navbar-toggle { - border-color: #ddd; -} -.navbar-default .navbar-toggle:hover, -.navbar-default .navbar-toggle:focus { - background-color: #ddd; -} -.navbar-default .navbar-toggle .icon-bar { - background-color: #888; -} -.navbar-default .navbar-collapse, -.navbar-default .navbar-form { - border-color: #e7e7e7; -} -.navbar-default .navbar-link { - color: #777; -} -.navbar-default .navbar-link:hover { - color: #333; -} -.navbar-default .btn-link { - color: #777; -} -.navbar-default .btn-link:hover, -.navbar-default .btn-link:focus { - color: #333; -} -.navbar-default .btn-link[disabled]:hover, -fieldset[disabled] .navbar-default .btn-link:hover, -.navbar-default .btn-link[disabled]:focus, -fieldset[disabled] .navbar-default .btn-link:focus { - color: #ccc; -} -.navbar-inverse { - background-color: #222; - border-color: #080808; -} -.navbar-inverse .navbar-brand { - color: #9d9d9d; -} -.navbar-inverse .navbar-brand:hover, -.navbar-inverse .navbar-brand:focus { - color: #fff; - background-color: transparent; -} -.navbar-inverse .navbar-text { - color: #9d9d9d; -} -.navbar-inverse .navbar-nav > li > a { - color: #9d9d9d; -} -.navbar-inverse .navbar-nav > li > a:hover, -.navbar-inverse .navbar-nav > li > a:focus { - color: #fff; - background-color: transparent; -} -.navbar-inverse .navbar-nav > .active > a, -.navbar-inverse .navbar-nav > .active > a:hover, -.navbar-inverse .navbar-nav > .active > a:focus { - color: #fff; - background-color: #080808; -} -.navbar-inverse .navbar-nav > .disabled > a, -.navbar-inverse .navbar-nav > .disabled > a:hover, -.navbar-inverse .navbar-nav > .disabled > a:focus { - color: #444; - background-color: transparent; -} -.navbar-inverse .navbar-nav > .open > a, -.navbar-inverse .navbar-nav > .open > a:hover, -.navbar-inverse .navbar-nav > .open > a:focus { - color: #fff; - background-color: #080808; -} -@media (max-width: 767px) { - .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { - border-color: #080808; - } - .navbar-inverse .navbar-nav .open .dropdown-menu .divider { - background-color: #080808; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { - color: #9d9d9d; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { - color: #fff; - background-color: transparent; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { - color: #fff; - background-color: #080808; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { - color: #444; - background-color: transparent; - } -} -.navbar-inverse .navbar-toggle { - border-color: #333; -} -.navbar-inverse .navbar-toggle:hover, -.navbar-inverse .navbar-toggle:focus { - background-color: #333; -} -.navbar-inverse .navbar-toggle .icon-bar { - background-color: #fff; -} -.navbar-inverse .navbar-collapse, -.navbar-inverse .navbar-form { - border-color: #101010; -} -.navbar-inverse .navbar-link { - color: #9d9d9d; -} -.navbar-inverse .navbar-link:hover { - color: #fff; -} -.navbar-inverse .btn-link { - color: #9d9d9d; -} -.navbar-inverse .btn-link:hover, -.navbar-inverse .btn-link:focus { - color: #fff; -} -.navbar-inverse .btn-link[disabled]:hover, -fieldset[disabled] .navbar-inverse .btn-link:hover, -.navbar-inverse .btn-link[disabled]:focus, -fieldset[disabled] .navbar-inverse .btn-link:focus { - color: #444; -} -.breadcrumb { - padding: 8px 15px; - margin-bottom: 20px; - list-style: none; - background-color: #f5f5f5; - border-radius: 4px; -} -.breadcrumb > li { - display: inline-block; -} -.breadcrumb > li + li:before { - padding: 0 5px; - color: #ccc; - content: "/\00a0"; -} -.breadcrumb > .active { - color: #777777; -} -.pagination { - display: inline-block; - padding-left: 0; - margin: 20px 0; - border-radius: 4px; -} -.pagination > li { - display: inline; -} -.pagination > li > a, -.pagination > li > span { - position: relative; - float: left; - padding: 6px 12px; - margin-left: -1px; - line-height: 1.42857143; - color: #337ab7; - text-decoration: none; - background-color: #fff; - border: 1px solid #ddd; -} -.pagination > li > a:hover, -.pagination > li > span:hover, -.pagination > li > a:focus, -.pagination > li > span:focus { - z-index: 2; - color: #23527c; - background-color: #eeeeee; - border-color: #ddd; -} -.pagination > li:first-child > a, -.pagination > li:first-child > span { - margin-left: 0; - border-top-left-radius: 4px; - border-bottom-left-radius: 4px; -} -.pagination > li:last-child > a, -.pagination > li:last-child > span { - border-top-right-radius: 4px; - border-bottom-right-radius: 4px; -} -.pagination > .active > a, -.pagination > .active > span, -.pagination > .active > a:hover, -.pagination > .active > span:hover, -.pagination > .active > a:focus, -.pagination > .active > span:focus { - z-index: 3; - color: #fff; - cursor: default; - background-color: #337ab7; - border-color: #337ab7; -} -.pagination > .disabled > span, -.pagination > .disabled > span:hover, -.pagination > .disabled > span:focus, -.pagination > .disabled > a, -.pagination > .disabled > a:hover, -.pagination > .disabled > a:focus { - color: #777777; - cursor: not-allowed; - background-color: #fff; - border-color: #ddd; -} -.pagination-lg > li > a, -.pagination-lg > li > span { - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; -} -.pagination-lg > li:first-child > a, -.pagination-lg > li:first-child > span { - border-top-left-radius: 6px; - border-bottom-left-radius: 6px; -} -.pagination-lg > li:last-child > a, -.pagination-lg > li:last-child > span { - border-top-right-radius: 6px; - border-bottom-right-radius: 6px; -} -.pagination-sm > li > a, -.pagination-sm > li > span { - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; -} -.pagination-sm > li:first-child > a, -.pagination-sm > li:first-child > span { - border-top-left-radius: 3px; - border-bottom-left-radius: 3px; -} -.pagination-sm > li:last-child > a, -.pagination-sm > li:last-child > span { - border-top-right-radius: 3px; - border-bottom-right-radius: 3px; -} -.pager { - padding-left: 0; - margin: 20px 0; - text-align: center; - list-style: none; -} -.pager li { - display: inline; -} -.pager li > a, -.pager li > span { - display: inline-block; - padding: 5px 14px; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 15px; -} -.pager li > a:hover, -.pager li > a:focus { - text-decoration: none; - background-color: #eeeeee; -} -.pager .next > a, -.pager .next > span { - float: right; -} -.pager .previous > a, -.pager .previous > span { - float: left; -} -.pager .disabled > a, -.pager .disabled > a:hover, -.pager .disabled > a:focus, -.pager .disabled > span { - color: #777777; - cursor: not-allowed; - background-color: #fff; -} -.label { - display: inline; - padding: 0.2em 0.6em 0.3em; - font-size: 75%; - font-weight: 700; - line-height: 1; - color: #fff; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - border-radius: 0.25em; -} -a.label:hover, -a.label:focus { - color: #fff; - text-decoration: none; - cursor: pointer; -} -.label:empty { - display: none; -} -.btn .label { - position: relative; - top: -1px; -} -.label-default { - background-color: #777777; -} -.label-default[href]:hover, -.label-default[href]:focus { - background-color: #5e5e5e; -} -.label-primary { - background-color: #337ab7; -} -.label-primary[href]:hover, -.label-primary[href]:focus { - background-color: #286090; -} -.label-success { - background-color: #5cb85c; -} -.label-success[href]:hover, -.label-success[href]:focus { - background-color: #449d44; -} -.label-info { - background-color: #5bc0de; -} -.label-info[href]:hover, -.label-info[href]:focus { - background-color: #31b0d5; -} -.label-warning { - background-color: #f0ad4e; -} -.label-warning[href]:hover, -.label-warning[href]:focus { - background-color: #ec971f; -} -.label-danger { - background-color: #d9534f; -} -.label-danger[href]:hover, -.label-danger[href]:focus { - background-color: #c9302c; -} -.badge { - display: inline-block; - min-width: 10px; - padding: 3px 7px; - font-size: 12px; - font-weight: bold; - line-height: 1; - color: #fff; - text-align: center; - white-space: nowrap; - vertical-align: middle; - background-color: #777777; - border-radius: 10px; -} -.badge:empty { - display: none; -} -.btn .badge { - position: relative; - top: -1px; -} -.btn-xs .badge, -.btn-group-xs > .btn .badge { - top: 0; - padding: 1px 5px; -} -a.badge:hover, -a.badge:focus { - color: #fff; - text-decoration: none; - cursor: pointer; -} -.list-group-item.active > .badge, -.nav-pills > .active > a > .badge { - color: #337ab7; - background-color: #fff; -} -.list-group-item > .badge { - float: right; -} -.list-group-item > .badge + .badge { - margin-right: 5px; -} -.nav-pills > li > a > .badge { - margin-left: 3px; -} -.jumbotron { - padding-top: 30px; - padding-bottom: 30px; - margin-bottom: 30px; - color: inherit; - background-color: #eeeeee; -} -.jumbotron h1, -.jumbotron .h1 { - color: inherit; -} -.jumbotron p { - margin-bottom: 15px; - font-size: 21px; - font-weight: 200; -} -.jumbotron > hr { - border-top-color: #d5d5d5; -} -.container .jumbotron, -.container-fluid .jumbotron { - padding-right: 15px; - padding-left: 15px; - border-radius: 6px; -} -.jumbotron .container { - max-width: 100%; -} -@media screen and (min-width: 768px) { - .jumbotron { - padding-top: 48px; - padding-bottom: 48px; - } - .container .jumbotron, - .container-fluid .jumbotron { - padding-right: 60px; - padding-left: 60px; - } - .jumbotron h1, - .jumbotron .h1 { - font-size: 63px; - } -} -.thumbnail { - display: block; - padding: 4px; - margin-bottom: 20px; - line-height: 1.42857143; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 4px; - -webkit-transition: border 0.2s ease-in-out; - -o-transition: border 0.2s ease-in-out; - transition: border 0.2s ease-in-out; -} -.thumbnail > img, -.thumbnail a > img { - margin-right: auto; - margin-left: auto; -} -a.thumbnail:hover, -a.thumbnail:focus, -a.thumbnail.active { - border-color: #337ab7; -} -.thumbnail .caption { - padding: 9px; - color: #333333; -} -.alert { - padding: 15px; - margin-bottom: 20px; - border: 1px solid transparent; - border-radius: 4px; -} -.alert h4 { - margin-top: 0; - color: inherit; -} -.alert .alert-link { - font-weight: bold; -} -.alert > p, -.alert > ul { - margin-bottom: 0; -} -.alert > p + p { - margin-top: 5px; -} -.alert-dismissable, -.alert-dismissible { - padding-right: 35px; -} -.alert-dismissable .close, -.alert-dismissible .close { - position: relative; - top: -2px; - right: -21px; - color: inherit; -} -.alert-success { - color: #3c763d; - background-color: #dff0d8; - border-color: #d6e9c6; -} -.alert-success hr { - border-top-color: #c9e2b3; -} -.alert-success .alert-link { - color: #2b542c; -} -.alert-info { - color: #31708f; - background-color: #d9edf7; - border-color: #bce8f1; -} -.alert-info hr { - border-top-color: #a6e1ec; -} -.alert-info .alert-link { - color: #245269; -} -.alert-warning { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #faebcc; -} -.alert-warning hr { - border-top-color: #f7e1b5; -} -.alert-warning .alert-link { - color: #66512c; -} -.alert-danger { - color: #a94442; - background-color: #f2dede; - border-color: #ebccd1; -} -.alert-danger hr { - border-top-color: #e4b9c0; -} -.alert-danger .alert-link { - color: #843534; -} -@-webkit-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -@-o-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -@keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -.progress { - height: 20px; - margin-bottom: 20px; - overflow: hidden; - background-color: #f5f5f5; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -} -.progress-bar { - float: left; - width: 0%; - height: 100%; - font-size: 12px; - line-height: 20px; - color: #fff; - text-align: center; - background-color: #337ab7; - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - -webkit-transition: width 0.6s ease; - -o-transition: width 0.6s ease; - transition: width 0.6s ease; -} -.progress-striped .progress-bar, -.progress-bar-striped { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - -webkit-background-size: 40px 40px; - background-size: 40px 40px; -} -.progress.active .progress-bar, -.progress-bar.active { - -webkit-animation: progress-bar-stripes 2s linear infinite; - -o-animation: progress-bar-stripes 2s linear infinite; - animation: progress-bar-stripes 2s linear infinite; -} -.progress-bar-success { - background-color: #5cb85c; -} -.progress-striped .progress-bar-success { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} -.progress-bar-info { - background-color: #5bc0de; -} -.progress-striped .progress-bar-info { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} -.progress-bar-warning { - background-color: #f0ad4e; -} -.progress-striped .progress-bar-warning { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} -.progress-bar-danger { - background-color: #d9534f; -} -.progress-striped .progress-bar-danger { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} -.media { - margin-top: 15px; -} -.media:first-child { - margin-top: 0; -} -.media, -.media-body { - overflow: hidden; - zoom: 1; -} -.media-body { - width: 10000px; -} -.media-object { - display: block; -} -.media-object.img-thumbnail { - max-width: none; -} -.media-right, -.media > .pull-right { - padding-left: 10px; -} -.media-left, -.media > .pull-left { - padding-right: 10px; -} -.media-left, -.media-right, -.media-body { - display: table-cell; - vertical-align: top; -} -.media-middle { - vertical-align: middle; -} -.media-bottom { - vertical-align: bottom; -} -.media-heading { - margin-top: 0; - margin-bottom: 5px; -} -.media-list { - padding-left: 0; - list-style: none; -} -.list-group { - padding-left: 0; - margin-bottom: 20px; -} -.list-group-item { - position: relative; - display: block; - padding: 10px 15px; - margin-bottom: -1px; - background-color: #fff; - border: 1px solid #ddd; -} -.list-group-item:first-child { - border-top-left-radius: 4px; - border-top-right-radius: 4px; -} -.list-group-item:last-child { - margin-bottom: 0; - border-bottom-right-radius: 4px; - border-bottom-left-radius: 4px; -} -.list-group-item.disabled, -.list-group-item.disabled:hover, -.list-group-item.disabled:focus { - color: #777777; - cursor: not-allowed; - background-color: #eeeeee; -} -.list-group-item.disabled .list-group-item-heading, -.list-group-item.disabled:hover .list-group-item-heading, -.list-group-item.disabled:focus .list-group-item-heading { - color: inherit; -} -.list-group-item.disabled .list-group-item-text, -.list-group-item.disabled:hover .list-group-item-text, -.list-group-item.disabled:focus .list-group-item-text { - color: #777777; -} -.list-group-item.active, -.list-group-item.active:hover, -.list-group-item.active:focus { - z-index: 2; - color: #fff; - background-color: #337ab7; - border-color: #337ab7; -} -.list-group-item.active .list-group-item-heading, -.list-group-item.active:hover .list-group-item-heading, -.list-group-item.active:focus .list-group-item-heading, -.list-group-item.active .list-group-item-heading > small, -.list-group-item.active:hover .list-group-item-heading > small, -.list-group-item.active:focus .list-group-item-heading > small, -.list-group-item.active .list-group-item-heading > .small, -.list-group-item.active:hover .list-group-item-heading > .small, -.list-group-item.active:focus .list-group-item-heading > .small { - color: inherit; -} -.list-group-item.active .list-group-item-text, -.list-group-item.active:hover .list-group-item-text, -.list-group-item.active:focus .list-group-item-text { - color: #c7ddef; -} -a.list-group-item, -button.list-group-item { - color: #555; -} -a.list-group-item .list-group-item-heading, -button.list-group-item .list-group-item-heading { - color: #333; -} -a.list-group-item:hover, -button.list-group-item:hover, -a.list-group-item:focus, -button.list-group-item:focus { - color: #555; - text-decoration: none; - background-color: #f5f5f5; -} -button.list-group-item { - width: 100%; - text-align: left; -} -.list-group-item-success { - color: #3c763d; - background-color: #dff0d8; -} -a.list-group-item-success, -button.list-group-item-success { - color: #3c763d; -} -a.list-group-item-success .list-group-item-heading, -button.list-group-item-success .list-group-item-heading { - color: inherit; -} -a.list-group-item-success:hover, -button.list-group-item-success:hover, -a.list-group-item-success:focus, -button.list-group-item-success:focus { - color: #3c763d; - background-color: #d0e9c6; -} -a.list-group-item-success.active, -button.list-group-item-success.active, -a.list-group-item-success.active:hover, -button.list-group-item-success.active:hover, -a.list-group-item-success.active:focus, -button.list-group-item-success.active:focus { - color: #fff; - background-color: #3c763d; - border-color: #3c763d; -} -.list-group-item-info { - color: #31708f; - background-color: #d9edf7; -} -a.list-group-item-info, -button.list-group-item-info { - color: #31708f; -} -a.list-group-item-info .list-group-item-heading, -button.list-group-item-info .list-group-item-heading { - color: inherit; -} -a.list-group-item-info:hover, -button.list-group-item-info:hover, -a.list-group-item-info:focus, -button.list-group-item-info:focus { - color: #31708f; - background-color: #c4e3f3; -} -a.list-group-item-info.active, -button.list-group-item-info.active, -a.list-group-item-info.active:hover, -button.list-group-item-info.active:hover, -a.list-group-item-info.active:focus, -button.list-group-item-info.active:focus { - color: #fff; - background-color: #31708f; - border-color: #31708f; -} -.list-group-item-warning { - color: #8a6d3b; - background-color: #fcf8e3; -} -a.list-group-item-warning, -button.list-group-item-warning { - color: #8a6d3b; -} -a.list-group-item-warning .list-group-item-heading, -button.list-group-item-warning .list-group-item-heading { - color: inherit; -} -a.list-group-item-warning:hover, -button.list-group-item-warning:hover, -a.list-group-item-warning:focus, -button.list-group-item-warning:focus { - color: #8a6d3b; - background-color: #faf2cc; -} -a.list-group-item-warning.active, -button.list-group-item-warning.active, -a.list-group-item-warning.active:hover, -button.list-group-item-warning.active:hover, -a.list-group-item-warning.active:focus, -button.list-group-item-warning.active:focus { - color: #fff; - background-color: #8a6d3b; - border-color: #8a6d3b; -} -.list-group-item-danger { - color: #a94442; - background-color: #f2dede; -} -a.list-group-item-danger, -button.list-group-item-danger { - color: #a94442; -} -a.list-group-item-danger .list-group-item-heading, -button.list-group-item-danger .list-group-item-heading { - color: inherit; -} -a.list-group-item-danger:hover, -button.list-group-item-danger:hover, -a.list-group-item-danger:focus, -button.list-group-item-danger:focus { - color: #a94442; - background-color: #ebcccc; -} -a.list-group-item-danger.active, -button.list-group-item-danger.active, -a.list-group-item-danger.active:hover, -button.list-group-item-danger.active:hover, -a.list-group-item-danger.active:focus, -button.list-group-item-danger.active:focus { - color: #fff; - background-color: #a94442; - border-color: #a94442; -} -.list-group-item-heading { - margin-top: 0; - margin-bottom: 5px; -} -.list-group-item-text { - margin-bottom: 0; - line-height: 1.3; -} -.panel { - margin-bottom: 20px; - background-color: #fff; - border: 1px solid transparent; - border-radius: 4px; - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); - box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); -} -.panel-body { - padding: 15px; -} -.panel-heading { - padding: 10px 15px; - border-bottom: 1px solid transparent; - border-top-left-radius: 3px; - border-top-right-radius: 3px; -} -.panel-heading > .dropdown .dropdown-toggle { - color: inherit; -} -.panel-title { - margin-top: 0; - margin-bottom: 0; - font-size: 16px; - color: inherit; -} -.panel-title > a, -.panel-title > small, -.panel-title > .small, -.panel-title > small > a, -.panel-title > .small > a { - color: inherit; -} -.panel-footer { - padding: 10px 15px; - background-color: #f5f5f5; - border-top: 1px solid #ddd; - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; -} -.panel > .list-group, -.panel > .panel-collapse > .list-group { - margin-bottom: 0; -} -.panel > .list-group .list-group-item, -.panel > .panel-collapse > .list-group .list-group-item { - border-width: 1px 0; - border-radius: 0; -} -.panel > .list-group:first-child .list-group-item:first-child, -.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { - border-top: 0; - border-top-left-radius: 3px; - border-top-right-radius: 3px; -} -.panel > .list-group:last-child .list-group-item:last-child, -.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { - border-bottom: 0; - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; -} -.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child { - border-top-left-radius: 0; - border-top-right-radius: 0; -} -.panel-heading + .list-group .list-group-item:first-child { - border-top-width: 0; -} -.list-group + .panel-footer { - border-top-width: 0; -} -.panel > .table, -.panel > .table-responsive > .table, -.panel > .panel-collapse > .table { - margin-bottom: 0; -} -.panel > .table caption, -.panel > .table-responsive > .table caption, -.panel > .panel-collapse > .table caption { - padding-right: 15px; - padding-left: 15px; -} -.panel > .table:first-child, -.panel > .table-responsive:first-child > .table:first-child { - border-top-left-radius: 3px; - border-top-right-radius: 3px; -} -.panel > .table:first-child > thead:first-child > tr:first-child, -.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, -.panel > .table:first-child > tbody:first-child > tr:first-child, -.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { - border-top-left-radius: 3px; - border-top-right-radius: 3px; -} -.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, -.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, -.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, -.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, -.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, -.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, -.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, -.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { - border-top-left-radius: 3px; -} -.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, -.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, -.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, -.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, -.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, -.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, -.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, -.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { - border-top-right-radius: 3px; -} -.panel > .table:last-child, -.panel > .table-responsive:last-child > .table:last-child { - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; -} -.panel > .table:last-child > tbody:last-child > tr:last-child, -.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, -.panel > .table:last-child > tfoot:last-child > tr:last-child, -.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; -} -.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, -.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, -.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, -.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, -.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, -.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, -.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, -.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { - border-bottom-left-radius: 3px; -} -.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, -.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, -.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, -.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, -.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, -.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, -.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, -.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { - border-bottom-right-radius: 3px; -} -.panel > .panel-body + .table, -.panel > .panel-body + .table-responsive, -.panel > .table + .panel-body, -.panel > .table-responsive + .panel-body { - border-top: 1px solid #ddd; -} -.panel > .table > tbody:first-child > tr:first-child th, -.panel > .table > tbody:first-child > tr:first-child td { - border-top: 0; -} -.panel > .table-bordered, -.panel > .table-responsive > .table-bordered { - border: 0; -} -.panel > .table-bordered > thead > tr > th:first-child, -.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, -.panel > .table-bordered > tbody > tr > th:first-child, -.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, -.panel > .table-bordered > tfoot > tr > th:first-child, -.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, -.panel > .table-bordered > thead > tr > td:first-child, -.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, -.panel > .table-bordered > tbody > tr > td:first-child, -.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, -.panel > .table-bordered > tfoot > tr > td:first-child, -.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { - border-left: 0; -} -.panel > .table-bordered > thead > tr > th:last-child, -.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, -.panel > .table-bordered > tbody > tr > th:last-child, -.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, -.panel > .table-bordered > tfoot > tr > th:last-child, -.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, -.panel > .table-bordered > thead > tr > td:last-child, -.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, -.panel > .table-bordered > tbody > tr > td:last-child, -.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, -.panel > .table-bordered > tfoot > tr > td:last-child, -.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { - border-right: 0; -} -.panel > .table-bordered > thead > tr:first-child > td, -.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, -.panel > .table-bordered > tbody > tr:first-child > td, -.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, -.panel > .table-bordered > thead > tr:first-child > th, -.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, -.panel > .table-bordered > tbody > tr:first-child > th, -.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { - border-bottom: 0; -} -.panel > .table-bordered > tbody > tr:last-child > td, -.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, -.panel > .table-bordered > tfoot > tr:last-child > td, -.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, -.panel > .table-bordered > tbody > tr:last-child > th, -.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, -.panel > .table-bordered > tfoot > tr:last-child > th, -.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { - border-bottom: 0; -} -.panel > .table-responsive { - margin-bottom: 0; - border: 0; -} -.panel-group { - margin-bottom: 20px; -} -.panel-group .panel { - margin-bottom: 0; - border-radius: 4px; -} -.panel-group .panel + .panel { - margin-top: 5px; -} -.panel-group .panel-heading { - border-bottom: 0; -} -.panel-group .panel-heading + .panel-collapse > .panel-body, -.panel-group .panel-heading + .panel-collapse > .list-group { - border-top: 1px solid #ddd; -} -.panel-group .panel-footer { - border-top: 0; -} -.panel-group .panel-footer + .panel-collapse .panel-body { - border-bottom: 1px solid #ddd; -} -.panel-default { - border-color: #ddd; -} -.panel-default > .panel-heading { - color: #333333; - background-color: #f5f5f5; - border-color: #ddd; -} -.panel-default > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #ddd; -} -.panel-default > .panel-heading .badge { - color: #f5f5f5; - background-color: #333333; -} -.panel-default > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #ddd; -} -.panel-primary { - border-color: #337ab7; -} -.panel-primary > .panel-heading { - color: #fff; - background-color: #337ab7; - border-color: #337ab7; -} -.panel-primary > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #337ab7; -} -.panel-primary > .panel-heading .badge { - color: #337ab7; - background-color: #fff; -} -.panel-primary > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #337ab7; -} -.panel-success { - border-color: #d6e9c6; -} -.panel-success > .panel-heading { - color: #3c763d; - background-color: #dff0d8; - border-color: #d6e9c6; -} -.panel-success > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #d6e9c6; -} -.panel-success > .panel-heading .badge { - color: #dff0d8; - background-color: #3c763d; -} -.panel-success > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #d6e9c6; -} -.panel-info { - border-color: #bce8f1; -} -.panel-info > .panel-heading { - color: #31708f; - background-color: #d9edf7; - border-color: #bce8f1; -} -.panel-info > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #bce8f1; -} -.panel-info > .panel-heading .badge { - color: #d9edf7; - background-color: #31708f; -} -.panel-info > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #bce8f1; -} -.panel-warning { - border-color: #faebcc; -} -.panel-warning > .panel-heading { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #faebcc; -} -.panel-warning > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #faebcc; -} -.panel-warning > .panel-heading .badge { - color: #fcf8e3; - background-color: #8a6d3b; -} -.panel-warning > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #faebcc; -} -.panel-danger { - border-color: #ebccd1; -} -.panel-danger > .panel-heading { - color: #a94442; - background-color: #f2dede; - border-color: #ebccd1; -} -.panel-danger > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #ebccd1; -} -.panel-danger > .panel-heading .badge { - color: #f2dede; - background-color: #a94442; -} -.panel-danger > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #ebccd1; -} -.embed-responsive { - position: relative; - display: block; - height: 0; - padding: 0; - overflow: hidden; -} -.embed-responsive .embed-responsive-item, -.embed-responsive iframe, -.embed-responsive embed, -.embed-responsive object, -.embed-responsive video { - position: absolute; - top: 0; - bottom: 0; - left: 0; - width: 100%; - height: 100%; - border: 0; -} -.embed-responsive-16by9 { - padding-bottom: 56.25%; -} -.embed-responsive-4by3 { - padding-bottom: 75%; -} -.well { - min-height: 20px; - padding: 19px; - margin-bottom: 20px; - background-color: #f5f5f5; - border: 1px solid #e3e3e3; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); -} -.well blockquote { - border-color: #ddd; - border-color: rgba(0, 0, 0, 0.15); -} -.well-lg { - padding: 24px; - border-radius: 6px; -} -.well-sm { - padding: 9px; - border-radius: 3px; -} -.close { - float: right; - font-size: 21px; - font-weight: bold; - line-height: 1; - color: #000; - text-shadow: 0 1px 0 #fff; - filter: alpha(opacity=20); - opacity: 0.2; -} -.close:hover, -.close:focus { - color: #000; - text-decoration: none; - cursor: pointer; - filter: alpha(opacity=50); - opacity: 0.5; -} -button.close { - padding: 0; - cursor: pointer; - background: transparent; - border: 0; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; -} -.modal-open { - overflow: hidden; -} -.modal { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1050; - display: none; - overflow: hidden; - -webkit-overflow-scrolling: touch; - outline: 0; -} -.modal.fade .modal-dialog { - -webkit-transform: translate(0, -25%); - -ms-transform: translate(0, -25%); - -o-transform: translate(0, -25%); - transform: translate(0, -25%); - -webkit-transition: -webkit-transform 0.3s ease-out; - -o-transition: -o-transform 0.3s ease-out; - transition: -webkit-transform 0.3s ease-out; - transition: transform 0.3s ease-out; - transition: transform 0.3s ease-out, -webkit-transform 0.3s ease-out, -o-transform 0.3s ease-out; -} -.modal.in .modal-dialog { - -webkit-transform: translate(0, 0); - -ms-transform: translate(0, 0); - -o-transform: translate(0, 0); - transform: translate(0, 0); -} -.modal-open .modal { - overflow-x: hidden; - overflow-y: auto; -} -.modal-dialog { - position: relative; - width: auto; - margin: 10px; -} -.modal-content { - position: relative; - background-color: #fff; - background-clip: padding-box; - border: 1px solid #999; - border: 1px solid rgba(0, 0, 0, 0.2); - border-radius: 6px; - -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); - box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); - outline: 0; -} -.modal-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1040; - background-color: #000; -} -.modal-backdrop.fade { - filter: alpha(opacity=0); - opacity: 0; -} -.modal-backdrop.in { - filter: alpha(opacity=50); - opacity: 0.5; -} -.modal-header { - padding: 15px; - border-bottom: 1px solid #e5e5e5; -} -.modal-header .close { - margin-top: -2px; -} -.modal-title { - margin: 0; - line-height: 1.42857143; -} -.modal-body { - position: relative; - padding: 15px; -} -.modal-footer { - padding: 15px; - text-align: right; - border-top: 1px solid #e5e5e5; -} -.modal-footer .btn + .btn { - margin-bottom: 0; - margin-left: 5px; -} -.modal-footer .btn-group .btn + .btn { - margin-left: -1px; -} -.modal-footer .btn-block + .btn-block { - margin-left: 0; -} -.modal-scrollbar-measure { - position: absolute; - top: -9999px; - width: 50px; - height: 50px; - overflow: scroll; -} -@media (min-width: 768px) { - .modal-dialog { - width: 600px; - margin: 30px auto; - } - .modal-content { - -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); - box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); - } - .modal-sm { - width: 300px; - } -} -@media (min-width: 992px) { - .modal-lg { - width: 900px; - } -} -.tooltip { - position: absolute; - z-index: 1070; - display: block; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-style: normal; - font-weight: 400; - line-height: 1.42857143; - line-break: auto; - text-align: left; - text-align: start; - text-decoration: none; - text-shadow: none; - text-transform: none; - letter-spacing: normal; - word-break: normal; - word-spacing: normal; - word-wrap: normal; - white-space: normal; - font-size: 12px; - filter: alpha(opacity=0); - opacity: 0; -} -.tooltip.in { - filter: alpha(opacity=90); - opacity: 0.9; -} -.tooltip.top { - padding: 5px 0; - margin-top: -3px; -} -.tooltip.right { - padding: 0 5px; - margin-left: 3px; -} -.tooltip.bottom { - padding: 5px 0; - margin-top: 3px; -} -.tooltip.left { - padding: 0 5px; - margin-left: -3px; -} -.tooltip.top .tooltip-arrow { - bottom: 0; - left: 50%; - margin-left: -5px; - border-width: 5px 5px 0; - border-top-color: #000; -} -.tooltip.top-left .tooltip-arrow { - right: 5px; - bottom: 0; - margin-bottom: -5px; - border-width: 5px 5px 0; - border-top-color: #000; -} -.tooltip.top-right .tooltip-arrow { - bottom: 0; - left: 5px; - margin-bottom: -5px; - border-width: 5px 5px 0; - border-top-color: #000; -} -.tooltip.right .tooltip-arrow { - top: 50%; - left: 0; - margin-top: -5px; - border-width: 5px 5px 5px 0; - border-right-color: #000; -} -.tooltip.left .tooltip-arrow { - top: 50%; - right: 0; - margin-top: -5px; - border-width: 5px 0 5px 5px; - border-left-color: #000; -} -.tooltip.bottom .tooltip-arrow { - top: 0; - left: 50%; - margin-left: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000; -} -.tooltip.bottom-left .tooltip-arrow { - top: 0; - right: 5px; - margin-top: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000; -} -.tooltip.bottom-right .tooltip-arrow { - top: 0; - left: 5px; - margin-top: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000; -} -.tooltip-inner { - max-width: 200px; - padding: 3px 8px; - color: #fff; - text-align: center; - background-color: #000; - border-radius: 4px; -} -.tooltip-arrow { - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} -.popover { - position: absolute; - top: 0; - left: 0; - z-index: 1060; - display: none; - max-width: 276px; - padding: 1px; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-style: normal; - font-weight: 400; - line-height: 1.42857143; - line-break: auto; - text-align: left; - text-align: start; - text-decoration: none; - text-shadow: none; - text-transform: none; - letter-spacing: normal; - word-break: normal; - word-spacing: normal; - word-wrap: normal; - white-space: normal; - font-size: 14px; - background-color: #fff; - background-clip: padding-box; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.2); - border-radius: 6px; - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); -} -.popover.top { - margin-top: -10px; -} -.popover.right { - margin-left: 10px; -} -.popover.bottom { - margin-top: 10px; -} -.popover.left { - margin-left: -10px; -} -.popover > .arrow { - border-width: 11px; -} -.popover > .arrow, -.popover > .arrow:after { - position: absolute; - display: block; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} -.popover > .arrow:after { - content: ""; - border-width: 10px; -} -.popover.top > .arrow { - bottom: -11px; - left: 50%; - margin-left: -11px; - border-top-color: #999999; - border-top-color: rgba(0, 0, 0, 0.25); - border-bottom-width: 0; -} -.popover.top > .arrow:after { - bottom: 1px; - margin-left: -10px; - content: " "; - border-top-color: #fff; - border-bottom-width: 0; -} -.popover.right > .arrow { - top: 50%; - left: -11px; - margin-top: -11px; - border-right-color: #999999; - border-right-color: rgba(0, 0, 0, 0.25); - border-left-width: 0; -} -.popover.right > .arrow:after { - bottom: -10px; - left: 1px; - content: " "; - border-right-color: #fff; - border-left-width: 0; -} -.popover.bottom > .arrow { - top: -11px; - left: 50%; - margin-left: -11px; - border-top-width: 0; - border-bottom-color: #999999; - border-bottom-color: rgba(0, 0, 0, 0.25); -} -.popover.bottom > .arrow:after { - top: 1px; - margin-left: -10px; - content: " "; - border-top-width: 0; - border-bottom-color: #fff; -} -.popover.left > .arrow { - top: 50%; - right: -11px; - margin-top: -11px; - border-right-width: 0; - border-left-color: #999999; - border-left-color: rgba(0, 0, 0, 0.25); -} -.popover.left > .arrow:after { - right: 1px; - bottom: -10px; - content: " "; - border-right-width: 0; - border-left-color: #fff; -} -.popover-title { - padding: 8px 14px; - margin: 0; - font-size: 14px; - background-color: #f7f7f7; - border-bottom: 1px solid #ebebeb; - border-radius: 5px 5px 0 0; -} -.popover-content { - padding: 9px 14px; -} -.carousel { - position: relative; -} -.carousel-inner { - position: relative; - width: 100%; - overflow: hidden; -} -.carousel-inner > .item { - position: relative; - display: none; - -webkit-transition: 0.6s ease-in-out left; - -o-transition: 0.6s ease-in-out left; - transition: 0.6s ease-in-out left; -} -.carousel-inner > .item > img, -.carousel-inner > .item > a > img { - line-height: 1; -} -@media all and (transform-3d), (-webkit-transform-3d) { - .carousel-inner > .item { - -webkit-transition: -webkit-transform 0.6s ease-in-out; - -o-transition: -o-transform 0.6s ease-in-out; - transition: -webkit-transform 0.6s ease-in-out; - transition: transform 0.6s ease-in-out; - transition: transform 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out, -o-transform 0.6s ease-in-out; - -webkit-backface-visibility: hidden; - backface-visibility: hidden; - -webkit-perspective: 1000px; - perspective: 1000px; - } - .carousel-inner > .item.next, - .carousel-inner > .item.active.right { - -webkit-transform: translate3d(100%, 0, 0); - transform: translate3d(100%, 0, 0); - left: 0; - } - .carousel-inner > .item.prev, - .carousel-inner > .item.active.left { - -webkit-transform: translate3d(-100%, 0, 0); - transform: translate3d(-100%, 0, 0); - left: 0; - } - .carousel-inner > .item.next.left, - .carousel-inner > .item.prev.right, - .carousel-inner > .item.active { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - left: 0; - } -} -.carousel-inner > .active, -.carousel-inner > .next, -.carousel-inner > .prev { - display: block; -} -.carousel-inner > .active { - left: 0; -} -.carousel-inner > .next, -.carousel-inner > .prev { - position: absolute; - top: 0; - width: 100%; -} -.carousel-inner > .next { - left: 100%; -} -.carousel-inner > .prev { - left: -100%; -} -.carousel-inner > .next.left, -.carousel-inner > .prev.right { - left: 0; -} -.carousel-inner > .active.left { - left: -100%; -} -.carousel-inner > .active.right { - left: 100%; -} -.carousel-control { - position: absolute; - top: 0; - bottom: 0; - left: 0; - width: 15%; - font-size: 20px; - color: #fff; - text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); - background-color: rgba(0, 0, 0, 0); - filter: alpha(opacity=50); - opacity: 0.5; -} -.carousel-control.left { - background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); - background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); - background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.0001))); - background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); - background-repeat: repeat-x; -} -.carousel-control.right { - right: 0; - left: auto; - background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); - background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); - background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.0001)), to(rgba(0, 0, 0, 0.5))); - background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); - background-repeat: repeat-x; -} -.carousel-control:hover, -.carousel-control:focus { - color: #fff; - text-decoration: none; - outline: 0; - filter: alpha(opacity=90); - opacity: 0.9; -} -.carousel-control .icon-prev, -.carousel-control .icon-next, -.carousel-control .glyphicon-chevron-left, -.carousel-control .glyphicon-chevron-right { - position: absolute; - top: 50%; - z-index: 5; - display: inline-block; - margin-top: -10px; -} -.carousel-control .icon-prev, -.carousel-control .glyphicon-chevron-left { - left: 50%; - margin-left: -10px; -} -.carousel-control .icon-next, -.carousel-control .glyphicon-chevron-right { - right: 50%; - margin-right: -10px; -} -.carousel-control .icon-prev, -.carousel-control .icon-next { - width: 20px; - height: 20px; - font-family: serif; - line-height: 1; -} -.carousel-control .icon-prev:before { - content: "\2039"; -} -.carousel-control .icon-next:before { - content: "\203a"; -} -.carousel-indicators { - position: absolute; - bottom: 10px; - left: 50%; - z-index: 15; - width: 60%; - padding-left: 0; - margin-left: -30%; - text-align: center; - list-style: none; -} -.carousel-indicators li { - display: inline-block; - width: 10px; - height: 10px; - margin: 1px; - text-indent: -999px; - cursor: pointer; - background-color: #000 \9; - background-color: rgba(0, 0, 0, 0); - border: 1px solid #fff; - border-radius: 10px; -} -.carousel-indicators .active { - width: 12px; - height: 12px; - margin: 0; - background-color: #fff; -} -.carousel-caption { - position: absolute; - right: 15%; - bottom: 20px; - left: 15%; - z-index: 10; - padding-top: 20px; - padding-bottom: 20px; - color: #fff; - text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); -} -.carousel-caption .btn { - text-shadow: none; -} -@media screen and (min-width: 768px) { - .carousel-control .glyphicon-chevron-left, - .carousel-control .glyphicon-chevron-right, - .carousel-control .icon-prev, - .carousel-control .icon-next { - width: 30px; - height: 30px; - margin-top: -10px; - font-size: 30px; - } - .carousel-control .glyphicon-chevron-left, - .carousel-control .icon-prev { - margin-left: -10px; - } - .carousel-control .glyphicon-chevron-right, - .carousel-control .icon-next { - margin-right: -10px; - } - .carousel-caption { - right: 20%; - left: 20%; - padding-bottom: 30px; - } - .carousel-indicators { - bottom: 20px; - } -} -.clearfix:before, -.clearfix:after, -.dl-horizontal dd:before, -.dl-horizontal dd:after, -.container:before, -.container:after, -.container-fluid:before, -.container-fluid:after, -.row:before, -.row:after, -.form-horizontal .form-group:before, -.form-horizontal .form-group:after, -.btn-toolbar:before, -.btn-toolbar:after, -.btn-group-vertical > .btn-group:before, -.btn-group-vertical > .btn-group:after, -.nav:before, -.nav:after, -.navbar:before, -.navbar:after, -.navbar-header:before, -.navbar-header:after, -.navbar-collapse:before, -.navbar-collapse:after, -.pager:before, -.pager:after, -.panel-body:before, -.panel-body:after, -.modal-header:before, -.modal-header:after, -.modal-footer:before, -.modal-footer:after { - display: table; - content: " "; -} -.clearfix:after, -.dl-horizontal dd:after, -.container:after, -.container-fluid:after, -.row:after, -.form-horizontal .form-group:after, -.btn-toolbar:after, -.btn-group-vertical > .btn-group:after, -.nav:after, -.navbar:after, -.navbar-header:after, -.navbar-collapse:after, -.pager:after, -.panel-body:after, -.modal-header:after, -.modal-footer:after { - clear: both; -} -.center-block { - display: block; - margin-right: auto; - margin-left: auto; -} -.pull-right { - float: right !important; -} -.pull-left { - float: left !important; -} -.hide { - display: none !important; -} -.show { - display: block !important; -} -.invisible { - visibility: hidden; -} -.text-hide { - font: 0/0 a; - color: transparent; - text-shadow: none; - background-color: transparent; - border: 0; -} -.hidden { - display: none !important; -} -.affix { - position: fixed; -} -@-ms-viewport { - width: device-width; -} -.visible-xs, -.visible-sm, -.visible-md, -.visible-lg { - display: none !important; -} -.visible-xs-block, -.visible-xs-inline, -.visible-xs-inline-block, -.visible-sm-block, -.visible-sm-inline, -.visible-sm-inline-block, -.visible-md-block, -.visible-md-inline, -.visible-md-inline-block, -.visible-lg-block, -.visible-lg-inline, -.visible-lg-inline-block { - display: none !important; -} -@media (max-width: 767px) { - .visible-xs { - display: block !important; - } - table.visible-xs { - display: table !important; - } - tr.visible-xs { - display: table-row !important; - } - th.visible-xs, - td.visible-xs { - display: table-cell !important; - } -} -@media (max-width: 767px) { - .visible-xs-block { - display: block !important; - } -} -@media (max-width: 767px) { - .visible-xs-inline { - display: inline !important; - } -} -@media (max-width: 767px) { - .visible-xs-inline-block { - display: inline-block !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm { - display: block !important; - } - table.visible-sm { - display: table !important; - } - tr.visible-sm { - display: table-row !important; - } - th.visible-sm, - td.visible-sm { - display: table-cell !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm-block { - display: block !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm-inline { - display: inline !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm-inline-block { - display: inline-block !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md { - display: block !important; - } - table.visible-md { - display: table !important; - } - tr.visible-md { - display: table-row !important; - } - th.visible-md, - td.visible-md { - display: table-cell !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md-block { - display: block !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md-inline { - display: inline !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md-inline-block { - display: inline-block !important; - } -} -@media (min-width: 1200px) { - .visible-lg { - display: block !important; - } - table.visible-lg { - display: table !important; - } - tr.visible-lg { - display: table-row !important; - } - th.visible-lg, - td.visible-lg { - display: table-cell !important; - } -} -@media (min-width: 1200px) { - .visible-lg-block { - display: block !important; - } -} -@media (min-width: 1200px) { - .visible-lg-inline { - display: inline !important; - } -} -@media (min-width: 1200px) { - .visible-lg-inline-block { - display: inline-block !important; - } -} -@media (max-width: 767px) { - .hidden-xs { - display: none !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .hidden-sm { - display: none !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .hidden-md { - display: none !important; - } -} -@media (min-width: 1200px) { - .hidden-lg { - display: none !important; - } -} -.visible-print { - display: none !important; -} -@media print { - .visible-print { - display: block !important; - } - table.visible-print { - display: table !important; - } - tr.visible-print { - display: table-row !important; - } - th.visible-print, - td.visible-print { - display: table-cell !important; - } -} -.visible-print-block { - display: none !important; -} -@media print { - .visible-print-block { - display: block !important; - } -} -.visible-print-inline { - display: none !important; -} -@media print { - .visible-print-inline { - display: inline !important; - } -} -.visible-print-inline-block { - display: none !important; -} -@media print { - .visible-print-inline-block { - display: inline-block !important; - } -} -@media print { - .hidden-print { - display: none !important; - } -} -/*# sourceMappingURL=bootstrap.css.map */ \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/resources/static/oauth/css/bootstrap.css.map b/springboot/wumei-iot/src/main/resources/static/oauth/css/bootstrap.css.map deleted file mode 100644 index caac3e61..00000000 --- a/springboot/wumei-iot/src/main/resources/static/oauth/css/bootstrap.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["bootstrap.css","less/normalize.less","less/print.less","less/glyphicons.less","less/scaffolding.less","less/mixins/vendor-prefixes.less","less/mixins/tab-focus.less","less/mixins/image.less","less/type.less","less/mixins/text-emphasis.less","less/mixins/background-variant.less","less/mixins/text-overflow.less","less/code.less","less/grid.less","less/mixins/grid.less","less/mixins/grid-framework.less","less/tables.less","less/mixins/table-row.less","less/forms.less","less/mixins/forms.less","less/buttons.less","less/mixins/buttons.less","less/mixins/opacity.less","less/component-animations.less","less/dropdowns.less","less/mixins/nav-divider.less","less/mixins/reset-filter.less","less/button-groups.less","less/mixins/border-radius.less","less/input-groups.less","less/navs.less","less/navbar.less","less/mixins/nav-vertical-align.less","less/utilities.less","less/breadcrumbs.less","less/pagination.less","less/mixins/pagination.less","less/pager.less","less/labels.less","less/mixins/labels.less","less/badges.less","less/jumbotron.less","less/thumbnails.less","less/alerts.less","less/mixins/alerts.less","less/progress-bars.less","less/mixins/gradients.less","less/mixins/progress-bar.less","less/media.less","less/list-group.less","less/mixins/list-group.less","less/panels.less","less/mixins/panels.less","less/responsive-embed.less","less/wells.less","less/close.less","less/modals.less","less/tooltip.less","less/mixins/reset-text.less","less/popovers.less","less/carousel.less","less/mixins/clearfix.less","less/mixins/center-block.less","less/mixins/hide-text.less","less/responsive-utilities.less","less/mixins/responsive-visibility.less"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,4EAA4E;ACK5E;EACE,wBAAA;EACA,2BAAA;EACA,+BAAA;CDHD;ACUD;EACE,UAAA;CDRD;ACqBD;;;;;;;;;;;;;EAaE,eAAA;CDnBD;AC2BD;;;;EAIE,sBAAA;EACA,yBAAA;CDzBD;ACiCD;EACE,cAAA;EACA,UAAA;CD/BD;ACuCD;;EAEE,cAAA;CDrCD;AC+CD;EACE,8BAAA;CD7CD;ACqDD;;EAEE,WAAA;CDnDD;AC8DD;EACE,oBAAA;EACA,2BAAA;EACA,0CAAA;EAAA,uCAAA;EAAA,kCAAA;CD5DD;ACmED;;EAEE,kBAAA;CDjED;ACwED;EACE,mBAAA;CDtED;AC8ED;EACE,eAAA;EACA,iBAAA;CD5ED;ACmFD;EACE,iBAAA;EACA,YAAA;CDjFD;ACwFD;EACE,eAAA;CDtFD;AC6FD;;EAEE,eAAA;EACA,eAAA;EACA,mBAAA;EACA,yBAAA;CD3FD;AC8FD;EACE,YAAA;CD5FD;AC+FD;EACE,gBAAA;CD7FD;ACuGD;EACE,UAAA;CDrGD;AC4GD;EACE,iBAAA;CD1GD;ACoHD;EACE,iBAAA;CDlHD;ACyHD;EACE,gCAAA;EAAA,6BAAA;EAAA,wBAAA;EACA,UAAA;CDvHD;AC8HD;EACE,eAAA;CD5HD;ACmID;;;;EAIE,kCAAA;EACA,eAAA;CDjID;ACmJD;;;;;EAKE,eAAA;EACA,cAAA;EACA,UAAA;CDjJD;ACwJD;EACE,kBAAA;CDtJD;ACgKD;;EAEE,qBAAA;CD9JD;ACyKD;;;;EAIE,2BAAA;EACA,gBAAA;CDvKD;AC8KD;;EAEE,gBAAA;CD5KD;ACmLD;;EAEE,UAAA;EACA,WAAA;CDjLD;ACyLD;EACE,oBAAA;CDvLD;ACkMD;;EAEE,+BAAA;EAAA,4BAAA;EAAA,uBAAA;EACA,WAAA;CDhMD;ACyMD;;EAEE,aAAA;CDvMD;AC+MD;EACE,8BAAA;EACA,gCAAA;EAAA,6BAAA;EAAA,wBAAA;CD7MD;ACsND;;EAEE,yBAAA;CDpND;AC2ND;EACE,0BAAA;EACA,cAAA;EACA,+BAAA;CDzND;ACiOD;EACE,UAAA;EACA,WAAA;CD/ND;ACsOD;EACE,eAAA;CDpOD;AC4OD;EACE,kBAAA;CD1OD;ACoPD;EACE,0BAAA;EACA,kBAAA;CDlPD;ACqPD;;EAEE,WAAA;CDnPD;AACD,qFAAqF;AEhLrF;EACE;;;IAGE,uBAAA;IACA,6BAAA;IACA,mCAAA;IACA,oCAAA;IAAA,4BAAA;GFkLD;EE/KD;;IAEE,2BAAA;GFiLD;EE9KD;IACE,6BAAA;GFgLD;EE7KD;IACE,8BAAA;GF+KD;EE1KD;;IAEE,YAAA;GF4KD;EEzKD;;IAEE,uBAAA;IACA,yBAAA;GF2KD;EExKD;IACE,4BAAA;GF0KD;EEvKD;;IAEE,yBAAA;GFyKD;EEtKD;IACE,2BAAA;GFwKD;EErKD;;;IAGE,WAAA;IACA,UAAA;GFuKD;EEpKD;;IAEE,wBAAA;GFsKD;EEhKD;IACE,cAAA;GFkKD;EEhKD;;IAGI,kCAAA;GFiKH;EE9JD;IACE,uBAAA;GFgKD;EE7JD;IACE,qCAAA;GF+JD;EEhKD;;IAKI,kCAAA;GF+JH;EE5JD;;IAGI,kCAAA;GF6JH;CACF;AGnPD;EACE,oCAAA;EACA,sDAAA;EACA,gYAAA;CHqPD;AG7OD;EACE,mBAAA;EACA,SAAA;EACA,sBAAA;EACA,oCAAA;EACA,mBAAA;EACA,iBAAA;EACA,eAAA;EACA,oCAAA;EACA,mCAAA;CH+OD;AG3OmC;EAAW,iBAAA;CH8O9C;AG7OmC;EAAW,iBAAA;CHgP9C;AG9OmC;;EAAW,iBAAA;CHkP9C;AGjPmC;EAAW,iBAAA;CHoP9C;AGnPmC;EAAW,iBAAA;CHsP9C;AGrPmC;EAAW,iBAAA;CHwP9C;AGvPmC;EAAW,iBAAA;CH0P9C;AGzPmC;EAAW,iBAAA;CH4P9C;AG3PmC;EAAW,iBAAA;CH8P9C;AG7PmC;EAAW,iBAAA;CHgQ9C;AG/PmC;EAAW,iBAAA;CHkQ9C;AGjQmC;EAAW,iBAAA;CHoQ9C;AGnQmC;EAAW,iBAAA;CHsQ9C;AGrQmC;EAAW,iBAAA;CHwQ9C;AGvQmC;EAAW,iBAAA;CH0Q9C;AGzQmC;EAAW,iBAAA;CH4Q9C;AG3QmC;EAAW,iBAAA;CH8Q9C;AG7QmC;EAAW,iBAAA;CHgR9C;AG/QmC;EAAW,iBAAA;CHkR9C;AGjRmC;EAAW,iBAAA;CHoR9C;AGnRmC;EAAW,iBAAA;CHsR9C;AGrRmC;EAAW,iBAAA;CHwR9C;AGvRmC;EAAW,iBAAA;CH0R9C;AGzRmC;EAAW,iBAAA;CH4R9C;AG3RmC;EAAW,iBAAA;CH8R9C;AG7RmC;EAAW,iBAAA;CHgS9C;AG/RmC;EAAW,iBAAA;CHkS9C;AGjSmC;EAAW,iBAAA;CHoS9C;AGnSmC;EAAW,iBAAA;CHsS9C;AGrSmC;EAAW,iBAAA;CHwS9C;AGvSmC;EAAW,iBAAA;CH0S9C;AGzSmC;EAAW,iBAAA;CH4S9C;AG3SmC;EAAW,iBAAA;CH8S9C;AG7SmC;EAAW,iBAAA;CHgT9C;AG/SmC;EAAW,iBAAA;CHkT9C;AGjTmC;EAAW,iBAAA;CHoT9C;AGnTmC;EAAW,iBAAA;CHsT9C;AGrTmC;EAAW,iBAAA;CHwT9C;AGvTmC;EAAW,iBAAA;CH0T9C;AGzTmC;EAAW,iBAAA;CH4T9C;AG3TmC;EAAW,iBAAA;CH8T9C;AG7TmC;EAAW,iBAAA;CHgU9C;AG/TmC;EAAW,iBAAA;CHkU9C;AGjUmC;EAAW,iBAAA;CHoU9C;AGnUmC;EAAW,iBAAA;CHsU9C;AGrUmC;EAAW,iBAAA;CHwU9C;AGvUmC;EAAW,iBAAA;CH0U9C;AGzUmC;EAAW,iBAAA;CH4U9C;AG3UmC;EAAW,iBAAA;CH8U9C;AG7UmC;EAAW,iBAAA;CHgV9C;AG/UmC;EAAW,iBAAA;CHkV9C;AGjVmC;EAAW,iBAAA;CHoV9C;AGnVmC;EAAW,iBAAA;CHsV9C;AGrVmC;EAAW,iBAAA;CHwV9C;AGvVmC;EAAW,iBAAA;CH0V9C;AGzVmC;EAAW,iBAAA;CH4V9C;AG3VmC;EAAW,iBAAA;CH8V9C;AG7VmC;EAAW,iBAAA;CHgW9C;AG/VmC;EAAW,iBAAA;CHkW9C;AGjWmC;EAAW,iBAAA;CHoW9C;AGnWmC;EAAW,iBAAA;CHsW9C;AGrWmC;EAAW,iBAAA;CHwW9C;AGvWmC;EAAW,iBAAA;CH0W9C;AGzWmC;EAAW,iBAAA;CH4W9C;AG3WmC;EAAW,iBAAA;CH8W9C;AG7WmC;EAAW,iBAAA;CHgX9C;AG/WmC;EAAW,iBAAA;CHkX9C;AGjXmC;EAAW,iBAAA;CHoX9C;AGnXmC;EAAW,iBAAA;CHsX9C;AGrXmC;EAAW,iBAAA;CHwX9C;AGvXmC;EAAW,iBAAA;CH0X9C;AGzXmC;EAAW,iBAAA;CH4X9C;AG3XmC;EAAW,iBAAA;CH8X9C;AG7XmC;EAAW,iBAAA;CHgY9C;AG/XmC;EAAW,iBAAA;CHkY9C;AGjYmC;EAAW,iBAAA;CHoY9C;AGnYmC;EAAW,iBAAA;CHsY9C;AGrYmC;EAAW,iBAAA;CHwY9C;AGvYmC;EAAW,iBAAA;CH0Y9C;AGzYmC;EAAW,iBAAA;CH4Y9C;AG3YmC;EAAW,iBAAA;CH8Y9C;AG7YmC;EAAW,iBAAA;CHgZ9C;AG/YmC;EAAW,iBAAA;CHkZ9C;AGjZmC;EAAW,iBAAA;CHoZ9C;AGnZmC;EAAW,iBAAA;CHsZ9C;AGrZmC;EAAW,iBAAA;CHwZ9C;AGvZmC;EAAW,iBAAA;CH0Z9C;AGzZmC;EAAW,iBAAA;CH4Z9C;AG3ZmC;EAAW,iBAAA;CH8Z9C;AG7ZmC;EAAW,iBAAA;CHga9C;AG/ZmC;EAAW,iBAAA;CHka9C;AGjamC;EAAW,iBAAA;CHoa9C;AGnamC;EAAW,iBAAA;CHsa9C;AGramC;EAAW,iBAAA;CHwa9C;AGvamC;EAAW,iBAAA;CH0a9C;AGzamC;EAAW,iBAAA;CH4a9C;AG3amC;EAAW,iBAAA;CH8a9C;AG7amC;EAAW,iBAAA;CHgb9C;AG/amC;EAAW,iBAAA;CHkb9C;AGjbmC;EAAW,iBAAA;CHob9C;AGnbmC;EAAW,iBAAA;CHsb9C;AGrbmC;EAAW,iBAAA;CHwb9C;AGvbmC;EAAW,iBAAA;CH0b9C;AGzbmC;EAAW,iBAAA;CH4b9C;AG3bmC;EAAW,iBAAA;CH8b9C;AG7bmC;EAAW,iBAAA;CHgc9C;AG/bmC;EAAW,iBAAA;CHkc9C;AGjcmC;EAAW,iBAAA;CHoc9C;AGncmC;EAAW,iBAAA;CHsc9C;AGrcmC;EAAW,iBAAA;CHwc9C;AGvcmC;EAAW,iBAAA;CH0c9C;AGzcmC;EAAW,iBAAA;CH4c9C;AG3cmC;EAAW,iBAAA;CH8c9C;AG7cmC;EAAW,iBAAA;CHgd9C;AG/cmC;EAAW,iBAAA;CHkd9C;AGjdmC;EAAW,iBAAA;CHod9C;AGndmC;EAAW,iBAAA;CHsd9C;AGrdmC;EAAW,iBAAA;CHwd9C;AGvdmC;EAAW,iBAAA;CH0d9C;AGzdmC;EAAW,iBAAA;CH4d9C;AG3dmC;EAAW,iBAAA;CH8d9C;AG7dmC;EAAW,iBAAA;CHge9C;AG/dmC;EAAW,iBAAA;CHke9C;AGjemC;EAAW,iBAAA;CHoe9C;AGnemC;EAAW,iBAAA;CHse9C;AGremC;EAAW,iBAAA;CHwe9C;AGvemC;EAAW,iBAAA;CH0e9C;AGzemC;EAAW,iBAAA;CH4e9C;AG3emC;EAAW,iBAAA;CH8e9C;AG7emC;EAAW,iBAAA;CHgf9C;AG/emC;EAAW,iBAAA;CHkf9C;AGjfmC;EAAW,iBAAA;CHof9C;AGnfmC;EAAW,iBAAA;CHsf9C;AGrfmC;EAAW,iBAAA;CHwf9C;AGvfmC;EAAW,iBAAA;CH0f9C;AGzfmC;EAAW,iBAAA;CH4f9C;AG3fmC;EAAW,iBAAA;CH8f9C;AG7fmC;EAAW,iBAAA;CHggB9C;AG/fmC;EAAW,iBAAA;CHkgB9C;AGjgBmC;EAAW,iBAAA;CHogB9C;AGngBmC;EAAW,iBAAA;CHsgB9C;AGrgBmC;EAAW,iBAAA;CHwgB9C;AGvgBmC;EAAW,iBAAA;CH0gB9C;AGzgBmC;EAAW,iBAAA;CH4gB9C;AG3gBmC;EAAW,iBAAA;CH8gB9C;AG7gBmC;EAAW,iBAAA;CHghB9C;AG/gBmC;EAAW,iBAAA;CHkhB9C;AGjhBmC;EAAW,iBAAA;CHohB9C;AGnhBmC;EAAW,iBAAA;CHshB9C;AGrhBmC;EAAW,iBAAA;CHwhB9C;AGvhBmC;EAAW,iBAAA;CH0hB9C;AGzhBmC;EAAW,iBAAA;CH4hB9C;AG3hBmC;EAAW,iBAAA;CH8hB9C;AG7hBmC;EAAW,iBAAA;CHgiB9C;AG/hBmC;EAAW,iBAAA;CHkiB9C;AGjiBmC;EAAW,iBAAA;CHoiB9C;AGniBmC;EAAW,iBAAA;CHsiB9C;AGriBmC;EAAW,iBAAA;CHwiB9C;AGviBmC;EAAW,iBAAA;CH0iB9C;AGziBmC;EAAW,iBAAA;CH4iB9C;AG3iBmC;EAAW,iBAAA;CH8iB9C;AG7iBmC;EAAW,iBAAA;CHgjB9C;AG/iBmC;EAAW,iBAAA;CHkjB9C;AGjjBmC;EAAW,iBAAA;CHojB9C;AGnjBmC;EAAW,iBAAA;CHsjB9C;AGrjBmC;EAAW,iBAAA;CHwjB9C;AGvjBmC;EAAW,iBAAA;CH0jB9C;AGzjBmC;EAAW,iBAAA;CH4jB9C;AG3jBmC;EAAW,iBAAA;CH8jB9C;AG7jBmC;EAAW,iBAAA;CHgkB9C;AG/jBmC;EAAW,iBAAA;CHkkB9C;AGjkBmC;EAAW,iBAAA;CHokB9C;AGnkBmC;EAAW,iBAAA;CHskB9C;AGrkBmC;EAAW,iBAAA;CHwkB9C;AGvkBmC;EAAW,iBAAA;CH0kB9C;AGzkBmC;EAAW,iBAAA;CH4kB9C;AG3kBmC;EAAW,iBAAA;CH8kB9C;AG7kBmC;EAAW,iBAAA;CHglB9C;AG/kBmC;EAAW,iBAAA;CHklB9C;AGjlBmC;EAAW,iBAAA;CHolB9C;AGnlBmC;EAAW,iBAAA;CHslB9C;AGrlBmC;EAAW,iBAAA;CHwlB9C;AGvlBmC;EAAW,iBAAA;CH0lB9C;AGzlBmC;EAAW,iBAAA;CH4lB9C;AG3lBmC;EAAW,iBAAA;CH8lB9C;AG7lBmC;EAAW,iBAAA;CHgmB9C;AG/lBmC;EAAW,iBAAA;CHkmB9C;AGjmBmC;EAAW,iBAAA;CHomB9C;AGnmBmC;EAAW,iBAAA;CHsmB9C;AGrmBmC;EAAW,iBAAA;CHwmB9C;AGvmBmC;EAAW,iBAAA;CH0mB9C;AGzmBmC;EAAW,iBAAA;CH4mB9C;AG3mBmC;EAAW,iBAAA;CH8mB9C;AG7mBmC;EAAW,iBAAA;CHgnB9C;AG/mBmC;EAAW,iBAAA;CHknB9C;AGjnBmC;EAAW,iBAAA;CHonB9C;AGnnBmC;EAAW,iBAAA;CHsnB9C;AGrnBmC;EAAW,iBAAA;CHwnB9C;AGvnBmC;EAAW,iBAAA;CH0nB9C;AGznBmC;EAAW,iBAAA;CH4nB9C;AG3nBmC;EAAW,iBAAA;CH8nB9C;AG7nBmC;EAAW,iBAAA;CHgoB9C;AG/nBmC;EAAW,iBAAA;CHkoB9C;AGjoBmC;EAAW,iBAAA;CHooB9C;AGnoBmC;EAAW,iBAAA;CHsoB9C;AGroBmC;EAAW,iBAAA;CHwoB9C;AG/nBmC;EAAW,iBAAA;CHkoB9C;AGjoBmC;EAAW,iBAAA;CHooB9C;AGnoBmC;EAAW,iBAAA;CHsoB9C;AGroBmC;EAAW,iBAAA;CHwoB9C;AGvoBmC;EAAW,iBAAA;CH0oB9C;AGzoBmC;EAAW,iBAAA;CH4oB9C;AG3oBmC;EAAW,iBAAA;CH8oB9C;AG7oBmC;EAAW,iBAAA;CHgpB9C;AG/oBmC;EAAW,iBAAA;CHkpB9C;AGjpBmC;EAAW,iBAAA;CHopB9C;AGnpBmC;EAAW,iBAAA;CHspB9C;AGrpBmC;EAAW,iBAAA;CHwpB9C;AGvpBmC;EAAW,iBAAA;CH0pB9C;AGzpBmC;EAAW,iBAAA;CH4pB9C;AG3pBmC;EAAW,iBAAA;CH8pB9C;AG7pBmC;EAAW,iBAAA;CHgqB9C;AG/pBmC;EAAW,iBAAA;CHkqB9C;AGjqBmC;EAAW,iBAAA;CHoqB9C;AGnqBmC;EAAW,iBAAA;CHsqB9C;AGrqBmC;EAAW,iBAAA;CHwqB9C;AGvqBmC;EAAW,iBAAA;CH0qB9C;AGzqBmC;EAAW,iBAAA;CH4qB9C;AG3qBmC;EAAW,iBAAA;CH8qB9C;AG7qBmC;EAAW,iBAAA;CHgrB9C;AG/qBmC;EAAW,iBAAA;CHkrB9C;AGjrBmC;EAAW,iBAAA;CHorB9C;AGnrBmC;EAAW,iBAAA;CHsrB9C;AGrrBmC;EAAW,iBAAA;CHwrB9C;AGvrBmC;EAAW,iBAAA;CH0rB9C;AGzrBmC;EAAW,iBAAA;CH4rB9C;AG3rBmC;EAAW,iBAAA;CH8rB9C;AG7rBmC;EAAW,iBAAA;CHgsB9C;AG/rBmC;EAAW,iBAAA;CHksB9C;AGjsBmC;EAAW,iBAAA;CHosB9C;AGnsBmC;EAAW,iBAAA;CHssB9C;AGrsBmC;EAAW,iBAAA;CHwsB9C;AGvsBmC;EAAW,iBAAA;CH0sB9C;AGzsBmC;EAAW,iBAAA;CH4sB9C;AG3sBmC;EAAW,iBAAA;CH8sB9C;AG7sBmC;EAAW,iBAAA;CHgtB9C;AG/sBmC;EAAW,iBAAA;CHktB9C;AGjtBmC;EAAW,iBAAA;CHotB9C;AGntBmC;EAAW,iBAAA;CHstB9C;AGrtBmC;EAAW,iBAAA;CHwtB9C;AGvtBmC;EAAW,iBAAA;CH0tB9C;AGztBmC;EAAW,iBAAA;CH4tB9C;AG3tBmC;EAAW,iBAAA;CH8tB9C;AG7tBmC;EAAW,iBAAA;CHguB9C;AG/tBmC;EAAW,iBAAA;CHkuB9C;AGjuBmC;EAAW,iBAAA;CHouB9C;AGnuBmC;EAAW,iBAAA;CHsuB9C;AGruBmC;EAAW,iBAAA;CHwuB9C;AGvuBmC;EAAW,iBAAA;CH0uB9C;AGzuBmC;EAAW,iBAAA;CH4uB9C;AG3uBmC;EAAW,iBAAA;CH8uB9C;AG7uBmC;EAAW,iBAAA;CHgvB9C;AIxhCD;ECkEE,+BAAA;EACG,4BAAA;EACK,uBAAA;CLy9BT;AI1hCD;;EC+DE,+BAAA;EACG,4BAAA;EACK,uBAAA;CL+9BT;AIxhCD;EACE,gBAAA;EACA,8CAAA;CJ0hCD;AIvhCD;EACE,4DAAA;EACA,gBAAA;EACA,wBAAA;EACA,eAAA;EACA,uBAAA;CJyhCD;AIrhCD;;;;EAIE,qBAAA;EACA,mBAAA;EACA,qBAAA;CJuhCD;AIjhCD;EACE,eAAA;EACA,sBAAA;CJmhCD;AIjhCC;;EAEE,eAAA;EACA,2BAAA;CJmhCH;AIhhCC;EEnDA,2CAAA;EACA,qBAAA;CNskCD;AIzgCD;EACE,UAAA;CJ2gCD;AIrgCD;EACE,uBAAA;CJugCD;AIngCD;;;;;EG1EE,eAAA;EACA,gBAAA;EACA,aAAA;CPolCD;AIvgCD;EACE,mBAAA;CJygCD;AIngCD;EACE,aAAA;EACA,wBAAA;EACA,uBAAA;EACA,uBAAA;EACA,mBAAA;EC+FA,yCAAA;EACK,oCAAA;EACG,iCAAA;EE5LR,sBAAA;EACA,gBAAA;EACA,aAAA;CPomCD;AIngCD;EACE,mBAAA;CJqgCD;AI//BD;EACE,iBAAA;EACA,oBAAA;EACA,UAAA;EACA,8BAAA;CJigCD;AIz/BD;EACE,mBAAA;EACA,WAAA;EACA,YAAA;EACA,WAAA;EACA,aAAA;EACA,iBAAA;EACA,uBAAA;EACA,UAAA;CJ2/BD;AIn/BC;;EAEE,iBAAA;EACA,YAAA;EACA,aAAA;EACA,UAAA;EACA,kBAAA;EACA,WAAA;CJq/BH;AI1+BD;EACE,gBAAA;CJ4+BD;AQjoCD;;;;;;;;;;;;EAEE,qBAAA;EACA,iBAAA;EACA,iBAAA;EACA,eAAA;CR6oCD;AQlpCD;;;;;;;;;;;;;;;;;;;;;;;;EASI,iBAAA;EACA,eAAA;EACA,eAAA;CRmqCH;AQ/pCD;;;;;;EAGE,iBAAA;EACA,oBAAA;CRoqCD;AQxqCD;;;;;;;;;;;;EAQI,eAAA;CR8qCH;AQ3qCD;;;;;;EAGE,iBAAA;EACA,oBAAA;CRgrCD;AQprCD;;;;;;;;;;;;EAQI,eAAA;CR0rCH;AQtrCD;;EAAU,gBAAA;CR0rCT;AQzrCD;;EAAU,gBAAA;CR6rCT;AQ5rCD;;EAAU,gBAAA;CRgsCT;AQ/rCD;;EAAU,gBAAA;CRmsCT;AQlsCD;;EAAU,gBAAA;CRssCT;AQrsCD;;EAAU,gBAAA;CRysCT;AQnsCD;EACE,iBAAA;CRqsCD;AQlsCD;EACE,oBAAA;EACA,gBAAA;EACA,iBAAA;EACA,iBAAA;CRosCD;AQlsCC;EAAA;IACE,gBAAA;GRqsCD;CACF;AQ7rCD;;EAEE,eAAA;CR+rCD;AQ5rCD;;EAEE,eAAA;EACA,0BAAA;CR8rCD;AQ1rCD;EAAuB,iBAAA;CR6rCtB;AQ5rCD;EAAuB,kBAAA;CR+rCtB;AQ9rCD;EAAuB,mBAAA;CRisCtB;AQhsCD;EAAuB,oBAAA;CRmsCtB;AQlsCD;EAAuB,oBAAA;CRqsCtB;AQlsCD;EAAuB,0BAAA;CRqsCtB;AQpsCD;EAAuB,0BAAA;CRusCtB;AQtsCD;EAAuB,2BAAA;CRysCtB;AQtsCD;EACE,eAAA;CRwsCD;AQtsCD;ECvGE,eAAA;CTgzCD;AS/yCC;;EAEE,eAAA;CTizCH;AQ1sCD;EC1GE,eAAA;CTuzCD;AStzCC;;EAEE,eAAA;CTwzCH;AQ9sCD;EC7GE,eAAA;CT8zCD;AS7zCC;;EAEE,eAAA;CT+zCH;AQltCD;EChHE,eAAA;CTq0CD;ASp0CC;;EAEE,eAAA;CTs0CH;AQttCD;ECnHE,eAAA;CT40CD;AS30CC;;EAEE,eAAA;CT60CH;AQttCD;EAGE,YAAA;EE7HA,0BAAA;CVo1CD;AUn1CC;;EAEE,0BAAA;CVq1CH;AQxtCD;EEhIE,0BAAA;CV21CD;AU11CC;;EAEE,0BAAA;CV41CH;AQ5tCD;EEnIE,0BAAA;CVk2CD;AUj2CC;;EAEE,0BAAA;CVm2CH;AQhuCD;EEtIE,0BAAA;CVy2CD;AUx2CC;;EAEE,0BAAA;CV02CH;AQpuCD;EEzIE,0BAAA;CVg3CD;AU/2CC;;EAEE,0BAAA;CVi3CH;AQnuCD;EACE,oBAAA;EACA,oBAAA;EACA,iCAAA;CRquCD;AQ7tCD;;EAEE,cAAA;EACA,oBAAA;CR+tCD;AQluCD;;;;EAMI,iBAAA;CRkuCH;AQ3tCD;EACE,gBAAA;EACA,iBAAA;CR6tCD;AQztCD;EALE,gBAAA;EACA,iBAAA;EAMA,kBAAA;CR4tCD;AQ9tCD;EAKI,sBAAA;EACA,mBAAA;EACA,kBAAA;CR4tCH;AQvtCD;EACE,cAAA;EACA,oBAAA;CRytCD;AQvtCD;;EAEE,wBAAA;CRytCD;AQvtCD;EACE,iBAAA;CRytCD;AQvtCD;EACE,eAAA;CRytCD;AQ5sCC;EAAA;IAEI,YAAA;IACA,aAAA;IACA,YAAA;IACA,kBAAA;IGxNJ,iBAAA;IACA,wBAAA;IACA,oBAAA;GXu6CC;EQttCD;IASI,mBAAA;GRgtCH;CACF;AQtsCD;;EAEE,aAAA;CRwsCD;AQrsCD;EACE,eAAA;EA9IqB,0BAAA;CRs1CtB;AQnsCD;EACE,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,+BAAA;CRqsCD;AQhsCG;;;EACE,iBAAA;CRosCL;AQ9sCD;;;EAmBI,eAAA;EACA,eAAA;EACA,wBAAA;EACA,eAAA;CRgsCH;AQ9rCG;;;EACE,uBAAA;CRksCL;AQ1rCD;;EAEE,oBAAA;EACA,gBAAA;EACA,kBAAA;EACA,gCAAA;EACA,eAAA;CR4rCD;AQtrCG;;;;;;EAAW,YAAA;CR8rCd;AQ7rCG;;;;;;EACE,uBAAA;CRosCL;AQ9rCD;EACE,oBAAA;EACA,mBAAA;EACA,wBAAA;CRgsCD;AYx+CD;;;;EAIE,+DAAA;CZ0+CD;AYt+CD;EACE,iBAAA;EACA,eAAA;EACA,eAAA;EACA,0BAAA;EACA,mBAAA;CZw+CD;AYp+CD;EACE,iBAAA;EACA,eAAA;EACA,YAAA;EACA,uBAAA;EACA,mBAAA;EACA,uDAAA;EAAA,+CAAA;CZs+CD;AY5+CD;EASI,WAAA;EACA,gBAAA;EACA,iBAAA;EACA,yBAAA;EAAA,iBAAA;CZs+CH;AYj+CD;EACE,eAAA;EACA,eAAA;EACA,iBAAA;EACA,gBAAA;EACA,wBAAA;EACA,eAAA;EACA,sBAAA;EACA,sBAAA;EACA,0BAAA;EACA,uBAAA;EACA,mBAAA;CZm+CD;AY9+CD;EAeI,WAAA;EACA,mBAAA;EACA,eAAA;EACA,sBAAA;EACA,8BAAA;EACA,iBAAA;CZk+CH;AY79CD;EACE,kBAAA;EACA,mBAAA;CZ+9CD;AazhDD;ECHE,oBAAA;EACA,mBAAA;EACA,mBAAA;EACA,kBAAA;Cd+hDD;Aa5hDC;EAAA;IACE,aAAA;Gb+hDD;CACF;Aa9hDC;EAAA;IACE,aAAA;GbiiDD;CACF;AahiDC;EAAA;IACE,cAAA;GbmiDD;CACF;Aa1hDD;ECvBE,oBAAA;EACA,mBAAA;EACA,mBAAA;EACA,kBAAA;CdojDD;AavhDD;ECvBE,oBAAA;EACA,mBAAA;CdijDD;AavhDD;EACE,gBAAA;EACA,eAAA;CbyhDD;Aa3hDD;EAKI,iBAAA;EACA,gBAAA;CbyhDH;AczkDA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECiBK,mBAAA;EAEA,gBAAA;EAEA,oBAAA;EACA,mBAAA;CfwmDL;Ac9nDA;;;;;;;;;;;;ECuCK,YAAA;CfqmDL;Ac5oDA;EC+CG,YAAA;CfgmDH;Ac/oDA;EC+CG,oBAAA;CfmmDH;AclpDA;EC+CG,oBAAA;CfsmDH;AcrpDA;EC+CG,WAAA;CfymDH;AcxpDA;EC+CG,oBAAA;Cf4mDH;Ac3pDA;EC+CG,oBAAA;Cf+mDH;Ac9pDA;EC+CG,WAAA;CfknDH;AcjqDA;EC+CG,oBAAA;CfqnDH;AcpqDA;EC+CG,oBAAA;CfwnDH;AcvqDA;EC+CG,WAAA;Cf2nDH;Ac1qDA;EC+CG,oBAAA;Cf8nDH;Ac7qDA;EC+CG,mBAAA;CfioDH;AchrDA;EC8DG,YAAA;CfqnDH;AcnrDA;EC8DG,oBAAA;CfwnDH;ActrDA;EC8DG,oBAAA;Cf2nDH;AczrDA;EC8DG,WAAA;Cf8nDH;Ac5rDA;EC8DG,oBAAA;CfioDH;Ac/rDA;EC8DG,oBAAA;CfooDH;AclsDA;EC8DG,WAAA;CfuoDH;AcrsDA;EC8DG,oBAAA;Cf0oDH;AcxsDA;EC8DG,oBAAA;Cf6oDH;Ac3sDA;EC8DG,WAAA;CfgpDH;Ac9sDA;EC8DG,oBAAA;CfmpDH;AcjtDA;EC8DG,mBAAA;CfspDH;AcptDA;ECmEG,YAAA;CfopDH;AcvtDA;ECoDG,WAAA;CfsqDH;Ac1tDA;ECoDG,mBAAA;CfyqDH;Ac7tDA;ECoDG,mBAAA;Cf4qDH;AchuDA;ECoDG,UAAA;Cf+qDH;AcnuDA;ECoDG,mBAAA;CfkrDH;ActuDA;ECoDG,mBAAA;CfqrDH;AczuDA;ECoDG,UAAA;CfwrDH;Ac5uDA;ECoDG,mBAAA;Cf2rDH;Ac/uDA;ECoDG,mBAAA;Cf8rDH;AclvDA;ECoDG,UAAA;CfisDH;AcrvDA;ECoDG,mBAAA;CfosDH;AcxvDA;ECoDG,kBAAA;CfusDH;Ac3vDA;ECyDG,WAAA;CfqsDH;Ac9vDA;ECwEG,kBAAA;CfyrDH;AcjwDA;ECwEG,0BAAA;Cf4rDH;AcpwDA;ECwEG,0BAAA;Cf+rDH;AcvwDA;ECwEG,iBAAA;CfksDH;Ac1wDA;ECwEG,0BAAA;CfqsDH;Ac7wDA;ECwEG,0BAAA;CfwsDH;AchxDA;ECwEG,iBAAA;Cf2sDH;AcnxDA;ECwEG,0BAAA;Cf8sDH;ActxDA;ECwEG,0BAAA;CfitDH;AczxDA;ECwEG,iBAAA;CfotDH;Ac5xDA;ECwEG,0BAAA;CfutDH;Ac/xDA;ECwEG,yBAAA;Cf0tDH;AclyDA;ECwEG,gBAAA;Cf6tDH;Aa5tDD;ECzEC;;;;;;;;;;;;ICuCK,YAAA;Gf6wDH;EcpzDF;IC+CG,YAAA;GfwwDD;EcvzDF;IC+CG,oBAAA;Gf2wDD;Ec1zDF;IC+CG,oBAAA;Gf8wDD;Ec7zDF;IC+CG,WAAA;GfixDD;Ech0DF;IC+CG,oBAAA;GfoxDD;Ecn0DF;IC+CG,oBAAA;GfuxDD;Ect0DF;IC+CG,WAAA;Gf0xDD;Ecz0DF;IC+CG,oBAAA;Gf6xDD;Ec50DF;IC+CG,oBAAA;GfgyDD;Ec/0DF;IC+CG,WAAA;GfmyDD;Ecl1DF;IC+CG,oBAAA;GfsyDD;Ecr1DF;IC+CG,mBAAA;GfyyDD;Ecx1DF;IC8DG,YAAA;Gf6xDD;Ec31DF;IC8DG,oBAAA;GfgyDD;Ec91DF;IC8DG,oBAAA;GfmyDD;Ecj2DF;IC8DG,WAAA;GfsyDD;Ecp2DF;IC8DG,oBAAA;GfyyDD;Ecv2DF;IC8DG,oBAAA;Gf4yDD;Ec12DF;IC8DG,WAAA;Gf+yDD;Ec72DF;IC8DG,oBAAA;GfkzDD;Ech3DF;IC8DG,oBAAA;GfqzDD;Ecn3DF;IC8DG,WAAA;GfwzDD;Ect3DF;IC8DG,oBAAA;Gf2zDD;Ecz3DF;IC8DG,mBAAA;Gf8zDD;Ec53DF;ICmEG,YAAA;Gf4zDD;Ec/3DF;ICoDG,WAAA;Gf80DD;Ecl4DF;ICoDG,mBAAA;Gfi1DD;Ecr4DF;ICoDG,mBAAA;Gfo1DD;Ecx4DF;ICoDG,UAAA;Gfu1DD;Ec34DF;ICoDG,mBAAA;Gf01DD;Ec94DF;ICoDG,mBAAA;Gf61DD;Ecj5DF;ICoDG,UAAA;Gfg2DD;Ecp5DF;ICoDG,mBAAA;Gfm2DD;Ecv5DF;ICoDG,mBAAA;Gfs2DD;Ec15DF;ICoDG,UAAA;Gfy2DD;Ec75DF;ICoDG,mBAAA;Gf42DD;Ech6DF;ICoDG,kBAAA;Gf+2DD;Ecn6DF;ICyDG,WAAA;Gf62DD;Ect6DF;ICwEG,kBAAA;Gfi2DD;Ecz6DF;ICwEG,0BAAA;Gfo2DD;Ec56DF;ICwEG,0BAAA;Gfu2DD;Ec/6DF;ICwEG,iBAAA;Gf02DD;Ecl7DF;ICwEG,0BAAA;Gf62DD;Ecr7DF;ICwEG,0BAAA;Gfg3DD;Ecx7DF;ICwEG,iBAAA;Gfm3DD;Ec37DF;ICwEG,0BAAA;Gfs3DD;Ec97DF;ICwEG,0BAAA;Gfy3DD;Ecj8DF;ICwEG,iBAAA;Gf43DD;Ecp8DF;ICwEG,0BAAA;Gf+3DD;Ecv8DF;ICwEG,yBAAA;Gfk4DD;Ec18DF;ICwEG,gBAAA;Gfq4DD;CACF;Aa53DD;EClFC;;;;;;;;;;;;ICuCK,YAAA;Gfs7DH;Ec79DF;IC+CG,YAAA;Gfi7DD;Ech+DF;IC+CG,oBAAA;Gfo7DD;Ecn+DF;IC+CG,oBAAA;Gfu7DD;Ect+DF;IC+CG,WAAA;Gf07DD;Ecz+DF;IC+CG,oBAAA;Gf67DD;Ec5+DF;IC+CG,oBAAA;Gfg8DD;Ec/+DF;IC+CG,WAAA;Gfm8DD;Ecl/DF;IC+CG,oBAAA;Gfs8DD;Ecr/DF;IC+CG,oBAAA;Gfy8DD;Ecx/DF;IC+CG,WAAA;Gf48DD;Ec3/DF;IC+CG,oBAAA;Gf+8DD;Ec9/DF;IC+CG,mBAAA;Gfk9DD;EcjgEF;IC8DG,YAAA;Gfs8DD;EcpgEF;IC8DG,oBAAA;Gfy8DD;EcvgEF;IC8DG,oBAAA;Gf48DD;Ec1gEF;IC8DG,WAAA;Gf+8DD;Ec7gEF;IC8DG,oBAAA;Gfk9DD;EchhEF;IC8DG,oBAAA;Gfq9DD;EcnhEF;IC8DG,WAAA;Gfw9DD;EcthEF;IC8DG,oBAAA;Gf29DD;EczhEF;IC8DG,oBAAA;Gf89DD;Ec5hEF;IC8DG,WAAA;Gfi+DD;Ec/hEF;IC8DG,oBAAA;Gfo+DD;EcliEF;IC8DG,mBAAA;Gfu+DD;EcriEF;ICmEG,YAAA;Gfq+DD;EcxiEF;ICoDG,WAAA;Gfu/DD;Ec3iEF;ICoDG,mBAAA;Gf0/DD;Ec9iEF;ICoDG,mBAAA;Gf6/DD;EcjjEF;ICoDG,UAAA;GfggED;EcpjEF;ICoDG,mBAAA;GfmgED;EcvjEF;ICoDG,mBAAA;GfsgED;Ec1jEF;ICoDG,UAAA;GfygED;Ec7jEF;ICoDG,mBAAA;Gf4gED;EchkEF;ICoDG,mBAAA;Gf+gED;EcnkEF;ICoDG,UAAA;GfkhED;EctkEF;ICoDG,mBAAA;GfqhED;EczkEF;ICoDG,kBAAA;GfwhED;Ec5kEF;ICyDG,WAAA;GfshED;Ec/kEF;ICwEG,kBAAA;Gf0gED;EcllEF;ICwEG,0BAAA;Gf6gED;EcrlEF;ICwEG,0BAAA;GfghED;EcxlEF;ICwEG,iBAAA;GfmhED;Ec3lEF;ICwEG,0BAAA;GfshED;Ec9lEF;ICwEG,0BAAA;GfyhED;EcjmEF;ICwEG,iBAAA;Gf4hED;EcpmEF;ICwEG,0BAAA;Gf+hED;EcvmEF;ICwEG,0BAAA;GfkiED;Ec1mEF;ICwEG,iBAAA;GfqiED;Ec7mEF;ICwEG,0BAAA;GfwiED;EchnEF;ICwEG,yBAAA;Gf2iED;EcnnEF;ICwEG,gBAAA;Gf8iED;CACF;Aa5hED;EC3FC;;;;;;;;;;;;ICuCK,YAAA;Gf+lEH;EctoEF;IC+CG,YAAA;Gf0lED;EczoEF;IC+CG,oBAAA;Gf6lED;Ec5oEF;IC+CG,oBAAA;GfgmED;Ec/oEF;IC+CG,WAAA;GfmmED;EclpEF;IC+CG,oBAAA;GfsmED;EcrpEF;IC+CG,oBAAA;GfymED;EcxpEF;IC+CG,WAAA;Gf4mED;Ec3pEF;IC+CG,oBAAA;Gf+mED;Ec9pEF;IC+CG,oBAAA;GfknED;EcjqEF;IC+CG,WAAA;GfqnED;EcpqEF;IC+CG,oBAAA;GfwnED;EcvqEF;IC+CG,mBAAA;Gf2nED;Ec1qEF;IC8DG,YAAA;Gf+mED;Ec7qEF;IC8DG,oBAAA;GfknED;EchrEF;IC8DG,oBAAA;GfqnED;EcnrEF;IC8DG,WAAA;GfwnED;EctrEF;IC8DG,oBAAA;Gf2nED;EczrEF;IC8DG,oBAAA;Gf8nED;Ec5rEF;IC8DG,WAAA;GfioED;Ec/rEF;IC8DG,oBAAA;GfooED;EclsEF;IC8DG,oBAAA;GfuoED;EcrsEF;IC8DG,WAAA;Gf0oED;EcxsEF;IC8DG,oBAAA;Gf6oED;Ec3sEF;IC8DG,mBAAA;GfgpED;Ec9sEF;ICmEG,YAAA;Gf8oED;EcjtEF;ICoDG,WAAA;GfgqED;EcptEF;ICoDG,mBAAA;GfmqED;EcvtEF;ICoDG,mBAAA;GfsqED;Ec1tEF;ICoDG,UAAA;GfyqED;Ec7tEF;ICoDG,mBAAA;Gf4qED;EchuEF;ICoDG,mBAAA;Gf+qED;EcnuEF;ICoDG,UAAA;GfkrED;EctuEF;ICoDG,mBAAA;GfqrED;EczuEF;ICoDG,mBAAA;GfwrED;Ec5uEF;ICoDG,UAAA;Gf2rED;Ec/uEF;ICoDG,mBAAA;Gf8rED;EclvEF;ICoDG,kBAAA;GfisED;EcrvEF;ICyDG,WAAA;Gf+rED;EcxvEF;ICwEG,kBAAA;GfmrED;Ec3vEF;ICwEG,0BAAA;GfsrED;Ec9vEF;ICwEG,0BAAA;GfyrED;EcjwEF;ICwEG,iBAAA;Gf4rED;EcpwEF;ICwEG,0BAAA;Gf+rED;EcvwEF;ICwEG,0BAAA;GfksED;Ec1wEF;ICwEG,iBAAA;GfqsED;Ec7wEF;ICwEG,0BAAA;GfwsED;EchxEF;ICwEG,0BAAA;Gf2sED;EcnxEF;ICwEG,iBAAA;Gf8sED;EctxEF;ICwEG,0BAAA;GfitED;EczxEF;ICwEG,yBAAA;GfotED;Ec5xEF;ICwEG,gBAAA;GfutED;CACF;AgBzxED;EACE,8BAAA;ChB2xED;AgB5xED;EAQI,iBAAA;EACA,sBAAA;EACA,YAAA;ChBuxEH;AgBlxEG;;EACE,iBAAA;EACA,oBAAA;EACA,YAAA;ChBqxEL;AgBhxED;EACE,iBAAA;EACA,oBAAA;EACA,eAAA;EACA,iBAAA;ChBkxED;AgB/wED;EACE,iBAAA;ChBixED;AgB3wED;EACE,YAAA;EACA,gBAAA;EACA,oBAAA;ChB6wED;AgBhxED;;;;;;EAWQ,aAAA;EACA,wBAAA;EACA,oBAAA;EACA,2BAAA;ChB6wEP;AgB3xED;EAoBI,uBAAA;EACA,8BAAA;ChB0wEH;AgB/xED;;;;;;EA8BQ,cAAA;ChBywEP;AgBvyED;EAoCI,2BAAA;ChBswEH;AgB1yED;EAyCI,uBAAA;ChBowEH;AgB7vED;;;;;;EAOQ,aAAA;ChB8vEP;AgBnvED;EACE,uBAAA;ChBqvED;AgBtvED;;;;;;EAQQ,uBAAA;ChBsvEP;AgB9vED;;EAeM,yBAAA;ChBmvEL;AgBzuED;EAEI,0BAAA;ChB0uEH;AgBjuED;EAEI,0BAAA;ChBkuEH;AiBj3EC;;;;;;;;;;;;EAOI,0BAAA;CjBw3EL;AiBl3EC;;;;;EAMI,0BAAA;CjBm3EL;AiBt4EC;;;;;;;;;;;;EAOI,0BAAA;CjB64EL;AiBv4EC;;;;;EAMI,0BAAA;CjBw4EL;AiB35EC;;;;;;;;;;;;EAOI,0BAAA;CjBk6EL;AiB55EC;;;;;EAMI,0BAAA;CjB65EL;AiBh7EC;;;;;;;;;;;;EAOI,0BAAA;CjBu7EL;AiBj7EC;;;;;EAMI,0BAAA;CjBk7EL;AiBr8EC;;;;;;;;;;;;EAOI,0BAAA;CjB48EL;AiBt8EC;;;;;EAMI,0BAAA;CjBu8EL;AgBnzED;EACE,kBAAA;EACA,iBAAA;ChBqzED;AgBnzEC;EAAA;IACE,YAAA;IACA,oBAAA;IACA,mBAAA;IACA,6CAAA;IACA,uBAAA;GhBszED;EgB3zED;IASI,iBAAA;GhBqzEH;EgB9zED;;;;;;IAkBU,oBAAA;GhBozET;EgBt0ED;IA0BI,UAAA;GhB+yEH;EgBz0ED;;;;;;IAmCU,eAAA;GhB8yET;EgBj1ED;;;;;;IAuCU,gBAAA;GhBkzET;EgBz1ED;;;;IAoDU,iBAAA;GhB2yET;CACF;AkBrgFD;EAIE,aAAA;EACA,WAAA;EACA,UAAA;EACA,UAAA;ClBogFD;AkBjgFD;EACE,eAAA;EACA,YAAA;EACA,WAAA;EACA,oBAAA;EACA,gBAAA;EACA,qBAAA;EACA,eAAA;EACA,UAAA;EACA,iCAAA;ClBmgFD;AkBhgFD;EACE,sBAAA;EACA,gBAAA;EACA,mBAAA;EACA,iBAAA;ClBkgFD;AkBx/ED;Eb6BE,+BAAA;EACG,4BAAA;EACK,uBAAA;EarBR,yBAAA;EACA,sBAAA;EAAA,iBAAA;ClBo/ED;AkBh/ED;;EAEE,gBAAA;EACA,mBAAA;EACA,oBAAA;ClBk/ED;AkB5+EC;;;;;;EAGE,oBAAA;ClBi/EH;AkB7+ED;EACE,eAAA;ClB++ED;AkB3+ED;EACE,eAAA;EACA,YAAA;ClB6+ED;AkBz+ED;;EAEE,aAAA;ClB2+ED;AkBv+ED;;;EZ1FE,2CAAA;EACA,qBAAA;CNskFD;AkBt+ED;EACE,eAAA;EACA,iBAAA;EACA,gBAAA;EACA,wBAAA;EACA,eAAA;ClBw+ED;AkB98ED;EACE,eAAA;EACA,YAAA;EACA,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,wBAAA;EACA,eAAA;EACA,uBAAA;EACA,uBAAA;EACA,uBAAA;EACA,mBAAA;Eb3EA,yDAAA;EACQ,iDAAA;EAyHR,+EAAA;EACK,0EAAA;EACG,uFAAA;EAAA,+EAAA;EAAA,uEAAA;EAAA,4GAAA;CLo6ET;AmB9iFC;EACE,sBAAA;EACA,WAAA;EdYF,0FAAA;EACQ,kFAAA;CLqiFT;AKpgFC;EACE,YAAA;EACA,WAAA;CLsgFH;AKpgFC;EAA0B,YAAA;CLugF3B;AKtgFC;EAAgC,YAAA;CLygFjC;AkB19EC;EACE,8BAAA;EACA,UAAA;ClB49EH;AkBp9EC;;;EAGE,0BAAA;EACA,WAAA;ClBs9EH;AkBn9EC;;EAEE,oBAAA;ClBq9EH;AkBj9EC;EACE,aAAA;ClBm9EH;AkBr8ED;EAKI;;;;IACE,kBAAA;GlBs8EH;EkBn8EC;;;;;;;;IAEE,kBAAA;GlB28EH;EkBx8EC;;;;;;;;IAEE,kBAAA;GlBg9EH;CACF;AkBt8ED;EACE,oBAAA;ClBw8ED;AkBh8ED;;EAEE,mBAAA;EACA,eAAA;EACA,iBAAA;EACA,oBAAA;ClBk8ED;AkB/7EC;;;;EAGI,oBAAA;ClBk8EL;AkB78ED;;EAgBI,iBAAA;EACA,mBAAA;EACA,iBAAA;EACA,iBAAA;EACA,gBAAA;ClBi8EH;AkB97ED;;;;EAIE,mBAAA;EACA,mBAAA;EACA,mBAAA;ClBg8ED;AkB77ED;;EAEE,iBAAA;ClB+7ED;AkB37ED;;EAEE,mBAAA;EACA,sBAAA;EACA,mBAAA;EACA,iBAAA;EACA,iBAAA;EACA,uBAAA;EACA,gBAAA;ClB67ED;AkB17EC;;;;EAEE,oBAAA;ClB87EH;AkB37ED;;EAEE,cAAA;EACA,kBAAA;ClB67ED;AkBp7ED;EACE,iBAAA;EAEA,iBAAA;EACA,oBAAA;EAEA,iBAAA;ClBo7ED;AkBl7EC;;EAEE,iBAAA;EACA,gBAAA;ClBo7EH;AkBv6ED;EC3PE,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;CnBqqFD;AmBnqFC;EACE,aAAA;EACA,kBAAA;CnBqqFH;AmBlqFC;;EAEE,aAAA;CnBoqFH;AkBn7ED;EAEI,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;ClBo7EH;AkB17ED;EASI,aAAA;EACA,kBAAA;ClBo7EH;AkB97ED;;EAcI,aAAA;ClBo7EH;AkBl8ED;EAiBI,aAAA;EACA,iBAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;ClBo7EH;AkBh7ED;ECvRE,aAAA;EACA,mBAAA;EACA,gBAAA;EACA,uBAAA;EACA,mBAAA;CnB0sFD;AmBxsFC;EACE,aAAA;EACA,kBAAA;CnB0sFH;AmBvsFC;;EAEE,aAAA;CnBysFH;AkB57ED;EAEI,aAAA;EACA,mBAAA;EACA,gBAAA;EACA,uBAAA;EACA,mBAAA;ClB67EH;AkBn8ED;EASI,aAAA;EACA,kBAAA;ClB67EH;AkBv8ED;;EAcI,aAAA;ClB67EH;AkB38ED;EAiBI,aAAA;EACA,iBAAA;EACA,mBAAA;EACA,gBAAA;EACA,uBAAA;ClB67EH;AkBp7ED;EAEE,mBAAA;ClBq7ED;AkBv7ED;EAMI,sBAAA;ClBo7EH;AkBh7ED;EACE,mBAAA;EACA,OAAA;EACA,SAAA;EACA,WAAA;EACA,eAAA;EACA,YAAA;EACA,aAAA;EACA,kBAAA;EACA,mBAAA;EACA,qBAAA;ClBk7ED;AkBh7ED;;;EAGE,YAAA;EACA,aAAA;EACA,kBAAA;ClBk7ED;AkBh7ED;;;EAGE,YAAA;EACA,aAAA;EACA,kBAAA;ClBk7ED;AkB96ED;;;;;;;;;;EClZI,eAAA;CnB40FH;AkB17ED;EC9YI,sBAAA;EdiDF,yDAAA;EACQ,iDAAA;CL2xFT;AmB30FG;EACE,sBAAA;Ed8CJ,0EAAA;EACQ,kEAAA;CLgyFT;AkBp8ED;ECpYI,eAAA;EACA,0BAAA;EACA,sBAAA;CnB20FH;AkBz8ED;EC9XI,eAAA;CnB00FH;AkBz8ED;;;;;;;;;;ECrZI,eAAA;CnB02FH;AkBr9ED;ECjZI,sBAAA;EdiDF,yDAAA;EACQ,iDAAA;CLyzFT;AmBz2FG;EACE,sBAAA;Ed8CJ,0EAAA;EACQ,kEAAA;CL8zFT;AkB/9ED;ECvYI,eAAA;EACA,0BAAA;EACA,sBAAA;CnBy2FH;AkBp+ED;ECjYI,eAAA;CnBw2FH;AkBp+ED;;;;;;;;;;ECxZI,eAAA;CnBw4FH;AkBh/ED;ECpZI,sBAAA;EdiDF,yDAAA;EACQ,iDAAA;CLu1FT;AmBv4FG;EACE,sBAAA;Ed8CJ,0EAAA;EACQ,kEAAA;CL41FT;AkB1/ED;EC1YI,eAAA;EACA,0BAAA;EACA,sBAAA;CnBu4FH;AkB//ED;ECpYI,eAAA;CnBs4FH;AkB3/EC;EACE,UAAA;ClB6/EH;AkB3/EC;EACE,OAAA;ClB6/EH;AkBn/ED;EACE,eAAA;EACA,gBAAA;EACA,oBAAA;EACA,eAAA;ClBq/ED;AkBn+EC;EAAA;IAGI,sBAAA;IACA,iBAAA;IACA,uBAAA;GlBo+EH;EkBz+ED;IAUI,sBAAA;IACA,YAAA;IACA,uBAAA;GlBk+EH;EkB9+ED;IAiBI,sBAAA;GlBg+EH;EkBj/ED;IAqBI,sBAAA;IACA,uBAAA;GlB+9EH;EkBr/ED;;;IA2BM,YAAA;GlB+9EL;EkB1/ED;IAiCI,YAAA;GlB49EH;EkB7/ED;IAqCI,iBAAA;IACA,uBAAA;GlB29EH;EkBjgFD;;IA6CI,sBAAA;IACA,cAAA;IACA,iBAAA;IACA,uBAAA;GlBw9EH;EkBxgFD;;IAmDM,gBAAA;GlBy9EL;EkB5gFD;;IAwDI,mBAAA;IACA,eAAA;GlBw9EH;EkBjhFD;IA8DI,OAAA;GlBs9EH;CACF;AkB58ED;;;;EASI,iBAAA;EACA,cAAA;EACA,iBAAA;ClBy8EH;AkBp9ED;;EAiBI,iBAAA;ClBu8EH;AkBx9ED;EJ9gBE,oBAAA;EACA,mBAAA;Cdy+FD;AkBj8EC;EAAA;IAEI,iBAAA;IACA,iBAAA;IACA,kBAAA;GlBm8EH;CACF;AkBn+ED;EAwCI,YAAA;ClB87EH;AkBt7EG;EAAA;IAEI,kBAAA;IACA,gBAAA;GlBw7EL;CACF;AkBp7EG;EAAA;IAEI,iBAAA;IACA,gBAAA;GlBs7EL;CACF;AoBrgGD;EACE,sBAAA;EACA,iBAAA;EACA,oBAAA;EACA,mBAAA;EACA,oBAAA;EACA,uBAAA;EACA,+BAAA;EAAA,2BAAA;EACA,gBAAA;EACA,uBAAA;EACA,8BAAA;ECoCA,kBAAA;EACA,gBAAA;EACA,wBAAA;EACA,mBAAA;EhBqKA,0BAAA;EACG,uBAAA;EACC,sBAAA;EACI,kBAAA;CLg0FT;AoBxgGG;;;;;;EdrBF,2CAAA;EACA,qBAAA;CNqiGD;AoB3gGC;;;EAGE,YAAA;EACA,sBAAA;CpB6gGH;AoB1gGC;;EAEE,uBAAA;EACA,WAAA;Ef2BF,yDAAA;EACQ,iDAAA;CLk/FT;AoB1gGC;;;EAGE,oBAAA;EE9CF,0BAAA;EACA,cAAA;EjBiEA,yBAAA;EACQ,iBAAA;CL2/FT;AoB1gGG;;EAEE,qBAAA;CpB4gGL;AoBngGD;EC7DE,YAAA;EACA,uBAAA;EACA,mBAAA;CrBmkGD;AqBjkGC;;EAEE,YAAA;EACA,0BAAA;EACA,sBAAA;CrBmkGH;AqBjkGC;EACE,YAAA;EACA,0BAAA;EACA,sBAAA;CrBmkGH;AqBjkGC;;;EAGE,YAAA;EACA,0BAAA;EACA,uBAAA;EACA,sBAAA;CrBmkGH;AqBjkGG;;;;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;CrBykGL;AqBnkGG;;;;;;;;;EAGE,uBAAA;EACA,mBAAA;CrB2kGL;AoBpjGD;EClBI,YAAA;EACA,uBAAA;CrBykGH;AoBrjGD;EChEE,YAAA;EACA,0BAAA;EACA,sBAAA;CrBwnGD;AqBtnGC;;EAEE,YAAA;EACA,0BAAA;EACA,sBAAA;CrBwnGH;AqBtnGC;EACE,YAAA;EACA,0BAAA;EACA,sBAAA;CrBwnGH;AqBtnGC;;;EAGE,YAAA;EACA,0BAAA;EACA,uBAAA;EACA,sBAAA;CrBwnGH;AqBtnGG;;;;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;CrB8nGL;AqBxnGG;;;;;;;;;EAGE,0BAAA;EACA,sBAAA;CrBgoGL;AoBtmGD;ECrBI,eAAA;EACA,uBAAA;CrB8nGH;AoBtmGD;ECpEE,YAAA;EACA,0BAAA;EACA,sBAAA;CrB6qGD;AqB3qGC;;EAEE,YAAA;EACA,0BAAA;EACA,sBAAA;CrB6qGH;AqB3qGC;EACE,YAAA;EACA,0BAAA;EACA,sBAAA;CrB6qGH;AqB3qGC;;;EAGE,YAAA;EACA,0BAAA;EACA,uBAAA;EACA,sBAAA;CrB6qGH;AqB3qGG;;;;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;CrBmrGL;AqB7qGG;;;;;;;;;EAGE,0BAAA;EACA,sBAAA;CrBqrGL;AoBvpGD;ECzBI,eAAA;EACA,uBAAA;CrBmrGH;AoBvpGD;ECxEE,YAAA;EACA,0BAAA;EACA,sBAAA;CrBkuGD;AqBhuGC;;EAEE,YAAA;EACA,0BAAA;EACA,sBAAA;CrBkuGH;AqBhuGC;EACE,YAAA;EACA,0BAAA;EACA,sBAAA;CrBkuGH;AqBhuGC;;;EAGE,YAAA;EACA,0BAAA;EACA,uBAAA;EACA,sBAAA;CrBkuGH;AqBhuGG;;;;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;CrBwuGL;AqBluGG;;;;;;;;;EAGE,0BAAA;EACA,sBAAA;CrB0uGL;AoBxsGD;EC7BI,eAAA;EACA,uBAAA;CrBwuGH;AoBxsGD;EC5EE,YAAA;EACA,0BAAA;EACA,sBAAA;CrBuxGD;AqBrxGC;;EAEE,YAAA;EACA,0BAAA;EACA,sBAAA;CrBuxGH;AqBrxGC;EACE,YAAA;EACA,0BAAA;EACA,sBAAA;CrBuxGH;AqBrxGC;;;EAGE,YAAA;EACA,0BAAA;EACA,uBAAA;EACA,sBAAA;CrBuxGH;AqBrxGG;;;;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;CrB6xGL;AqBvxGG;;;;;;;;;EAGE,0BAAA;EACA,sBAAA;CrB+xGL;AoBzvGD;ECjCI,eAAA;EACA,uBAAA;CrB6xGH;AoBzvGD;EChFE,YAAA;EACA,0BAAA;EACA,sBAAA;CrB40GD;AqB10GC;;EAEE,YAAA;EACA,0BAAA;EACA,sBAAA;CrB40GH;AqB10GC;EACE,YAAA;EACA,0BAAA;EACA,sBAAA;CrB40GH;AqB10GC;;;EAGE,YAAA;EACA,0BAAA;EACA,uBAAA;EACA,sBAAA;CrB40GH;AqB10GG;;;;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;CrBk1GL;AqB50GG;;;;;;;;;EAGE,0BAAA;EACA,sBAAA;CrBo1GL;AoB1yGD;ECrCI,eAAA;EACA,uBAAA;CrBk1GH;AoBryGD;EACE,iBAAA;EACA,eAAA;EACA,iBAAA;CpBuyGD;AoBryGC;;;;;EAKE,8BAAA;EfnCF,yBAAA;EACQ,iBAAA;CL20GT;AoBtyGC;;;;EAIE,0BAAA;CpBwyGH;AoBtyGC;;EAEE,eAAA;EACA,2BAAA;EACA,8BAAA;CpBwyGH;AoBpyGG;;;;EAEE,eAAA;EACA,sBAAA;CpBwyGL;AoB/xGD;;EC9EE,mBAAA;EACA,gBAAA;EACA,uBAAA;EACA,mBAAA;CrBi3GD;AoBlyGD;;EClFE,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;CrBw3GD;AoBryGD;;ECtFE,iBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;CrB+3GD;AoBpyGD;EACE,eAAA;EACA,YAAA;CpBsyGD;AoBlyGD;EACE,gBAAA;CpBoyGD;AoB7xGC;;;EACE,YAAA;CpBiyGH;AuB37GD;EACE,WAAA;ElBoLA,yCAAA;EACK,oCAAA;EACG,iCAAA;CL0wGT;AuB77GC;EACE,WAAA;CvB+7GH;AuB37GD;EACE,cAAA;CvB67GD;AuB37GC;EAAY,eAAA;CvB87Gb;AuB77GC;EAAY,mBAAA;CvBg8Gb;AuB/7GC;EAAY,yBAAA;CvBk8Gb;AuB/7GD;EACE,mBAAA;EACA,UAAA;EACA,iBAAA;ElBsKA,gDAAA;EACQ,2CAAA;EAAA,wCAAA;EAOR,mCAAA;EACQ,8BAAA;EAAA,2BAAA;EAGR,yCAAA;EACQ,oCAAA;EAAA,iCAAA;CLoxGT;AwBh+GD;EACE,sBAAA;EACA,SAAA;EACA,UAAA;EACA,iBAAA;EACA,uBAAA;EACA,uBAAA;EACA,yBAAA;EACA,oCAAA;EACA,mCAAA;CxBk+GD;AwB99GD;;EAEE,mBAAA;CxBg+GD;AwB59GD;EACE,WAAA;CxB89GD;AwB19GD;EACE,mBAAA;EACA,UAAA;EACA,QAAA;EACA,cAAA;EACA,cAAA;EACA,YAAA;EACA,iBAAA;EACA,eAAA;EACA,gBAAA;EACA,gBAAA;EACA,iBAAA;EACA,iBAAA;EACA,uBAAA;EACA,6BAAA;EACA,uBAAA;EACA,sCAAA;EACA,mBAAA;EnBuBA,oDAAA;EACQ,4CAAA;CLs8GT;AwBx9GC;EACE,SAAA;EACA,WAAA;CxB09GH;AwBn/GD;ECzBE,YAAA;EACA,cAAA;EACA,iBAAA;EACA,0BAAA;CzB+gHD;AwBz/GD;EAmCI,eAAA;EACA,kBAAA;EACA,YAAA;EACA,iBAAA;EACA,wBAAA;EACA,eAAA;EACA,oBAAA;CxBy9GH;AwBv9GG;;EAEE,eAAA;EACA,sBAAA;EACA,0BAAA;CxBy9GL;AwBl9GC;;;EAGE,YAAA;EACA,sBAAA;EACA,0BAAA;EACA,WAAA;CxBo9GH;AwB38GC;;;EAGE,eAAA;CxB68GH;AwBz8GC;;EAEE,sBAAA;EACA,oBAAA;EACA,8BAAA;EACA,uBAAA;EEzGF,oEAAA;C1BqjHD;AwBt8GD;EAGI,eAAA;CxBs8GH;AwBz8GD;EAQI,WAAA;CxBo8GH;AwB57GD;EACE,SAAA;EACA,WAAA;CxB87GD;AwBt7GD;EACE,YAAA;EACA,QAAA;CxBw7GD;AwBp7GD;EACE,eAAA;EACA,kBAAA;EACA,gBAAA;EACA,wBAAA;EACA,eAAA;EACA,oBAAA;CxBs7GD;AwBl7GD;EACE,gBAAA;EACA,OAAA;EACA,SAAA;EACA,UAAA;EACA,QAAA;EACA,aAAA;CxBo7GD;AwBh7GD;EACE,SAAA;EACA,WAAA;CxBk7GD;AwB16GD;;EAII,YAAA;EACA,cAAA;EACA,0BAAA;EACA,4BAAA;CxB06GH;AwBj7GD;;EAWI,UAAA;EACA,aAAA;EACA,mBAAA;CxB06GH;AwBj6GD;EACE;IApEA,SAAA;IACA,WAAA;GxBw+GC;EwBr6GD;IA1DA,YAAA;IACA,QAAA;GxBk+GC;CACF;A2B7mHD;;EAEE,mBAAA;EACA,sBAAA;EACA,uBAAA;C3B+mHD;A2BnnHD;;EAMI,mBAAA;EACA,YAAA;C3BinHH;A2B/mHG;;;;;;;;EAIE,WAAA;C3BqnHL;A2B/mHD;;;;EAKI,kBAAA;C3BgnHH;A2B3mHD;EACE,kBAAA;C3B6mHD;A2B9mHD;;;EAOI,YAAA;C3B4mHH;A2BnnHD;;;EAYI,iBAAA;C3B4mHH;A2BxmHD;EACE,iBAAA;C3B0mHD;A2BtmHD;EACE,eAAA;C3BwmHD;A2BvmHC;ECpDA,2BAAA;EACA,8BAAA;C5B8pHD;A2BtmHD;;ECjDE,0BAAA;EACA,6BAAA;C5B2pHD;A2BrmHD;EACE,YAAA;C3BumHD;A2BrmHD;EACE,iBAAA;C3BumHD;A2BrmHD;;ECrEE,2BAAA;EACA,8BAAA;C5B8qHD;A2BpmHD;ECnEE,0BAAA;EACA,6BAAA;C5B0qHD;A2BnmHD;;EAEE,WAAA;C3BqmHD;A2BplHD;EACE,mBAAA;EACA,kBAAA;C3BslHD;A2BplHD;EACE,oBAAA;EACA,mBAAA;C3BslHD;A2BjlHD;EtB/CE,yDAAA;EACQ,iDAAA;CLmoHT;A2BjlHC;EtBnDA,yBAAA;EACQ,iBAAA;CLuoHT;A2B9kHD;EACE,eAAA;C3BglHD;A2B7kHD;EACE,wBAAA;EACA,uBAAA;C3B+kHD;A2B5kHD;EACE,wBAAA;C3B8kHD;A2BvkHD;;;EAII,eAAA;EACA,YAAA;EACA,YAAA;EACA,gBAAA;C3BwkHH;A2B/kHD;EAcM,YAAA;C3BokHL;A2BllHD;;;;EAsBI,iBAAA;EACA,eAAA;C3BkkHH;A2B7jHC;EACE,iBAAA;C3B+jHH;A2B7jHC;EC7KA,4BAAA;EACA,6BAAA;EAOA,8BAAA;EACA,6BAAA;C5BuuHD;A2B/jHC;ECjLA,0BAAA;EACA,2BAAA;EAOA,gCAAA;EACA,+BAAA;C5B6uHD;A2BhkHD;EACE,iBAAA;C3BkkHD;A2BhkHD;;ECjLE,8BAAA;EACA,6BAAA;C5BqvHD;A2B/jHD;EC/LE,0BAAA;EACA,2BAAA;C5BiwHD;A2B3jHD;EACE,eAAA;EACA,YAAA;EACA,oBAAA;EACA,0BAAA;C3B6jHD;A2BjkHD;;EAOI,oBAAA;EACA,YAAA;EACA,UAAA;C3B8jHH;A2BvkHD;EAYI,YAAA;C3B8jHH;A2B1kHD;EAgBI,WAAA;C3B6jHH;A2B5iHD;;;;EAKM,mBAAA;EACA,uBAAA;EACA,qBAAA;C3B6iHL;A6BvxHD;EACE,mBAAA;EACA,eAAA;EACA,0BAAA;C7ByxHD;A6BtxHC;EACE,YAAA;EACA,iBAAA;EACA,gBAAA;C7BwxHH;A6BjyHD;EAeI,mBAAA;EACA,WAAA;EAKA,YAAA;EAEA,YAAA;EACA,iBAAA;C7BgxHH;A6B9wHG;EACE,WAAA;C7BgxHL;A6BtwHD;;;EVwBE,aAAA;EACA,mBAAA;EACA,gBAAA;EACA,uBAAA;EACA,mBAAA;CnBmvHD;AmBjvHC;;;EACE,aAAA;EACA,kBAAA;CnBqvHH;AmBlvHC;;;;;;EAEE,aAAA;CnBwvHH;A6BxxHD;;;EVmBE,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;CnB0wHD;AmBxwHC;;;EACE,aAAA;EACA,kBAAA;CnB4wHH;AmBzwHC;;;;;;EAEE,aAAA;CnB+wHH;A6BtyHD;;;EAGE,oBAAA;C7BwyHD;A6BtyHC;;;EACE,iBAAA;C7B0yHH;A6BtyHD;;EAEE,UAAA;EACA,oBAAA;EACA,uBAAA;C7BwyHD;A6BnyHD;EACE,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,eAAA;EACA,eAAA;EACA,mBAAA;EACA,0BAAA;EACA,uBAAA;EACA,mBAAA;C7BqyHD;A6BlyHC;EACE,kBAAA;EACA,gBAAA;EACA,mBAAA;C7BoyHH;A6BlyHC;EACE,mBAAA;EACA,gBAAA;EACA,mBAAA;C7BoyHH;A6BxzHD;;EA0BI,cAAA;C7BkyHH;A6B7xHD;;;;;;;EDtGE,2BAAA;EACA,8BAAA;C5B44HD;A6B9xHD;EACE,gBAAA;C7BgyHD;A6B9xHD;;;;;;;ED1GE,0BAAA;EACA,6BAAA;C5Bi5HD;A6B/xHD;EACE,eAAA;C7BiyHD;A6B5xHD;EACE,mBAAA;EAGA,aAAA;EACA,oBAAA;C7B4xHD;A6BjyHD;EAUI,mBAAA;C7B0xHH;A6BpyHD;EAYM,kBAAA;C7B2xHL;A6BxxHG;;;EAGE,WAAA;C7B0xHL;A6BrxHC;;EAGI,mBAAA;C7BsxHL;A6BnxHC;;EAGI,WAAA;EACA,kBAAA;C7BoxHL;A8Bn7HD;EACE,gBAAA;EACA,iBAAA;EACA,iBAAA;C9Bq7HD;A8Bx7HD;EAOI,mBAAA;EACA,eAAA;C9Bo7HH;A8B57HD;EAWM,mBAAA;EACA,eAAA;EACA,mBAAA;C9Bo7HL;A8Bn7HK;;EAEE,sBAAA;EACA,0BAAA;C9Bq7HP;A8Bh7HG;EACE,eAAA;C9Bk7HL;A8Bh7HK;;EAEE,eAAA;EACA,sBAAA;EACA,oBAAA;EACA,8BAAA;C9Bk7HP;A8B36HG;;;EAGE,0BAAA;EACA,sBAAA;C9B66HL;A8Bt9HD;ELLE,YAAA;EACA,cAAA;EACA,iBAAA;EACA,0BAAA;CzB89HD;A8B59HD;EA0DI,gBAAA;C9Bq6HH;A8B55HD;EACE,8BAAA;C9B85HD;A8B/5HD;EAGI,YAAA;EAEA,oBAAA;C9B85HH;A8Bn6HD;EASM,kBAAA;EACA,wBAAA;EACA,8BAAA;EACA,2BAAA;C9B65HL;A8B55HK;EACE,mCAAA;C9B85HP;A8Bx5HK;;;EAGE,eAAA;EACA,gBAAA;EACA,uBAAA;EACA,uBAAA;EACA,iCAAA;C9B05HP;A8Br5HC;EAqDA,YAAA;EA8BA,iBAAA;C9Bs0HD;A8Bz5HC;EAwDE,YAAA;C9Bo2HH;A8B55HC;EA0DI,mBAAA;EACA,mBAAA;C9Bq2HL;A8Bh6HC;EAgEE,UAAA;EACA,WAAA;C9Bm2HH;A8Bh2HC;EAAA;IAEI,oBAAA;IACA,UAAA;G9Bk2HH;E8Br2HD;IAKM,iBAAA;G9Bm2HL;CACF;A8B76HC;EAuFE,gBAAA;EACA,mBAAA;C9By1HH;A8Bj7HC;;;EA8FE,uBAAA;C9Bw1HH;A8Br1HC;EAAA;IAEI,8BAAA;IACA,2BAAA;G9Bu1HH;E8B11HD;;;IAQI,0BAAA;G9Bu1HH;CACF;A8Bx7HD;EAEI,YAAA;C9By7HH;A8B37HD;EAMM,mBAAA;C9Bw7HL;A8B97HD;EASM,iBAAA;C9Bw7HL;A8Bn7HK;;;EAGE,YAAA;EACA,0BAAA;C9Bq7HP;A8B76HD;EAEI,YAAA;C9B86HH;A8Bh7HD;EAIM,gBAAA;EACA,eAAA;C9B+6HL;A8Bn6HD;EACE,YAAA;C9Bq6HD;A8Bt6HD;EAII,YAAA;C9Bq6HH;A8Bz6HD;EAMM,mBAAA;EACA,mBAAA;C9Bs6HL;A8B76HD;EAYI,UAAA;EACA,WAAA;C9Bo6HH;A8Bj6HC;EAAA;IAEI,oBAAA;IACA,UAAA;G9Bm6HH;E8Bt6HD;IAKM,iBAAA;G9Bo6HL;CACF;A8B55HD;EACE,iBAAA;C9B85HD;A8B/5HD;EAKI,gBAAA;EACA,mBAAA;C9B65HH;A8Bn6HD;;;EAYI,uBAAA;C9B45HH;A8Bz5HC;EAAA;IAEI,8BAAA;IACA,2BAAA;G9B25HH;E8B95HD;;;IAQI,0BAAA;G9B25HH;CACF;A8Bl5HD;EAEI,cAAA;C9Bm5HH;A8Br5HD;EAKI,eAAA;C9Bm5HH;A8B14HD;EAEE,iBAAA;EF7OA,0BAAA;EACA,2BAAA;C5BynID;A+BjnID;EACE,mBAAA;EACA,iBAAA;EACA,oBAAA;EACA,8BAAA;C/BmnID;A+B9mIC;EAAA;IACE,mBAAA;G/BinID;CACF;A+BrmIC;EAAA;IACE,YAAA;G/BwmID;CACF;A+B1lID;EACE,oBAAA;EACA,mBAAA;EACA,oBAAA;EACA,kCAAA;EACA,2DAAA;EAAA,mDAAA;EAEA,kCAAA;C/B2lID;A+BzlIC;EACE,iBAAA;C/B2lIH;A+BxlIC;EAAA;IACE,YAAA;IACA,cAAA;IACA,yBAAA;IAAA,iBAAA;G/B2lID;E+BzlIC;IACE,0BAAA;IACA,wBAAA;IACA,kBAAA;IACA,6BAAA;G/B2lIH;E+BxlIC;IACE,oBAAA;G/B0lIH;E+BrlIC;;;IAGE,iBAAA;IACA,gBAAA;G/BulIH;CACF;A+BnlID;;EAWE,gBAAA;EACA,SAAA;EACA,QAAA;EACA,cAAA;C/B4kID;A+B1lID;;EAGI,kBAAA;C/B2lIH;A+BzlIG;EAAA;;IACE,kBAAA;G/B6lIH;CACF;A+BnlIC;EAAA;;IACE,iBAAA;G/BulID;CACF;A+BplID;EACE,OAAA;EACA,sBAAA;C/BslID;A+BplID;EACE,UAAA;EACA,iBAAA;EACA,sBAAA;C/BslID;A+B9kID;;;;EAII,oBAAA;EACA,mBAAA;C/BglIH;A+B9kIG;EAAA;;;;IACE,gBAAA;IACA,eAAA;G/BolIH;CACF;A+BxkID;EACE,cAAA;EACA,sBAAA;C/B0kID;A+BxkIC;EAAA;IACE,iBAAA;G/B2kID;CACF;A+BrkID;EACE,YAAA;EACA,aAAA;EACA,mBAAA;EACA,gBAAA;EACA,kBAAA;C/BukID;A+BrkIC;;EAEE,sBAAA;C/BukIH;A+BhlID;EAaI,eAAA;C/BskIH;A+BnkIC;EACE;;IAEE,mBAAA;G/BqkIH;CACF;A+B3jID;EACE,mBAAA;EACA,aAAA;EACA,kBAAA;EACA,mBAAA;EC9LA,gBAAA;EACA,mBAAA;ED+LA,8BAAA;EACA,uBAAA;EACA,8BAAA;EACA,mBAAA;C/B8jID;A+B1jIC;EACE,WAAA;C/B4jIH;A+B1kID;EAmBI,eAAA;EACA,YAAA;EACA,YAAA;EACA,mBAAA;C/B0jIH;A+BhlID;EAyBI,gBAAA;C/B0jIH;A+BvjIC;EAAA;IACE,cAAA;G/B0jID;CACF;A+BjjID;EACE,oBAAA;C/BmjID;A+BpjID;EAII,kBAAA;EACA,qBAAA;EACA,kBAAA;C/BmjIH;A+BhjIC;EAAA;IAGI,iBAAA;IACA,YAAA;IACA,YAAA;IACA,cAAA;IACA,8BAAA;IACA,UAAA;IACA,yBAAA;IAAA,iBAAA;G/BijIH;E+B1jID;;IAYM,2BAAA;G/BkjIL;E+B9jID;IAeM,kBAAA;G/BkjIL;E+BjjIK;;IAEE,uBAAA;G/BmjIP;CACF;A+B7iIC;EAAA;IACE,YAAA;IACA,UAAA;G/BgjID;E+BljID;IAKI,YAAA;G/BgjIH;E+BrjID;IAOM,kBAAA;IACA,qBAAA;G/BijIL;CACF;A+BtiID;EACE,mBAAA;EACA,oBAAA;EACA,mBAAA;EACA,kCAAA;EACA,qCAAA;E1B5NA,6FAAA;EACQ,qFAAA;E2BjER,gBAAA;EACA,mBAAA;ChCu0ID;AkB13HC;EAAA;IAGI,sBAAA;IACA,iBAAA;IACA,uBAAA;GlB23HH;EkBh4HD;IAUI,sBAAA;IACA,YAAA;IACA,uBAAA;GlBy3HH;EkBr4HD;IAiBI,sBAAA;GlBu3HH;EkBx4HD;IAqBI,sBAAA;IACA,uBAAA;GlBs3HH;EkB54HD;;;IA2BM,YAAA;GlBs3HL;EkBj5HD;IAiCI,YAAA;GlBm3HH;EkBp5HD;IAqCI,iBAAA;IACA,uBAAA;GlBk3HH;EkBx5HD;;IA6CI,sBAAA;IACA,cAAA;IACA,iBAAA;IACA,uBAAA;GlB+2HH;EkB/5HD;;IAmDM,gBAAA;GlBg3HL;EkBn6HD;;IAwDI,mBAAA;IACA,eAAA;GlB+2HH;EkBx6HD;IA8DI,OAAA;GlB62HH;CACF;A+BtlIG;EAAA;IACE,mBAAA;G/BylIH;E+BvlIG;IACE,iBAAA;G/BylIL;CACF;A+BjlIC;EAAA;IACE,YAAA;IACA,eAAA;IACA,kBAAA;IACA,gBAAA;IACA,eAAA;IACA,UAAA;I1BvPF,yBAAA;IACQ,iBAAA;GL40IP;CACF;A+B9kID;EACE,cAAA;EHpUA,0BAAA;EACA,2BAAA;C5Bq5ID;A+B9kID;EACE,iBAAA;EHzUA,4BAAA;EACA,6BAAA;EAOA,8BAAA;EACA,6BAAA;C5Bo5ID;A+B1kID;EChVE,gBAAA;EACA,mBAAA;ChC65ID;A+B3kIC;ECnVA,iBAAA;EACA,oBAAA;ChCi6ID;A+B5kIC;ECtVA,iBAAA;EACA,oBAAA;ChCq6ID;A+BtkID;EChWE,iBAAA;EACA,oBAAA;ChCy6ID;A+BvkIC;EAAA;IACE,YAAA;IACA,mBAAA;IACA,kBAAA;G/B0kID;CACF;A+B9jID;EACE;IEtWA,uBAAA;GjCu6IC;E+BhkID;IE1WA,wBAAA;IF4WE,oBAAA;G/BkkID;E+BpkID;IAKI,gBAAA;G/BkkIH;CACF;A+BzjID;EACE,0BAAA;EACA,sBAAA;C/B2jID;A+B7jID;EAKI,YAAA;C/B2jIH;A+B1jIG;;EAEE,eAAA;EACA,8BAAA;C/B4jIL;A+BrkID;EAcI,YAAA;C/B0jIH;A+BxkID;EAmBM,YAAA;C/BwjIL;A+BtjIK;;EAEE,YAAA;EACA,8BAAA;C/BwjIP;A+BpjIK;;;EAGE,YAAA;EACA,0BAAA;C/BsjIP;A+BljIK;;;EAGE,YAAA;EACA,8BAAA;C/BojIP;A+B7iIK;;;EAGE,YAAA;EACA,0BAAA;C/B+iIP;A+B3iIG;EAAA;IAIM,YAAA;G/B2iIP;E+B1iIO;;IAEE,YAAA;IACA,8BAAA;G/B4iIT;E+BxiIO;;;IAGE,YAAA;IACA,0BAAA;G/B0iIT;E+BtiIO;;;IAGE,YAAA;IACA,8BAAA;G/BwiIT;CACF;A+BxnID;EAuFI,mBAAA;C/BoiIH;A+BniIG;;EAEE,uBAAA;C/BqiIL;A+B/nID;EA6FM,uBAAA;C/BqiIL;A+BloID;;EAmGI,sBAAA;C/BmiIH;A+BtoID;EA4GI,YAAA;C/B6hIH;A+B5hIG;EACE,YAAA;C/B8hIL;A+B5oID;EAmHI,YAAA;C/B4hIH;A+B3hIG;;EAEE,YAAA;C/B6hIL;A+BzhIK;;;;EAEE,YAAA;C/B6hIP;A+BrhID;EACE,uBAAA;EACA,sBAAA;C/BuhID;A+BzhID;EAKI,eAAA;C/BuhIH;A+BthIG;;EAEE,YAAA;EACA,8BAAA;C/BwhIL;A+BjiID;EAcI,eAAA;C/BshIH;A+BpiID;EAmBM,eAAA;C/BohIL;A+BlhIK;;EAEE,YAAA;EACA,8BAAA;C/BohIP;A+BhhIK;;;EAGE,YAAA;EACA,0BAAA;C/BkhIP;A+B9gIK;;;EAGE,YAAA;EACA,8BAAA;C/BghIP;A+B1gIK;;;EAGE,YAAA;EACA,0BAAA;C/B4gIP;A+BxgIG;EAAA;IAIM,sBAAA;G/BwgIP;E+B5gIC;IAOM,0BAAA;G/BwgIP;E+B/gIC;IAUM,eAAA;G/BwgIP;E+BvgIO;;IAEE,YAAA;IACA,8BAAA;G/BygIT;E+BrgIO;;;IAGE,YAAA;IACA,0BAAA;G/BugIT;E+BngIO;;;IAGE,YAAA;IACA,8BAAA;G/BqgIT;CACF;A+B1lID;EA6FI,mBAAA;C/BggIH;A+B//HG;;EAEE,uBAAA;C/BigIL;A+BjmID;EAmGM,uBAAA;C/BigIL;A+BpmID;;EAyGI,sBAAA;C/B+/HH;A+BxmID;EA6GI,eAAA;C/B8/HH;A+B7/HG;EACE,YAAA;C/B+/HL;A+B9mID;EAoHI,eAAA;C/B6/HH;A+B5/HG;;EAEE,YAAA;C/B8/HL;A+B1/HK;;;;EAEE,YAAA;C/B8/HP;AkCpoJD;EACE,kBAAA;EACA,oBAAA;EACA,iBAAA;EACA,0BAAA;EACA,mBAAA;ClCsoJD;AkC3oJD;EAQI,sBAAA;ClCsoJH;AkC9oJD;EAWM,eAAA;EACA,YAAA;EACA,kBAAA;ClCsoJL;AkCnpJD;EAkBI,eAAA;ClCooJH;AmCxpJD;EACE,sBAAA;EACA,gBAAA;EACA,eAAA;EACA,mBAAA;CnC0pJD;AmC9pJD;EAOI,gBAAA;CnC0pJH;AmCjqJD;;EAUM,mBAAA;EACA,YAAA;EACA,kBAAA;EACA,kBAAA;EACA,wBAAA;EACA,eAAA;EACA,sBAAA;EACA,uBAAA;EACA,uBAAA;CnC2pJL;AmCzpJK;;;;EAEE,WAAA;EACA,eAAA;EACA,0BAAA;EACA,mBAAA;CnC6pJP;AmC1pJG;;EAGI,eAAA;EPnBN,4BAAA;EACA,+BAAA;C5B+qJD;AmCzpJG;;EP/BF,6BAAA;EACA,gCAAA;C5B4rJD;AmCppJG;;;;;;EAGE,WAAA;EACA,YAAA;EACA,gBAAA;EACA,0BAAA;EACA,sBAAA;CnCypJL;AmC7sJD;;;;;;EA+DM,eAAA;EACA,oBAAA;EACA,uBAAA;EACA,mBAAA;CnCspJL;AmC7oJD;;ECxEM,mBAAA;EACA,gBAAA;EACA,uBAAA;CpCytJL;AoCvtJG;;ERKF,4BAAA;EACA,+BAAA;C5BstJD;AoCttJG;;ERTF,6BAAA;EACA,gCAAA;C5BmuJD;AmCxpJD;;EC7EM,kBAAA;EACA,gBAAA;EACA,iBAAA;CpCyuJL;AoCvuJG;;ERKF,4BAAA;EACA,+BAAA;C5BsuJD;AoCtuJG;;ERTF,6BAAA;EACA,gCAAA;C5BmvJD;AqCtvJD;EACE,gBAAA;EACA,eAAA;EACA,mBAAA;EACA,iBAAA;CrCwvJD;AqC5vJD;EAOI,gBAAA;CrCwvJH;AqC/vJD;;EAUM,sBAAA;EACA,kBAAA;EACA,uBAAA;EACA,uBAAA;EACA,oBAAA;CrCyvJL;AqCvwJD;;EAmBM,sBAAA;EACA,0BAAA;CrCwvJL;AqC5wJD;;EA2BM,aAAA;CrCqvJL;AqChxJD;;EAkCM,YAAA;CrCkvJL;AqCpxJD;;;;EA2CM,eAAA;EACA,oBAAA;EACA,uBAAA;CrC+uJL;AsC7xJD;EACE,gBAAA;EACA,2BAAA;EACA,eAAA;EACA,iBAAA;EACA,eAAA;EACA,YAAA;EACA,mBAAA;EACA,oBAAA;EACA,yBAAA;EACA,sBAAA;CtC+xJD;AsC3xJG;;EAEE,YAAA;EACA,sBAAA;EACA,gBAAA;CtC6xJL;AsCxxJC;EACE,cAAA;CtC0xJH;AsCtxJC;EACE,mBAAA;EACA,UAAA;CtCwxJH;AsCjxJD;ECtCE,0BAAA;CvC0zJD;AuCvzJG;;EAEE,0BAAA;CvCyzJL;AsCpxJD;EC1CE,0BAAA;CvCi0JD;AuC9zJG;;EAEE,0BAAA;CvCg0JL;AsCvxJD;EC9CE,0BAAA;CvCw0JD;AuCr0JG;;EAEE,0BAAA;CvCu0JL;AsC1xJD;EClDE,0BAAA;CvC+0JD;AuC50JG;;EAEE,0BAAA;CvC80JL;AsC7xJD;ECtDE,0BAAA;CvCs1JD;AuCn1JG;;EAEE,0BAAA;CvCq1JL;AsChyJD;EC1DE,0BAAA;CvC61JD;AuC11JG;;EAEE,0BAAA;CvC41JL;AwC91JD;EACE,sBAAA;EACA,gBAAA;EACA,iBAAA;EACA,gBAAA;EACA,kBAAA;EACA,eAAA;EACA,YAAA;EACA,mBAAA;EACA,oBAAA;EACA,uBAAA;EACA,0BAAA;EACA,oBAAA;CxCg2JD;AwC71JC;EACE,cAAA;CxC+1JH;AwC31JC;EACE,mBAAA;EACA,UAAA;CxC61JH;AwC11JC;;EAEE,OAAA;EACA,iBAAA;CxC41JH;AwCv1JG;;EAEE,YAAA;EACA,sBAAA;EACA,gBAAA;CxCy1JL;AwCp1JC;;EAEE,eAAA;EACA,uBAAA;CxCs1JH;AwCn1JC;EACE,aAAA;CxCq1JH;AwCl1JC;EACE,kBAAA;CxCo1JH;AwCj1JC;EACE,iBAAA;CxCm1JH;AyC74JD;EACE,kBAAA;EACA,qBAAA;EACA,oBAAA;EACA,eAAA;EACA,0BAAA;CzC+4JD;AyCp5JD;;EASI,eAAA;CzC+4JH;AyCx5JD;EAaI,oBAAA;EACA,gBAAA;EACA,iBAAA;CzC84JH;AyC75JD;EAmBI,0BAAA;CzC64JH;AyC14JC;;EAEE,oBAAA;EACA,mBAAA;EACA,mBAAA;CzC44JH;AyCt6JD;EA8BI,gBAAA;CzC24JH;AyCx4JC;EAAA;IACE,kBAAA;IACA,qBAAA;GzC24JD;EyCz4JC;;IAEE,oBAAA;IACA,mBAAA;GzC24JH;EyCl5JD;;IAYI,gBAAA;GzC04JH;CACF;A0Cr7JD;EACE,eAAA;EACA,aAAA;EACA,oBAAA;EACA,wBAAA;EACA,uBAAA;EACA,uBAAA;EACA,mBAAA;ErCiLA,4CAAA;EACK,uCAAA;EACG,oCAAA;CLuwJT;A0Cj8JD;;EAaI,mBAAA;EACA,kBAAA;C1Cw7JH;A0Cp7JC;;;EAGE,sBAAA;C1Cs7JH;A0C38JD;EA0BI,aAAA;EACA,eAAA;C1Co7JH;A2C/8JD;EACE,cAAA;EACA,oBAAA;EACA,8BAAA;EACA,mBAAA;C3Ci9JD;A2Cr9JD;EAQI,cAAA;EACA,eAAA;C3Cg9JH;A2Cz9JD;EAcI,kBAAA;C3C88JH;A2C59JD;;EAoBI,iBAAA;C3C48JH;A2Ch+JD;EAwBI,gBAAA;C3C28JH;A2Cl8JD;;EAEE,oBAAA;C3Co8JD;A2Ct8JD;;EAMI,mBAAA;EACA,UAAA;EACA,aAAA;EACA,eAAA;C3Co8JH;A2C57JD;ECvDE,eAAA;EACA,0BAAA;EACA,sBAAA;C5Cs/JD;A2Cj8JD;EClDI,0BAAA;C5Cs/JH;A2Cp8JD;EC9CI,eAAA;C5Cq/JH;A2Cn8JD;EC3DE,eAAA;EACA,0BAAA;EACA,sBAAA;C5CigKD;A2Cx8JD;ECtDI,0BAAA;C5CigKH;A2C38JD;EClDI,eAAA;C5CggKH;A2C18JD;EC/DE,eAAA;EACA,0BAAA;EACA,sBAAA;C5C4gKD;A2C/8JD;EC1DI,0BAAA;C5C4gKH;A2Cl9JD;ECtDI,eAAA;C5C2gKH;A2Cj9JD;ECnEE,eAAA;EACA,0BAAA;EACA,sBAAA;C5CuhKD;A2Ct9JD;EC9DI,0BAAA;C5CuhKH;A2Cz9JD;EC1DI,eAAA;C5CshKH;A6CvhKD;EACE;IAAQ,4BAAA;G7C0hKP;E6CzhKD;IAAQ,yBAAA;G7C4hKP;CACF;A6CzhKD;EACE;IAAQ,4BAAA;G7C4hKP;E6C3hKD;IAAQ,yBAAA;G7C8hKP;CACF;A6CjiKD;EACE;IAAQ,4BAAA;G7C4hKP;E6C3hKD;IAAQ,yBAAA;G7C8hKP;CACF;A6CvhKD;EACE,aAAA;EACA,oBAAA;EACA,iBAAA;EACA,0BAAA;EACA,mBAAA;ExCsCA,uDAAA;EACQ,+CAAA;CLo/JT;A6CthKD;EACE,YAAA;EACA,UAAA;EACA,aAAA;EACA,gBAAA;EACA,kBAAA;EACA,YAAA;EACA,mBAAA;EACA,0BAAA;ExCyBA,uDAAA;EACQ,+CAAA;EAyHR,oCAAA;EACK,+BAAA;EACG,4BAAA;CLw4JT;A6CnhKD;;ECDI,8MAAA;EACA,yMAAA;EACA,sMAAA;EDEF,mCAAA;EAAA,2BAAA;C7CuhKD;A6ChhKD;;ExC5CE,2DAAA;EACK,sDAAA;EACG,mDAAA;CLgkKT;A6C7gKD;EEvEE,0BAAA;C/CulKD;A+CplKC;EDgDE,8MAAA;EACA,yMAAA;EACA,sMAAA;C9CuiKH;A6CjhKD;EE3EE,0BAAA;C/C+lKD;A+C5lKC;EDgDE,8MAAA;EACA,yMAAA;EACA,sMAAA;C9C+iKH;A6CrhKD;EE/EE,0BAAA;C/CumKD;A+CpmKC;EDgDE,8MAAA;EACA,yMAAA;EACA,sMAAA;C9CujKH;A6CzhKD;EEnFE,0BAAA;C/C+mKD;A+C5mKC;EDgDE,8MAAA;EACA,yMAAA;EACA,sMAAA;C9C+jKH;AgDvnKD;EAEE,iBAAA;ChDwnKD;AgDtnKC;EACE,cAAA;ChDwnKH;AgDpnKD;;EAEE,iBAAA;EACA,QAAA;ChDsnKD;AgDnnKD;EACE,eAAA;ChDqnKD;AgDlnKD;EACE,eAAA;ChDonKD;AgDjnKC;EACE,gBAAA;ChDmnKH;AgD/mKD;;EAEE,mBAAA;ChDinKD;AgD9mKD;;EAEE,oBAAA;ChDgnKD;AgD7mKD;;;EAGE,oBAAA;EACA,oBAAA;ChD+mKD;AgD5mKD;EACE,uBAAA;ChD8mKD;AgD3mKD;EACE,uBAAA;ChD6mKD;AgDzmKD;EACE,cAAA;EACA,mBAAA;ChD2mKD;AgDrmKD;EACE,gBAAA;EACA,iBAAA;ChDumKD;AiD5pKD;EAEE,gBAAA;EACA,oBAAA;CjD6pKD;AiDrpKD;EACE,mBAAA;EACA,eAAA;EACA,mBAAA;EAEA,oBAAA;EACA,uBAAA;EACA,uBAAA;CjDspKD;AiDnpKC;ErB7BA,4BAAA;EACA,6BAAA;C5BmrKD;AiDppKC;EACE,iBAAA;ErBzBF,gCAAA;EACA,+BAAA;C5BgrKD;AiDnpKC;;;EAGE,eAAA;EACA,oBAAA;EACA,0BAAA;CjDqpKH;AiD1pKC;;;EASI,eAAA;CjDspKL;AiD/pKC;;;EAYI,eAAA;CjDwpKL;AiDnpKC;;;EAGE,WAAA;EACA,YAAA;EACA,0BAAA;EACA,sBAAA;CjDqpKH;AiD3pKC;;;;;;;;;EAYI,eAAA;CjD0pKL;AiDtqKC;;;EAeI,eAAA;CjD4pKL;AiDjpKD;;EAEE,YAAA;CjDmpKD;AiDrpKD;;EAKI,YAAA;CjDopKH;AiDhpKC;;;;EAEE,YAAA;EACA,sBAAA;EACA,0BAAA;CjDopKH;AiDhpKD;EACE,YAAA;EACA,iBAAA;CjDkpKD;AczvKA;EoCIG,eAAA;EACA,0BAAA;ClDwvKH;AkDtvKG;;EAEE,eAAA;ClDwvKL;AkD1vKG;;EAKI,eAAA;ClDyvKP;AkDtvKK;;;;EAEE,eAAA;EACA,0BAAA;ClD0vKP;AkDxvKK;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;ClD6vKP;ActxKA;EoCIG,eAAA;EACA,0BAAA;ClDqxKH;AkDnxKG;;EAEE,eAAA;ClDqxKL;AkDvxKG;;EAKI,eAAA;ClDsxKP;AkDnxKK;;;;EAEE,eAAA;EACA,0BAAA;ClDuxKP;AkDrxKK;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;ClD0xKP;AcnzKA;EoCIG,eAAA;EACA,0BAAA;ClDkzKH;AkDhzKG;;EAEE,eAAA;ClDkzKL;AkDpzKG;;EAKI,eAAA;ClDmzKP;AkDhzKK;;;;EAEE,eAAA;EACA,0BAAA;ClDozKP;AkDlzKK;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;ClDuzKP;Ach1KA;EoCIG,eAAA;EACA,0BAAA;ClD+0KH;AkD70KG;;EAEE,eAAA;ClD+0KL;AkDj1KG;;EAKI,eAAA;ClDg1KP;AkD70KK;;;;EAEE,eAAA;EACA,0BAAA;ClDi1KP;AkD/0KK;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;ClDo1KP;AiDnvKD;EACE,cAAA;EACA,mBAAA;CjDqvKD;AiDnvKD;EACE,iBAAA;EACA,iBAAA;CjDqvKD;AmD72KD;EACE,oBAAA;EACA,uBAAA;EACA,8BAAA;EACA,mBAAA;E9C0DA,kDAAA;EACQ,0CAAA;CLszKT;AmD52KD;EACE,cAAA;CnD82KD;AmDz2KD;EACE,mBAAA;EACA,qCAAA;EvBtBA,4BAAA;EACA,6BAAA;C5Bk4KD;AmD/2KD;EAMI,eAAA;CnD42KH;AmDv2KD;EACE,cAAA;EACA,iBAAA;EACA,gBAAA;EACA,eAAA;CnDy2KD;AmD72KD;;;;;EAWI,eAAA;CnDy2KH;AmDp2KD;EACE,mBAAA;EACA,0BAAA;EACA,2BAAA;EvB1CA,gCAAA;EACA,+BAAA;C5Bi5KD;AmD91KD;;EAGI,iBAAA;CnD+1KH;AmDl2KD;;EAMM,oBAAA;EACA,iBAAA;CnDg2KL;AmD51KG;;EAEI,cAAA;EvBzEN,4BAAA;EACA,6BAAA;C5Bw6KD;AmD11KG;;EAEI,iBAAA;EvBzEN,gCAAA;EACA,+BAAA;C5Bs6KD;AmDn3KD;EvB5DE,0BAAA;EACA,2BAAA;C5Bk7KD;AmDt1KD;EAEI,oBAAA;CnDu1KH;AmDp1KD;EACE,oBAAA;CnDs1KD;AmD90KD;;;EAII,iBAAA;CnD+0KH;AmDn1KD;;;EAOM,oBAAA;EACA,mBAAA;CnDi1KL;AmDz1KD;;EvB3GE,4BAAA;EACA,6BAAA;C5Bw8KD;AmD91KD;;;;EAmBQ,4BAAA;EACA,6BAAA;CnDi1KP;AmDr2KD;;;;;;;;EAwBU,4BAAA;CnDu1KT;AmD/2KD;;;;;;;;EA4BU,6BAAA;CnD61KT;AmDz3KD;;EvBnGE,gCAAA;EACA,+BAAA;C5Bg+KD;AmD93KD;;;;EAyCQ,gCAAA;EACA,+BAAA;CnD21KP;AmDr4KD;;;;;;;;EA8CU,+BAAA;CnDi2KT;AmD/4KD;;;;;;;;EAkDU,gCAAA;CnDu2KT;AmDz5KD;;;;EA2DI,2BAAA;CnDo2KH;AmD/5KD;;EA+DI,cAAA;CnDo2KH;AmDn6KD;;EAmEI,UAAA;CnDo2KH;AmDv6KD;;;;;;;;;;;;EA0EU,eAAA;CnD22KT;AmDr7KD;;;;;;;;;;;;EA8EU,gBAAA;CnDq3KT;AmDn8KD;;;;;;;;EAuFU,iBAAA;CnDs3KT;AmD78KD;;;;;;;;EAgGU,iBAAA;CnDu3KT;AmDv9KD;EAsGI,iBAAA;EACA,UAAA;CnDo3KH;AmD12KD;EACE,oBAAA;CnD42KD;AmD72KD;EAKI,iBAAA;EACA,mBAAA;CnD22KH;AmDj3KD;EASM,gBAAA;CnD22KL;AmDp3KD;EAcI,iBAAA;CnDy2KH;AmDv3KD;;EAkBM,2BAAA;CnDy2KL;AmD33KD;EAuBI,cAAA;CnDu2KH;AmD93KD;EAyBM,8BAAA;CnDw2KL;AmDj2KD;EC5PE,mBAAA;CpDgmLD;AoD9lLC;EACE,eAAA;EACA,0BAAA;EACA,mBAAA;CpDgmLH;AoDnmLC;EAMI,uBAAA;CpDgmLL;AoDtmLC;EASI,eAAA;EACA,0BAAA;CpDgmLL;AoD7lLC;EAEI,0BAAA;CpD8lLL;AmDh3KD;EC/PE,sBAAA;CpDknLD;AoDhnLC;EACE,YAAA;EACA,0BAAA;EACA,sBAAA;CpDknLH;AoDrnLC;EAMI,0BAAA;CpDknLL;AoDxnLC;EASI,eAAA;EACA,uBAAA;CpDknLL;AoD/mLC;EAEI,6BAAA;CpDgnLL;AmD/3KD;EClQE,sBAAA;CpDooLD;AoDloLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpDooLH;AoDvoLC;EAMI,0BAAA;CpDooLL;AoD1oLC;EASI,eAAA;EACA,0BAAA;CpDooLL;AoDjoLC;EAEI,6BAAA;CpDkoLL;AmD94KD;ECrQE,sBAAA;CpDspLD;AoDppLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpDspLH;AoDzpLC;EAMI,0BAAA;CpDspLL;AoD5pLC;EASI,eAAA;EACA,0BAAA;CpDspLL;AoDnpLC;EAEI,6BAAA;CpDopLL;AmD75KD;ECxQE,sBAAA;CpDwqLD;AoDtqLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpDwqLH;AoD3qLC;EAMI,0BAAA;CpDwqLL;AoD9qLC;EASI,eAAA;EACA,0BAAA;CpDwqLL;AoDrqLC;EAEI,6BAAA;CpDsqLL;AmD56KD;EC3QE,sBAAA;CpD0rLD;AoDxrLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpD0rLH;AoD7rLC;EAMI,0BAAA;CpD0rLL;AoDhsLC;EASI,eAAA;EACA,0BAAA;CpD0rLL;AoDvrLC;EAEI,6BAAA;CpDwrLL;AqDxsLD;EACE,mBAAA;EACA,eAAA;EACA,UAAA;EACA,WAAA;EACA,iBAAA;CrD0sLD;AqD/sLD;;;;;EAYI,mBAAA;EACA,OAAA;EACA,UAAA;EACA,QAAA;EACA,YAAA;EACA,aAAA;EACA,UAAA;CrD0sLH;AqDrsLD;EACE,uBAAA;CrDusLD;AqDnsLD;EACE,oBAAA;CrDqsLD;AsDhuLD;EACE,iBAAA;EACA,cAAA;EACA,oBAAA;EACA,0BAAA;EACA,0BAAA;EACA,mBAAA;EjD0DA,wDAAA;EACQ,gDAAA;CLyqLT;AsD1uLD;EASI,mBAAA;EACA,kCAAA;CtDouLH;AsD/tLD;EACE,cAAA;EACA,mBAAA;CtDiuLD;AsD/tLD;EACE,aAAA;EACA,mBAAA;CtDiuLD;AuDrvLD;EACE,aAAA;EACA,gBAAA;EACA,kBAAA;EACA,eAAA;EACA,YAAA;EACA,0BAAA;EjCTA,0BAAA;EACA,aAAA;CtBiwLD;AuDtvLC;;EAEE,YAAA;EACA,sBAAA;EACA,gBAAA;EjChBF,0BAAA;EACA,aAAA;CtBywLD;AuDlvLC;EACE,WAAA;EACA,gBAAA;EACA,wBAAA;EACA,UAAA;EACA,yBAAA;EACA,sBAAA;EAAA,iBAAA;CvDovLH;AwD5wLD;EACE,iBAAA;CxD8wLD;AwD1wLD;EACE,gBAAA;EACA,OAAA;EACA,SAAA;EACA,UAAA;EACA,QAAA;EACA,cAAA;EACA,cAAA;EACA,iBAAA;EACA,kCAAA;EAIA,WAAA;CxDywLD;AwDtwLC;EnDiHA,sCAAA;EACI,kCAAA;EACC,iCAAA;EACG,8BAAA;EAkER,oDAAA;EAEK,0CAAA;EACG,4CAAA;EAAA,oCAAA;EAAA,iGAAA;CLulLT;AwD5wLC;EnD6GA,mCAAA;EACI,+BAAA;EACC,8BAAA;EACG,2BAAA;CLkqLT;AwDhxLD;EACE,mBAAA;EACA,iBAAA;CxDkxLD;AwD9wLD;EACE,mBAAA;EACA,YAAA;EACA,aAAA;CxDgxLD;AwD5wLD;EACE,mBAAA;EACA,uBAAA;EACA,6BAAA;EACA,uBAAA;EACA,qCAAA;EACA,mBAAA;EnDcA,iDAAA;EACQ,yCAAA;EmDZR,WAAA;CxD8wLD;AwD1wLD;EACE,gBAAA;EACA,OAAA;EACA,SAAA;EACA,UAAA;EACA,QAAA;EACA,cAAA;EACA,uBAAA;CxD4wLD;AwD1wLC;ElCpEA,yBAAA;EACA,WAAA;CtBi1LD;AwD7wLC;ElCrEA,0BAAA;EACA,aAAA;CtBq1LD;AwD5wLD;EACE,cAAA;EACA,iCAAA;CxD8wLD;AwD1wLD;EACE,iBAAA;CxD4wLD;AwDxwLD;EACE,UAAA;EACA,wBAAA;CxD0wLD;AwDrwLD;EACE,mBAAA;EACA,cAAA;CxDuwLD;AwDnwLD;EACE,cAAA;EACA,kBAAA;EACA,8BAAA;CxDqwLD;AwDxwLD;EAQI,iBAAA;EACA,iBAAA;CxDmwLH;AwD5wLD;EAaI,kBAAA;CxDkwLH;AwD/wLD;EAiBI,eAAA;CxDiwLH;AwD5vLD;EACE,mBAAA;EACA,aAAA;EACA,YAAA;EACA,aAAA;EACA,iBAAA;CxD8vLD;AwD1vLD;EAEE;IACE,aAAA;IACA,kBAAA;GxD2vLD;EwDzvLD;InDrEA,kDAAA;IACQ,0CAAA;GLi0LP;EwDxvLD;IAAY,aAAA;GxD2vLX;CACF;AwDzvLD;EACE;IAAY,aAAA;GxD4vLX;CACF;AyD34LD;EACE,mBAAA;EACA,cAAA;EACA,eAAA;ECRA,4DAAA;EAEA,mBAAA;EACA,iBAAA;EACA,wBAAA;EACA,iBAAA;EACA,iBAAA;EACA,kBAAA;EACA,sBAAA;EACA,kBAAA;EACA,qBAAA;EACA,uBAAA;EACA,mBAAA;EACA,qBAAA;EACA,kBAAA;EACA,oBAAA;EDHA,gBAAA;EnCTA,yBAAA;EACA,WAAA;CtBm6LD;AyDv5LC;EnCbA,0BAAA;EACA,aAAA;CtBu6LD;AyD15LC;EACE,eAAA;EACA,iBAAA;CzD45LH;AyD15LC;EACE,eAAA;EACA,iBAAA;CzD45LH;AyD15LC;EACE,eAAA;EACA,gBAAA;CzD45LH;AyD15LC;EACE,eAAA;EACA,kBAAA;CzD45LH;AyDx5LC;EACE,UAAA;EACA,UAAA;EACA,kBAAA;EACA,wBAAA;EACA,uBAAA;CzD05LH;AyDx5LC;EACE,WAAA;EACA,UAAA;EACA,oBAAA;EACA,wBAAA;EACA,uBAAA;CzD05LH;AyDx5LC;EACE,UAAA;EACA,UAAA;EACA,oBAAA;EACA,wBAAA;EACA,uBAAA;CzD05LH;AyDx5LC;EACE,SAAA;EACA,QAAA;EACA,iBAAA;EACA,4BAAA;EACA,yBAAA;CzD05LH;AyDx5LC;EACE,SAAA;EACA,SAAA;EACA,iBAAA;EACA,4BAAA;EACA,wBAAA;CzD05LH;AyDx5LC;EACE,OAAA;EACA,UAAA;EACA,kBAAA;EACA,wBAAA;EACA,0BAAA;CzD05LH;AyDx5LC;EACE,OAAA;EACA,WAAA;EACA,iBAAA;EACA,wBAAA;EACA,0BAAA;CzD05LH;AyDx5LC;EACE,OAAA;EACA,UAAA;EACA,iBAAA;EACA,wBAAA;EACA,0BAAA;CzD05LH;AyDr5LD;EACE,iBAAA;EACA,iBAAA;EACA,YAAA;EACA,mBAAA;EACA,uBAAA;EACA,mBAAA;CzDu5LD;AyDn5LD;EACE,mBAAA;EACA,SAAA;EACA,UAAA;EACA,0BAAA;EACA,oBAAA;CzDq5LD;A2D9/LD;EACE,mBAAA;EACA,OAAA;EACA,QAAA;EACA,cAAA;EACA,cAAA;EACA,iBAAA;EACA,aAAA;EDXA,4DAAA;EAEA,mBAAA;EACA,iBAAA;EACA,wBAAA;EACA,iBAAA;EACA,iBAAA;EACA,kBAAA;EACA,sBAAA;EACA,kBAAA;EACA,qBAAA;EACA,uBAAA;EACA,mBAAA;EACA,qBAAA;EACA,kBAAA;EACA,oBAAA;ECAA,gBAAA;EACA,uBAAA;EACA,6BAAA;EACA,uBAAA;EACA,qCAAA;EACA,mBAAA;EtDiDA,kDAAA;EACQ,0CAAA;CL49LT;A2D1gMC;EAAQ,kBAAA;C3D6gMT;A2D5gMC;EAAU,kBAAA;C3D+gMX;A2D9gMC;EAAW,iBAAA;C3DihMZ;A2DhhMC;EAAS,mBAAA;C3DmhMV;A2D1iMD;EA4BI,mBAAA;C3DihMH;A2D/gMG;;EAEE,mBAAA;EACA,eAAA;EACA,SAAA;EACA,UAAA;EACA,0BAAA;EACA,oBAAA;C3DihML;A2D9gMG;EACE,YAAA;EACA,mBAAA;C3DghML;A2D5gMC;EACE,cAAA;EACA,UAAA;EACA,mBAAA;EACA,0BAAA;EACA,sCAAA;EACA,uBAAA;C3D8gMH;A2D7gMG;EACE,YAAA;EACA,mBAAA;EACA,aAAA;EACA,uBAAA;EACA,uBAAA;C3D+gML;A2D5gMC;EACE,SAAA;EACA,YAAA;EACA,kBAAA;EACA,4BAAA;EACA,wCAAA;EACA,qBAAA;C3D8gMH;A2D7gMG;EACE,cAAA;EACA,UAAA;EACA,aAAA;EACA,yBAAA;EACA,qBAAA;C3D+gML;A2D5gMC;EACE,WAAA;EACA,UAAA;EACA,mBAAA;EACA,oBAAA;EACA,6BAAA;EACA,yCAAA;C3D8gMH;A2D7gMG;EACE,SAAA;EACA,mBAAA;EACA,aAAA;EACA,oBAAA;EACA,0BAAA;C3D+gML;A2D3gMC;EACE,SAAA;EACA,aAAA;EACA,kBAAA;EACA,sBAAA;EACA,2BAAA;EACA,uCAAA;C3D6gMH;A2D5gMG;EACE,WAAA;EACA,cAAA;EACA,aAAA;EACA,sBAAA;EACA,wBAAA;C3D8gML;A2DzgMD;EACE,kBAAA;EACA,UAAA;EACA,gBAAA;EACA,0BAAA;EACA,iCAAA;EACA,2BAAA;C3D2gMD;A2DxgMD;EACE,kBAAA;C3D0gMD;A4D9nMD;EACE,mBAAA;C5DgoMD;A4D7nMD;EACE,mBAAA;EACA,YAAA;EACA,iBAAA;C5D+nMD;A4DloMD;EAMI,mBAAA;EACA,cAAA;EvD6KF,0CAAA;EACK,qCAAA;EACG,kCAAA;CLm9LT;A4DzoMD;;EAcM,eAAA;C5D+nML;A4D3nMG;EAAA;IvDuLF,uDAAA;IAEK,6CAAA;IACG,+CAAA;IAAA,uCAAA;IAAA,0GAAA;IA7JR,oCAAA;IAEQ,4BAAA;IA+GR,4BAAA;IAEQ,oBAAA;GLw/LP;E4DnoMG;;IvDmHJ,2CAAA;IACQ,mCAAA;IuDjHF,QAAA;G5DsoML;E4DpoMG;;IvD8GJ,4CAAA;IACQ,oCAAA;IuD5GF,QAAA;G5DuoML;E4DroMG;;;IvDyGJ,wCAAA;IACQ,gCAAA;IuDtGF,QAAA;G5DwoML;CACF;A4D9qMD;;;EA6CI,eAAA;C5DsoMH;A4DnrMD;EAiDI,QAAA;C5DqoMH;A4DtrMD;;EAsDI,mBAAA;EACA,OAAA;EACA,YAAA;C5DooMH;A4D5rMD;EA4DI,WAAA;C5DmoMH;A4D/rMD;EA+DI,YAAA;C5DmoMH;A4DlsMD;;EAmEI,QAAA;C5DmoMH;A4DtsMD;EAuEI,YAAA;C5DkoMH;A4DzsMD;EA0EI,WAAA;C5DkoMH;A4D1nMD;EACE,mBAAA;EACA,OAAA;EACA,UAAA;EACA,QAAA;EACA,WAAA;EACA,gBAAA;EACA,YAAA;EACA,mBAAA;EACA,0CAAA;EACA,mCAAA;EtCpGA,0BAAA;EACA,aAAA;CtBiuMD;A4DxnMC;EdrGE,mGAAA;EACA,8FAAA;EACA,qHAAA;EAAA,+FAAA;EACA,uHAAA;EACA,4BAAA;C9CguMH;A4D5nMC;EACE,SAAA;EACA,WAAA;Ed1GA,mGAAA;EACA,8FAAA;EACA,qHAAA;EAAA,+FAAA;EACA,uHAAA;EACA,4BAAA;C9CyuMH;A4D9nMC;;EAEE,YAAA;EACA,sBAAA;EACA,WAAA;EtCxHF,0BAAA;EACA,aAAA;CtByvMD;A4DhqMD;;;;EAuCI,mBAAA;EACA,SAAA;EACA,WAAA;EACA,sBAAA;EACA,kBAAA;C5D+nMH;A4D1qMD;;EA+CI,UAAA;EACA,mBAAA;C5D+nMH;A4D/qMD;;EAoDI,WAAA;EACA,oBAAA;C5D+nMH;A4DprMD;;EAyDI,YAAA;EACA,aAAA;EACA,mBAAA;EACA,eAAA;C5D+nMH;A4D3nMG;EACE,iBAAA;C5D6nML;A4DznMG;EACE,iBAAA;C5D2nML;A4DjnMD;EACE,mBAAA;EACA,aAAA;EACA,UAAA;EACA,YAAA;EACA,WAAA;EACA,gBAAA;EACA,kBAAA;EACA,mBAAA;EACA,iBAAA;C5DmnMD;A4D5nMD;EAYI,sBAAA;EACA,YAAA;EACA,aAAA;EACA,YAAA;EACA,oBAAA;EACA,gBAAA;EAUA,0BAAA;EACA,mCAAA;EAEA,uBAAA;EACA,oBAAA;C5DymMH;A4DxoMD;EAmCI,YAAA;EACA,aAAA;EACA,UAAA;EACA,uBAAA;C5DwmMH;A4DjmMD;EACE,mBAAA;EACA,WAAA;EACA,aAAA;EACA,UAAA;EACA,YAAA;EACA,kBAAA;EACA,qBAAA;EACA,YAAA;EACA,mBAAA;EACA,0CAAA;C5DmmMD;A4DjmMC;EACE,kBAAA;C5DmmMH;A4D7lMD;EAGE;;;;IAKI,YAAA;IACA,aAAA;IACA,kBAAA;IACA,gBAAA;G5D4lMH;E4DpmMD;;IAYI,mBAAA;G5D4lMH;E4DxmMD;;IAgBI,oBAAA;G5D4lMH;E4DvlMD;IACE,WAAA;IACA,UAAA;IACA,qBAAA;G5DylMD;E4DrlMD;IACE,aAAA;G5DulMD;CACF;A6Dz1MC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAEE,eAAA;EACA,aAAA;C7Dy3MH;A6Dv3MC;;;;;;;;;;;;;;;;EACE,YAAA;C7Dw4MH;AiC94MD;E6BVE,eAAA;EACA,mBAAA;EACA,kBAAA;C9D25MD;AiCh5MD;EACE,wBAAA;CjCk5MD;AiCh5MD;EACE,uBAAA;CjCk5MD;AiC14MD;EACE,yBAAA;CjC44MD;AiC14MD;EACE,0BAAA;CjC44MD;AiC14MD;EACE,mBAAA;CjC44MD;AiC14MD;E8BzBE,YAAA;EACA,mBAAA;EACA,kBAAA;EACA,8BAAA;EACA,UAAA;C/Ds6MD;AiCx4MD;EACE,yBAAA;CjC04MD;AiCn4MD;EACE,gBAAA;CjCq4MD;AgEt6MD;EACE,oBAAA;ChEw6MD;AgEl6MD;;;;EClBE,yBAAA;CjE07MD;AgEj6MD;;;;;;;;;;;;EAYE,yBAAA;ChEm6MD;AgE/5MC;EAAA;ICjDA,0BAAA;GjEo9MC;EiEn9MD;IAAU,0BAAA;GjEs9MT;EiEr9MD;IAAU,8BAAA;GjEw9MT;EiEv9MD;;IACU,+BAAA;GjE09MT;CACF;AgEz6MC;EAAA;IACE,0BAAA;GhE46MD;CACF;AgEz6MC;EAAA;IACE,2BAAA;GhE46MD;CACF;AgEz6MC;EAAA;IACE,iCAAA;GhE46MD;CACF;AgEx6MC;EAAA;ICtEA,0BAAA;GjEk/MC;EiEj/MD;IAAU,0BAAA;GjEo/MT;EiEn/MD;IAAU,8BAAA;GjEs/MT;EiEr/MD;;IACU,+BAAA;GjEw/MT;CACF;AgEl7MC;EAAA;IACE,0BAAA;GhEq7MD;CACF;AgEl7MC;EAAA;IACE,2BAAA;GhEq7MD;CACF;AgEl7MC;EAAA;IACE,iCAAA;GhEq7MD;CACF;AgEj7MC;EAAA;IC3FA,0BAAA;GjEghNC;EiE/gND;IAAU,0BAAA;GjEkhNT;EiEjhND;IAAU,8BAAA;GjEohNT;EiEnhND;;IACU,+BAAA;GjEshNT;CACF;AgE37MC;EAAA;IACE,0BAAA;GhE87MD;CACF;AgE37MC;EAAA;IACE,2BAAA;GhE87MD;CACF;AgE37MC;EAAA;IACE,iCAAA;GhE87MD;CACF;AgE17MC;EAAA;IChHA,0BAAA;GjE8iNC;EiE7iND;IAAU,0BAAA;GjEgjNT;EiE/iND;IAAU,8BAAA;GjEkjNT;EiEjjND;;IACU,+BAAA;GjEojNT;CACF;AgEp8MC;EAAA;IACE,0BAAA;GhEu8MD;CACF;AgEp8MC;EAAA;IACE,2BAAA;GhEu8MD;CACF;AgEp8MC;EAAA;IACE,iCAAA;GhEu8MD;CACF;AgEn8MC;EAAA;IC7HA,yBAAA;GjEokNC;CACF;AgEn8MC;EAAA;IClIA,yBAAA;GjEykNC;CACF;AgEn8MC;EAAA;ICvIA,yBAAA;GjE8kNC;CACF;AgEn8MC;EAAA;IC5IA,yBAAA;GjEmlNC;CACF;AgE77MD;ECvJE,yBAAA;CjEulND;AgE77MC;EAAA;IClKA,0BAAA;GjEmmNC;EiElmND;IAAU,0BAAA;GjEqmNT;EiEpmND;IAAU,8BAAA;GjEumNT;EiEtmND;;IACU,+BAAA;GjEymNT;CACF;AgEx8MD;EACE,yBAAA;ChE08MD;AgEx8MC;EAAA;IACE,0BAAA;GhE28MD;CACF;AgEz8MD;EACE,yBAAA;ChE28MD;AgEz8MC;EAAA;IACE,2BAAA;GhE48MD;CACF;AgE18MD;EACE,yBAAA;ChE48MD;AgE18MC;EAAA;IACE,iCAAA;GhE68MD;CACF;AgEz8MC;EAAA;ICrLA,yBAAA;GjEkoNC;CACF","file":"bootstrap.css","sourcesContent":["/*!\n * Bootstrap v3.4.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\nhtml {\n font-family: sans-serif;\n -ms-text-size-adjust: 100%;\n -webkit-text-size-adjust: 100%;\n}\nbody {\n margin: 0;\n}\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block;\n vertical-align: baseline;\n}\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n[hidden],\ntemplate {\n display: none;\n}\na {\n background-color: transparent;\n}\na:active,\na:hover {\n outline: 0;\n}\nabbr[title] {\n border-bottom: none;\n text-decoration: underline;\n text-decoration: underline dotted;\n}\nb,\nstrong {\n font-weight: bold;\n}\ndfn {\n font-style: italic;\n}\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\nmark {\n background: #ff0;\n color: #000;\n}\nsmall {\n font-size: 80%;\n}\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\nsup {\n top: -0.5em;\n}\nsub {\n bottom: -0.25em;\n}\nimg {\n border: 0;\n}\nsvg:not(:root) {\n overflow: hidden;\n}\nfigure {\n margin: 1em 40px;\n}\nhr {\n box-sizing: content-box;\n height: 0;\n}\npre {\n overflow: auto;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit;\n font: inherit;\n margin: 0;\n}\nbutton {\n overflow: visible;\n}\nbutton,\nselect {\n text-transform: none;\n}\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button;\n cursor: pointer;\n}\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\ninput {\n line-height: normal;\n}\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box;\n padding: 0;\n}\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: textfield;\n box-sizing: content-box;\n}\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\nlegend {\n border: 0;\n padding: 0;\n}\ntextarea {\n overflow: auto;\n}\noptgroup {\n font-weight: bold;\n}\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\ntd,\nth {\n padding: 0;\n}\n/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n@media print {\n *,\n *:before,\n *:after {\n color: #000 !important;\n text-shadow: none !important;\n background: transparent !important;\n box-shadow: none !important;\n }\n a,\n a:visited {\n text-decoration: underline;\n }\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n thead {\n display: table-header-group;\n }\n tr,\n img {\n page-break-inside: avoid;\n }\n img {\n max-width: 100% !important;\n }\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n h2,\n h3 {\n page-break-after: avoid;\n }\n .navbar {\n display: none;\n }\n .btn > .caret,\n .dropup > .btn > .caret {\n border-top-color: #000 !important;\n }\n .label {\n border: 1px solid #000;\n }\n .table {\n border-collapse: collapse !important;\n }\n .table td,\n .table th {\n background-color: #fff !important;\n }\n .table-bordered th,\n .table-bordered td {\n border: 1px solid #ddd !important;\n }\n}\n@font-face {\n font-family: \"Glyphicons Halflings\";\n src: url(\"../fonts/glyphicons-halflings-regular.eot\");\n src: url(\"../fonts/glyphicons-halflings-regular.eot?#iefix\") format(\"embedded-opentype\"), url(\"../fonts/glyphicons-halflings-regular.woff2\") format(\"woff2\"), url(\"../fonts/glyphicons-halflings-regular.woff\") format(\"woff\"), url(\"../fonts/glyphicons-halflings-regular.ttf\") format(\"truetype\"), url(\"../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular\") format(\"svg\");\n}\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: \"Glyphicons Halflings\";\n font-style: normal;\n font-weight: 400;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n.glyphicon-asterisk:before {\n content: \"\\002a\";\n}\n.glyphicon-plus:before {\n content: \"\\002b\";\n}\n.glyphicon-euro:before,\n.glyphicon-eur:before {\n content: \"\\20ac\";\n}\n.glyphicon-minus:before {\n content: \"\\2212\";\n}\n.glyphicon-cloud:before {\n content: \"\\2601\";\n}\n.glyphicon-envelope:before {\n content: \"\\2709\";\n}\n.glyphicon-pencil:before {\n content: \"\\270f\";\n}\n.glyphicon-glass:before {\n content: \"\\e001\";\n}\n.glyphicon-music:before {\n content: \"\\e002\";\n}\n.glyphicon-search:before {\n content: \"\\e003\";\n}\n.glyphicon-heart:before {\n content: \"\\e005\";\n}\n.glyphicon-star:before {\n content: \"\\e006\";\n}\n.glyphicon-star-empty:before {\n content: \"\\e007\";\n}\n.glyphicon-user:before {\n content: \"\\e008\";\n}\n.glyphicon-film:before {\n content: \"\\e009\";\n}\n.glyphicon-th-large:before {\n content: \"\\e010\";\n}\n.glyphicon-th:before {\n content: \"\\e011\";\n}\n.glyphicon-th-list:before {\n content: \"\\e012\";\n}\n.glyphicon-ok:before {\n content: \"\\e013\";\n}\n.glyphicon-remove:before {\n content: \"\\e014\";\n}\n.glyphicon-zoom-in:before {\n content: \"\\e015\";\n}\n.glyphicon-zoom-out:before {\n content: \"\\e016\";\n}\n.glyphicon-off:before {\n content: \"\\e017\";\n}\n.glyphicon-signal:before {\n content: \"\\e018\";\n}\n.glyphicon-cog:before {\n content: \"\\e019\";\n}\n.glyphicon-trash:before {\n content: \"\\e020\";\n}\n.glyphicon-home:before {\n content: \"\\e021\";\n}\n.glyphicon-file:before {\n content: \"\\e022\";\n}\n.glyphicon-time:before {\n content: \"\\e023\";\n}\n.glyphicon-road:before {\n content: \"\\e024\";\n}\n.glyphicon-download-alt:before {\n content: \"\\e025\";\n}\n.glyphicon-download:before {\n content: \"\\e026\";\n}\n.glyphicon-upload:before {\n content: \"\\e027\";\n}\n.glyphicon-inbox:before {\n content: \"\\e028\";\n}\n.glyphicon-play-circle:before {\n content: \"\\e029\";\n}\n.glyphicon-repeat:before {\n content: \"\\e030\";\n}\n.glyphicon-refresh:before {\n content: \"\\e031\";\n}\n.glyphicon-list-alt:before {\n content: \"\\e032\";\n}\n.glyphicon-lock:before {\n content: \"\\e033\";\n}\n.glyphicon-flag:before {\n content: \"\\e034\";\n}\n.glyphicon-headphones:before {\n content: \"\\e035\";\n}\n.glyphicon-volume-off:before {\n content: \"\\e036\";\n}\n.glyphicon-volume-down:before {\n content: \"\\e037\";\n}\n.glyphicon-volume-up:before {\n content: \"\\e038\";\n}\n.glyphicon-qrcode:before {\n content: \"\\e039\";\n}\n.glyphicon-barcode:before {\n content: \"\\e040\";\n}\n.glyphicon-tag:before {\n content: \"\\e041\";\n}\n.glyphicon-tags:before {\n content: \"\\e042\";\n}\n.glyphicon-book:before {\n content: \"\\e043\";\n}\n.glyphicon-bookmark:before {\n content: \"\\e044\";\n}\n.glyphicon-print:before {\n content: \"\\e045\";\n}\n.glyphicon-camera:before {\n content: \"\\e046\";\n}\n.glyphicon-font:before {\n content: \"\\e047\";\n}\n.glyphicon-bold:before {\n content: \"\\e048\";\n}\n.glyphicon-italic:before {\n content: \"\\e049\";\n}\n.glyphicon-text-height:before {\n content: \"\\e050\";\n}\n.glyphicon-text-width:before {\n content: \"\\e051\";\n}\n.glyphicon-align-left:before {\n content: \"\\e052\";\n}\n.glyphicon-align-center:before {\n content: \"\\e053\";\n}\n.glyphicon-align-right:before {\n content: \"\\e054\";\n}\n.glyphicon-align-justify:before {\n content: \"\\e055\";\n}\n.glyphicon-list:before {\n content: \"\\e056\";\n}\n.glyphicon-indent-left:before {\n content: \"\\e057\";\n}\n.glyphicon-indent-right:before {\n content: \"\\e058\";\n}\n.glyphicon-facetime-video:before {\n content: \"\\e059\";\n}\n.glyphicon-picture:before {\n content: \"\\e060\";\n}\n.glyphicon-map-marker:before {\n content: \"\\e062\";\n}\n.glyphicon-adjust:before {\n content: \"\\e063\";\n}\n.glyphicon-tint:before {\n content: \"\\e064\";\n}\n.glyphicon-edit:before {\n content: \"\\e065\";\n}\n.glyphicon-share:before {\n content: \"\\e066\";\n}\n.glyphicon-check:before {\n content: \"\\e067\";\n}\n.glyphicon-move:before {\n content: \"\\e068\";\n}\n.glyphicon-step-backward:before {\n content: \"\\e069\";\n}\n.glyphicon-fast-backward:before {\n content: \"\\e070\";\n}\n.glyphicon-backward:before {\n content: \"\\e071\";\n}\n.glyphicon-play:before {\n content: \"\\e072\";\n}\n.glyphicon-pause:before {\n content: \"\\e073\";\n}\n.glyphicon-stop:before {\n content: \"\\e074\";\n}\n.glyphicon-forward:before {\n content: \"\\e075\";\n}\n.glyphicon-fast-forward:before {\n content: \"\\e076\";\n}\n.glyphicon-step-forward:before {\n content: \"\\e077\";\n}\n.glyphicon-eject:before {\n content: \"\\e078\";\n}\n.glyphicon-chevron-left:before {\n content: \"\\e079\";\n}\n.glyphicon-chevron-right:before {\n content: \"\\e080\";\n}\n.glyphicon-plus-sign:before {\n content: \"\\e081\";\n}\n.glyphicon-minus-sign:before {\n content: \"\\e082\";\n}\n.glyphicon-remove-sign:before {\n content: \"\\e083\";\n}\n.glyphicon-ok-sign:before {\n content: \"\\e084\";\n}\n.glyphicon-question-sign:before {\n content: \"\\e085\";\n}\n.glyphicon-info-sign:before {\n content: \"\\e086\";\n}\n.glyphicon-screenshot:before {\n content: \"\\e087\";\n}\n.glyphicon-remove-circle:before {\n content: \"\\e088\";\n}\n.glyphicon-ok-circle:before {\n content: \"\\e089\";\n}\n.glyphicon-ban-circle:before {\n content: \"\\e090\";\n}\n.glyphicon-arrow-left:before {\n content: \"\\e091\";\n}\n.glyphicon-arrow-right:before {\n content: \"\\e092\";\n}\n.glyphicon-arrow-up:before {\n content: \"\\e093\";\n}\n.glyphicon-arrow-down:before {\n content: \"\\e094\";\n}\n.glyphicon-share-alt:before {\n content: \"\\e095\";\n}\n.glyphicon-resize-full:before {\n content: \"\\e096\";\n}\n.glyphicon-resize-small:before {\n content: \"\\e097\";\n}\n.glyphicon-exclamation-sign:before {\n content: \"\\e101\";\n}\n.glyphicon-gift:before {\n content: \"\\e102\";\n}\n.glyphicon-leaf:before {\n content: \"\\e103\";\n}\n.glyphicon-fire:before {\n content: \"\\e104\";\n}\n.glyphicon-eye-open:before {\n content: \"\\e105\";\n}\n.glyphicon-eye-close:before {\n content: \"\\e106\";\n}\n.glyphicon-warning-sign:before {\n content: \"\\e107\";\n}\n.glyphicon-plane:before {\n content: \"\\e108\";\n}\n.glyphicon-calendar:before {\n content: \"\\e109\";\n}\n.glyphicon-random:before {\n content: \"\\e110\";\n}\n.glyphicon-comment:before {\n content: \"\\e111\";\n}\n.glyphicon-magnet:before {\n content: \"\\e112\";\n}\n.glyphicon-chevron-up:before {\n content: \"\\e113\";\n}\n.glyphicon-chevron-down:before {\n content: \"\\e114\";\n}\n.glyphicon-retweet:before {\n content: \"\\e115\";\n}\n.glyphicon-shopping-cart:before {\n content: \"\\e116\";\n}\n.glyphicon-folder-close:before {\n content: \"\\e117\";\n}\n.glyphicon-folder-open:before {\n content: \"\\e118\";\n}\n.glyphicon-resize-vertical:before {\n content: \"\\e119\";\n}\n.glyphicon-resize-horizontal:before {\n content: \"\\e120\";\n}\n.glyphicon-hdd:before {\n content: \"\\e121\";\n}\n.glyphicon-bullhorn:before {\n content: \"\\e122\";\n}\n.glyphicon-bell:before {\n content: \"\\e123\";\n}\n.glyphicon-certificate:before {\n content: \"\\e124\";\n}\n.glyphicon-thumbs-up:before {\n content: \"\\e125\";\n}\n.glyphicon-thumbs-down:before {\n content: \"\\e126\";\n}\n.glyphicon-hand-right:before {\n content: \"\\e127\";\n}\n.glyphicon-hand-left:before {\n content: \"\\e128\";\n}\n.glyphicon-hand-up:before {\n content: \"\\e129\";\n}\n.glyphicon-hand-down:before {\n content: \"\\e130\";\n}\n.glyphicon-circle-arrow-right:before {\n content: \"\\e131\";\n}\n.glyphicon-circle-arrow-left:before {\n content: \"\\e132\";\n}\n.glyphicon-circle-arrow-up:before {\n content: \"\\e133\";\n}\n.glyphicon-circle-arrow-down:before {\n content: \"\\e134\";\n}\n.glyphicon-globe:before {\n content: \"\\e135\";\n}\n.glyphicon-wrench:before {\n content: \"\\e136\";\n}\n.glyphicon-tasks:before {\n content: \"\\e137\";\n}\n.glyphicon-filter:before {\n content: \"\\e138\";\n}\n.glyphicon-briefcase:before {\n content: \"\\e139\";\n}\n.glyphicon-fullscreen:before {\n content: \"\\e140\";\n}\n.glyphicon-dashboard:before {\n content: \"\\e141\";\n}\n.glyphicon-paperclip:before {\n content: \"\\e142\";\n}\n.glyphicon-heart-empty:before {\n content: \"\\e143\";\n}\n.glyphicon-link:before {\n content: \"\\e144\";\n}\n.glyphicon-phone:before {\n content: \"\\e145\";\n}\n.glyphicon-pushpin:before {\n content: \"\\e146\";\n}\n.glyphicon-usd:before {\n content: \"\\e148\";\n}\n.glyphicon-gbp:before {\n content: \"\\e149\";\n}\n.glyphicon-sort:before {\n content: \"\\e150\";\n}\n.glyphicon-sort-by-alphabet:before {\n content: \"\\e151\";\n}\n.glyphicon-sort-by-alphabet-alt:before {\n content: \"\\e152\";\n}\n.glyphicon-sort-by-order:before {\n content: \"\\e153\";\n}\n.glyphicon-sort-by-order-alt:before {\n content: \"\\e154\";\n}\n.glyphicon-sort-by-attributes:before {\n content: \"\\e155\";\n}\n.glyphicon-sort-by-attributes-alt:before {\n content: \"\\e156\";\n}\n.glyphicon-unchecked:before {\n content: \"\\e157\";\n}\n.glyphicon-expand:before {\n content: \"\\e158\";\n}\n.glyphicon-collapse-down:before {\n content: \"\\e159\";\n}\n.glyphicon-collapse-up:before {\n content: \"\\e160\";\n}\n.glyphicon-log-in:before {\n content: \"\\e161\";\n}\n.glyphicon-flash:before {\n content: \"\\e162\";\n}\n.glyphicon-log-out:before {\n content: \"\\e163\";\n}\n.glyphicon-new-window:before {\n content: \"\\e164\";\n}\n.glyphicon-record:before {\n content: \"\\e165\";\n}\n.glyphicon-save:before {\n content: \"\\e166\";\n}\n.glyphicon-open:before {\n content: \"\\e167\";\n}\n.glyphicon-saved:before {\n content: \"\\e168\";\n}\n.glyphicon-import:before {\n content: \"\\e169\";\n}\n.glyphicon-export:before {\n content: \"\\e170\";\n}\n.glyphicon-send:before {\n content: \"\\e171\";\n}\n.glyphicon-floppy-disk:before {\n content: \"\\e172\";\n}\n.glyphicon-floppy-saved:before {\n content: \"\\e173\";\n}\n.glyphicon-floppy-remove:before {\n content: \"\\e174\";\n}\n.glyphicon-floppy-save:before {\n content: \"\\e175\";\n}\n.glyphicon-floppy-open:before {\n content: \"\\e176\";\n}\n.glyphicon-credit-card:before {\n content: \"\\e177\";\n}\n.glyphicon-transfer:before {\n content: \"\\e178\";\n}\n.glyphicon-cutlery:before {\n content: \"\\e179\";\n}\n.glyphicon-header:before {\n content: \"\\e180\";\n}\n.glyphicon-compressed:before {\n content: \"\\e181\";\n}\n.glyphicon-earphone:before {\n content: \"\\e182\";\n}\n.glyphicon-phone-alt:before {\n content: \"\\e183\";\n}\n.glyphicon-tower:before {\n content: \"\\e184\";\n}\n.glyphicon-stats:before {\n content: \"\\e185\";\n}\n.glyphicon-sd-video:before {\n content: \"\\e186\";\n}\n.glyphicon-hd-video:before {\n content: \"\\e187\";\n}\n.glyphicon-subtitles:before {\n content: \"\\e188\";\n}\n.glyphicon-sound-stereo:before {\n content: \"\\e189\";\n}\n.glyphicon-sound-dolby:before {\n content: \"\\e190\";\n}\n.glyphicon-sound-5-1:before {\n content: \"\\e191\";\n}\n.glyphicon-sound-6-1:before {\n content: \"\\e192\";\n}\n.glyphicon-sound-7-1:before {\n content: \"\\e193\";\n}\n.glyphicon-copyright-mark:before {\n content: \"\\e194\";\n}\n.glyphicon-registration-mark:before {\n content: \"\\e195\";\n}\n.glyphicon-cloud-download:before {\n content: \"\\e197\";\n}\n.glyphicon-cloud-upload:before {\n content: \"\\e198\";\n}\n.glyphicon-tree-conifer:before {\n content: \"\\e199\";\n}\n.glyphicon-tree-deciduous:before {\n content: \"\\e200\";\n}\n.glyphicon-cd:before {\n content: \"\\e201\";\n}\n.glyphicon-save-file:before {\n content: \"\\e202\";\n}\n.glyphicon-open-file:before {\n content: \"\\e203\";\n}\n.glyphicon-level-up:before {\n content: \"\\e204\";\n}\n.glyphicon-copy:before {\n content: \"\\e205\";\n}\n.glyphicon-paste:before {\n content: \"\\e206\";\n}\n.glyphicon-alert:before {\n content: \"\\e209\";\n}\n.glyphicon-equalizer:before {\n content: \"\\e210\";\n}\n.glyphicon-king:before {\n content: \"\\e211\";\n}\n.glyphicon-queen:before {\n content: \"\\e212\";\n}\n.glyphicon-pawn:before {\n content: \"\\e213\";\n}\n.glyphicon-bishop:before {\n content: \"\\e214\";\n}\n.glyphicon-knight:before {\n content: \"\\e215\";\n}\n.glyphicon-baby-formula:before {\n content: \"\\e216\";\n}\n.glyphicon-tent:before {\n content: \"\\26fa\";\n}\n.glyphicon-blackboard:before {\n content: \"\\e218\";\n}\n.glyphicon-bed:before {\n content: \"\\e219\";\n}\n.glyphicon-apple:before {\n content: \"\\f8ff\";\n}\n.glyphicon-erase:before {\n content: \"\\e221\";\n}\n.glyphicon-hourglass:before {\n content: \"\\231b\";\n}\n.glyphicon-lamp:before {\n content: \"\\e223\";\n}\n.glyphicon-duplicate:before {\n content: \"\\e224\";\n}\n.glyphicon-piggy-bank:before {\n content: \"\\e225\";\n}\n.glyphicon-scissors:before {\n content: \"\\e226\";\n}\n.glyphicon-bitcoin:before {\n content: \"\\e227\";\n}\n.glyphicon-btc:before {\n content: \"\\e227\";\n}\n.glyphicon-xbt:before {\n content: \"\\e227\";\n}\n.glyphicon-yen:before {\n content: \"\\00a5\";\n}\n.glyphicon-jpy:before {\n content: \"\\00a5\";\n}\n.glyphicon-ruble:before {\n content: \"\\20bd\";\n}\n.glyphicon-rub:before {\n content: \"\\20bd\";\n}\n.glyphicon-scale:before {\n content: \"\\e230\";\n}\n.glyphicon-ice-lolly:before {\n content: \"\\e231\";\n}\n.glyphicon-ice-lolly-tasted:before {\n content: \"\\e232\";\n}\n.glyphicon-education:before {\n content: \"\\e233\";\n}\n.glyphicon-option-horizontal:before {\n content: \"\\e234\";\n}\n.glyphicon-option-vertical:before {\n content: \"\\e235\";\n}\n.glyphicon-menu-hamburger:before {\n content: \"\\e236\";\n}\n.glyphicon-modal-window:before {\n content: \"\\e237\";\n}\n.glyphicon-oil:before {\n content: \"\\e238\";\n}\n.glyphicon-grain:before {\n content: \"\\e239\";\n}\n.glyphicon-sunglasses:before {\n content: \"\\e240\";\n}\n.glyphicon-text-size:before {\n content: \"\\e241\";\n}\n.glyphicon-text-color:before {\n content: \"\\e242\";\n}\n.glyphicon-text-background:before {\n content: \"\\e243\";\n}\n.glyphicon-object-align-top:before {\n content: \"\\e244\";\n}\n.glyphicon-object-align-bottom:before {\n content: \"\\e245\";\n}\n.glyphicon-object-align-horizontal:before {\n content: \"\\e246\";\n}\n.glyphicon-object-align-left:before {\n content: \"\\e247\";\n}\n.glyphicon-object-align-vertical:before {\n content: \"\\e248\";\n}\n.glyphicon-object-align-right:before {\n content: \"\\e249\";\n}\n.glyphicon-triangle-right:before {\n content: \"\\e250\";\n}\n.glyphicon-triangle-left:before {\n content: \"\\e251\";\n}\n.glyphicon-triangle-bottom:before {\n content: \"\\e252\";\n}\n.glyphicon-triangle-top:before {\n content: \"\\e253\";\n}\n.glyphicon-console:before {\n content: \"\\e254\";\n}\n.glyphicon-superscript:before {\n content: \"\\e255\";\n}\n.glyphicon-subscript:before {\n content: \"\\e256\";\n}\n.glyphicon-menu-left:before {\n content: \"\\e257\";\n}\n.glyphicon-menu-right:before {\n content: \"\\e258\";\n}\n.glyphicon-menu-down:before {\n content: \"\\e259\";\n}\n.glyphicon-menu-up:before {\n content: \"\\e260\";\n}\n* {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n*:before,\n*:after {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 14px;\n line-height: 1.42857143;\n color: #333333;\n background-color: #fff;\n}\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\na {\n color: #337ab7;\n text-decoration: none;\n}\na:hover,\na:focus {\n color: #23527c;\n text-decoration: underline;\n}\na:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\nfigure {\n margin: 0;\n}\nimg {\n vertical-align: middle;\n}\n.img-responsive,\n.thumbnail > img,\n.thumbnail a > img,\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n display: block;\n max-width: 100%;\n height: auto;\n}\n.img-rounded {\n border-radius: 6px;\n}\n.img-thumbnail {\n padding: 4px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: all 0.2s ease-in-out;\n -o-transition: all 0.2s ease-in-out;\n transition: all 0.2s ease-in-out;\n display: inline-block;\n max-width: 100%;\n height: auto;\n}\n.img-circle {\n border-radius: 50%;\n}\nhr {\n margin-top: 20px;\n margin-bottom: 20px;\n border: 0;\n border-top: 1px solid #eeeeee;\n}\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n.sr-only-focusable:active,\n.sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n}\n[role=\"button\"] {\n cursor: pointer;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n font-family: inherit;\n font-weight: 500;\n line-height: 1.1;\n color: inherit;\n}\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small,\n.h1 small,\n.h2 small,\n.h3 small,\n.h4 small,\n.h5 small,\n.h6 small,\nh1 .small,\nh2 .small,\nh3 .small,\nh4 .small,\nh5 .small,\nh6 .small,\n.h1 .small,\n.h2 .small,\n.h3 .small,\n.h4 .small,\n.h5 .small,\n.h6 .small {\n font-weight: 400;\n line-height: 1;\n color: #777777;\n}\nh1,\n.h1,\nh2,\n.h2,\nh3,\n.h3 {\n margin-top: 20px;\n margin-bottom: 10px;\n}\nh1 small,\n.h1 small,\nh2 small,\n.h2 small,\nh3 small,\n.h3 small,\nh1 .small,\n.h1 .small,\nh2 .small,\n.h2 .small,\nh3 .small,\n.h3 .small {\n font-size: 65%;\n}\nh4,\n.h4,\nh5,\n.h5,\nh6,\n.h6 {\n margin-top: 10px;\n margin-bottom: 10px;\n}\nh4 small,\n.h4 small,\nh5 small,\n.h5 small,\nh6 small,\n.h6 small,\nh4 .small,\n.h4 .small,\nh5 .small,\n.h5 .small,\nh6 .small,\n.h6 .small {\n font-size: 75%;\n}\nh1,\n.h1 {\n font-size: 36px;\n}\nh2,\n.h2 {\n font-size: 30px;\n}\nh3,\n.h3 {\n font-size: 24px;\n}\nh4,\n.h4 {\n font-size: 18px;\n}\nh5,\n.h5 {\n font-size: 14px;\n}\nh6,\n.h6 {\n font-size: 12px;\n}\np {\n margin: 0 0 10px;\n}\n.lead {\n margin-bottom: 20px;\n font-size: 16px;\n font-weight: 300;\n line-height: 1.4;\n}\n@media (min-width: 768px) {\n .lead {\n font-size: 21px;\n }\n}\nsmall,\n.small {\n font-size: 85%;\n}\nmark,\n.mark {\n padding: 0.2em;\n background-color: #fcf8e3;\n}\n.text-left {\n text-align: left;\n}\n.text-right {\n text-align: right;\n}\n.text-center {\n text-align: center;\n}\n.text-justify {\n text-align: justify;\n}\n.text-nowrap {\n white-space: nowrap;\n}\n.text-lowercase {\n text-transform: lowercase;\n}\n.text-uppercase {\n text-transform: uppercase;\n}\n.text-capitalize {\n text-transform: capitalize;\n}\n.text-muted {\n color: #777777;\n}\n.text-primary {\n color: #337ab7;\n}\na.text-primary:hover,\na.text-primary:focus {\n color: #286090;\n}\n.text-success {\n color: #3c763d;\n}\na.text-success:hover,\na.text-success:focus {\n color: #2b542c;\n}\n.text-info {\n color: #31708f;\n}\na.text-info:hover,\na.text-info:focus {\n color: #245269;\n}\n.text-warning {\n color: #8a6d3b;\n}\na.text-warning:hover,\na.text-warning:focus {\n color: #66512c;\n}\n.text-danger {\n color: #a94442;\n}\na.text-danger:hover,\na.text-danger:focus {\n color: #843534;\n}\n.bg-primary {\n color: #fff;\n background-color: #337ab7;\n}\na.bg-primary:hover,\na.bg-primary:focus {\n background-color: #286090;\n}\n.bg-success {\n background-color: #dff0d8;\n}\na.bg-success:hover,\na.bg-success:focus {\n background-color: #c1e2b3;\n}\n.bg-info {\n background-color: #d9edf7;\n}\na.bg-info:hover,\na.bg-info:focus {\n background-color: #afd9ee;\n}\n.bg-warning {\n background-color: #fcf8e3;\n}\na.bg-warning:hover,\na.bg-warning:focus {\n background-color: #f7ecb5;\n}\n.bg-danger {\n background-color: #f2dede;\n}\na.bg-danger:hover,\na.bg-danger:focus {\n background-color: #e4b9b9;\n}\n.page-header {\n padding-bottom: 9px;\n margin: 40px 0 20px;\n border-bottom: 1px solid #eeeeee;\n}\nul,\nol {\n margin-top: 0;\n margin-bottom: 10px;\n}\nul ul,\nol ul,\nul ol,\nol ol {\n margin-bottom: 0;\n}\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n.list-inline {\n padding-left: 0;\n list-style: none;\n margin-left: -5px;\n}\n.list-inline > li {\n display: inline-block;\n padding-right: 5px;\n padding-left: 5px;\n}\ndl {\n margin-top: 0;\n margin-bottom: 20px;\n}\ndt,\ndd {\n line-height: 1.42857143;\n}\ndt {\n font-weight: 700;\n}\ndd {\n margin-left: 0;\n}\n@media (min-width: 768px) {\n .dl-horizontal dt {\n float: left;\n width: 160px;\n clear: left;\n text-align: right;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .dl-horizontal dd {\n margin-left: 180px;\n }\n}\nabbr[title],\nabbr[data-original-title] {\n cursor: help;\n}\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\nblockquote {\n padding: 10px 20px;\n margin: 0 0 20px;\n font-size: 17.5px;\n border-left: 5px solid #eeeeee;\n}\nblockquote p:last-child,\nblockquote ul:last-child,\nblockquote ol:last-child {\n margin-bottom: 0;\n}\nblockquote footer,\nblockquote small,\nblockquote .small {\n display: block;\n font-size: 80%;\n line-height: 1.42857143;\n color: #777777;\n}\nblockquote footer:before,\nblockquote small:before,\nblockquote .small:before {\n content: \"\\2014 \\00A0\";\n}\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n text-align: right;\n border-right: 5px solid #eeeeee;\n border-left: 0;\n}\n.blockquote-reverse footer:before,\nblockquote.pull-right footer:before,\n.blockquote-reverse small:before,\nblockquote.pull-right small:before,\n.blockquote-reverse .small:before,\nblockquote.pull-right .small:before {\n content: \"\";\n}\n.blockquote-reverse footer:after,\nblockquote.pull-right footer:after,\n.blockquote-reverse small:after,\nblockquote.pull-right small:after,\n.blockquote-reverse .small:after,\nblockquote.pull-right .small:after {\n content: \"\\00A0 \\2014\";\n}\naddress {\n margin-bottom: 20px;\n font-style: normal;\n line-height: 1.42857143;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: #c7254e;\n background-color: #f9f2f4;\n border-radius: 4px;\n}\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: #fff;\n background-color: #333;\n border-radius: 3px;\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\nkbd kbd {\n padding: 0;\n font-size: 100%;\n font-weight: 700;\n box-shadow: none;\n}\npre {\n display: block;\n padding: 9.5px;\n margin: 0 0 10px;\n font-size: 13px;\n line-height: 1.42857143;\n color: #333333;\n word-break: break-all;\n word-wrap: break-word;\n background-color: #f5f5f5;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\npre code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n}\n.pre-scrollable {\n max-height: 340px;\n overflow-y: scroll;\n}\n.container {\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n@media (min-width: 768px) {\n .container {\n width: 750px;\n }\n}\n@media (min-width: 992px) {\n .container {\n width: 970px;\n }\n}\n@media (min-width: 1200px) {\n .container {\n width: 1170px;\n }\n}\n.container-fluid {\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n.row {\n margin-right: -15px;\n margin-left: -15px;\n}\n.row-no-gutters {\n margin-right: 0;\n margin-left: 0;\n}\n.row-no-gutters [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n}\n.col-xs-1,\n.col-sm-1,\n.col-md-1,\n.col-lg-1,\n.col-xs-2,\n.col-sm-2,\n.col-md-2,\n.col-lg-2,\n.col-xs-3,\n.col-sm-3,\n.col-md-3,\n.col-lg-3,\n.col-xs-4,\n.col-sm-4,\n.col-md-4,\n.col-lg-4,\n.col-xs-5,\n.col-sm-5,\n.col-md-5,\n.col-lg-5,\n.col-xs-6,\n.col-sm-6,\n.col-md-6,\n.col-lg-6,\n.col-xs-7,\n.col-sm-7,\n.col-md-7,\n.col-lg-7,\n.col-xs-8,\n.col-sm-8,\n.col-md-8,\n.col-lg-8,\n.col-xs-9,\n.col-sm-9,\n.col-md-9,\n.col-lg-9,\n.col-xs-10,\n.col-sm-10,\n.col-md-10,\n.col-lg-10,\n.col-xs-11,\n.col-sm-11,\n.col-md-11,\n.col-lg-11,\n.col-xs-12,\n.col-sm-12,\n.col-md-12,\n.col-lg-12 {\n position: relative;\n min-height: 1px;\n padding-right: 15px;\n padding-left: 15px;\n}\n.col-xs-1,\n.col-xs-2,\n.col-xs-3,\n.col-xs-4,\n.col-xs-5,\n.col-xs-6,\n.col-xs-7,\n.col-xs-8,\n.col-xs-9,\n.col-xs-10,\n.col-xs-11,\n.col-xs-12 {\n float: left;\n}\n.col-xs-12 {\n width: 100%;\n}\n.col-xs-11 {\n width: 91.66666667%;\n}\n.col-xs-10 {\n width: 83.33333333%;\n}\n.col-xs-9 {\n width: 75%;\n}\n.col-xs-8 {\n width: 66.66666667%;\n}\n.col-xs-7 {\n width: 58.33333333%;\n}\n.col-xs-6 {\n width: 50%;\n}\n.col-xs-5 {\n width: 41.66666667%;\n}\n.col-xs-4 {\n width: 33.33333333%;\n}\n.col-xs-3 {\n width: 25%;\n}\n.col-xs-2 {\n width: 16.66666667%;\n}\n.col-xs-1 {\n width: 8.33333333%;\n}\n.col-xs-pull-12 {\n right: 100%;\n}\n.col-xs-pull-11 {\n right: 91.66666667%;\n}\n.col-xs-pull-10 {\n right: 83.33333333%;\n}\n.col-xs-pull-9 {\n right: 75%;\n}\n.col-xs-pull-8 {\n right: 66.66666667%;\n}\n.col-xs-pull-7 {\n right: 58.33333333%;\n}\n.col-xs-pull-6 {\n right: 50%;\n}\n.col-xs-pull-5 {\n right: 41.66666667%;\n}\n.col-xs-pull-4 {\n right: 33.33333333%;\n}\n.col-xs-pull-3 {\n right: 25%;\n}\n.col-xs-pull-2 {\n right: 16.66666667%;\n}\n.col-xs-pull-1 {\n right: 8.33333333%;\n}\n.col-xs-pull-0 {\n right: auto;\n}\n.col-xs-push-12 {\n left: 100%;\n}\n.col-xs-push-11 {\n left: 91.66666667%;\n}\n.col-xs-push-10 {\n left: 83.33333333%;\n}\n.col-xs-push-9 {\n left: 75%;\n}\n.col-xs-push-8 {\n left: 66.66666667%;\n}\n.col-xs-push-7 {\n left: 58.33333333%;\n}\n.col-xs-push-6 {\n left: 50%;\n}\n.col-xs-push-5 {\n left: 41.66666667%;\n}\n.col-xs-push-4 {\n left: 33.33333333%;\n}\n.col-xs-push-3 {\n left: 25%;\n}\n.col-xs-push-2 {\n left: 16.66666667%;\n}\n.col-xs-push-1 {\n left: 8.33333333%;\n}\n.col-xs-push-0 {\n left: auto;\n}\n.col-xs-offset-12 {\n margin-left: 100%;\n}\n.col-xs-offset-11 {\n margin-left: 91.66666667%;\n}\n.col-xs-offset-10 {\n margin-left: 83.33333333%;\n}\n.col-xs-offset-9 {\n margin-left: 75%;\n}\n.col-xs-offset-8 {\n margin-left: 66.66666667%;\n}\n.col-xs-offset-7 {\n margin-left: 58.33333333%;\n}\n.col-xs-offset-6 {\n margin-left: 50%;\n}\n.col-xs-offset-5 {\n margin-left: 41.66666667%;\n}\n.col-xs-offset-4 {\n margin-left: 33.33333333%;\n}\n.col-xs-offset-3 {\n margin-left: 25%;\n}\n.col-xs-offset-2 {\n margin-left: 16.66666667%;\n}\n.col-xs-offset-1 {\n margin-left: 8.33333333%;\n}\n.col-xs-offset-0 {\n margin-left: 0%;\n}\n@media (min-width: 768px) {\n .col-sm-1,\n .col-sm-2,\n .col-sm-3,\n .col-sm-4,\n .col-sm-5,\n .col-sm-6,\n .col-sm-7,\n .col-sm-8,\n .col-sm-9,\n .col-sm-10,\n .col-sm-11,\n .col-sm-12 {\n float: left;\n }\n .col-sm-12 {\n width: 100%;\n }\n .col-sm-11 {\n width: 91.66666667%;\n }\n .col-sm-10 {\n width: 83.33333333%;\n }\n .col-sm-9 {\n width: 75%;\n }\n .col-sm-8 {\n width: 66.66666667%;\n }\n .col-sm-7 {\n width: 58.33333333%;\n }\n .col-sm-6 {\n width: 50%;\n }\n .col-sm-5 {\n width: 41.66666667%;\n }\n .col-sm-4 {\n width: 33.33333333%;\n }\n .col-sm-3 {\n width: 25%;\n }\n .col-sm-2 {\n width: 16.66666667%;\n }\n .col-sm-1 {\n width: 8.33333333%;\n }\n .col-sm-pull-12 {\n right: 100%;\n }\n .col-sm-pull-11 {\n right: 91.66666667%;\n }\n .col-sm-pull-10 {\n right: 83.33333333%;\n }\n .col-sm-pull-9 {\n right: 75%;\n }\n .col-sm-pull-8 {\n right: 66.66666667%;\n }\n .col-sm-pull-7 {\n right: 58.33333333%;\n }\n .col-sm-pull-6 {\n right: 50%;\n }\n .col-sm-pull-5 {\n right: 41.66666667%;\n }\n .col-sm-pull-4 {\n right: 33.33333333%;\n }\n .col-sm-pull-3 {\n right: 25%;\n }\n .col-sm-pull-2 {\n right: 16.66666667%;\n }\n .col-sm-pull-1 {\n right: 8.33333333%;\n }\n .col-sm-pull-0 {\n right: auto;\n }\n .col-sm-push-12 {\n left: 100%;\n }\n .col-sm-push-11 {\n left: 91.66666667%;\n }\n .col-sm-push-10 {\n left: 83.33333333%;\n }\n .col-sm-push-9 {\n left: 75%;\n }\n .col-sm-push-8 {\n left: 66.66666667%;\n }\n .col-sm-push-7 {\n left: 58.33333333%;\n }\n .col-sm-push-6 {\n left: 50%;\n }\n .col-sm-push-5 {\n left: 41.66666667%;\n }\n .col-sm-push-4 {\n left: 33.33333333%;\n }\n .col-sm-push-3 {\n left: 25%;\n }\n .col-sm-push-2 {\n left: 16.66666667%;\n }\n .col-sm-push-1 {\n left: 8.33333333%;\n }\n .col-sm-push-0 {\n left: auto;\n }\n .col-sm-offset-12 {\n margin-left: 100%;\n }\n .col-sm-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-sm-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-sm-offset-9 {\n margin-left: 75%;\n }\n .col-sm-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-sm-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-sm-offset-6 {\n margin-left: 50%;\n }\n .col-sm-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-sm-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-sm-offset-3 {\n margin-left: 25%;\n }\n .col-sm-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-sm-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-sm-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 992px) {\n .col-md-1,\n .col-md-2,\n .col-md-3,\n .col-md-4,\n .col-md-5,\n .col-md-6,\n .col-md-7,\n .col-md-8,\n .col-md-9,\n .col-md-10,\n .col-md-11,\n .col-md-12 {\n float: left;\n }\n .col-md-12 {\n width: 100%;\n }\n .col-md-11 {\n width: 91.66666667%;\n }\n .col-md-10 {\n width: 83.33333333%;\n }\n .col-md-9 {\n width: 75%;\n }\n .col-md-8 {\n width: 66.66666667%;\n }\n .col-md-7 {\n width: 58.33333333%;\n }\n .col-md-6 {\n width: 50%;\n }\n .col-md-5 {\n width: 41.66666667%;\n }\n .col-md-4 {\n width: 33.33333333%;\n }\n .col-md-3 {\n width: 25%;\n }\n .col-md-2 {\n width: 16.66666667%;\n }\n .col-md-1 {\n width: 8.33333333%;\n }\n .col-md-pull-12 {\n right: 100%;\n }\n .col-md-pull-11 {\n right: 91.66666667%;\n }\n .col-md-pull-10 {\n right: 83.33333333%;\n }\n .col-md-pull-9 {\n right: 75%;\n }\n .col-md-pull-8 {\n right: 66.66666667%;\n }\n .col-md-pull-7 {\n right: 58.33333333%;\n }\n .col-md-pull-6 {\n right: 50%;\n }\n .col-md-pull-5 {\n right: 41.66666667%;\n }\n .col-md-pull-4 {\n right: 33.33333333%;\n }\n .col-md-pull-3 {\n right: 25%;\n }\n .col-md-pull-2 {\n right: 16.66666667%;\n }\n .col-md-pull-1 {\n right: 8.33333333%;\n }\n .col-md-pull-0 {\n right: auto;\n }\n .col-md-push-12 {\n left: 100%;\n }\n .col-md-push-11 {\n left: 91.66666667%;\n }\n .col-md-push-10 {\n left: 83.33333333%;\n }\n .col-md-push-9 {\n left: 75%;\n }\n .col-md-push-8 {\n left: 66.66666667%;\n }\n .col-md-push-7 {\n left: 58.33333333%;\n }\n .col-md-push-6 {\n left: 50%;\n }\n .col-md-push-5 {\n left: 41.66666667%;\n }\n .col-md-push-4 {\n left: 33.33333333%;\n }\n .col-md-push-3 {\n left: 25%;\n }\n .col-md-push-2 {\n left: 16.66666667%;\n }\n .col-md-push-1 {\n left: 8.33333333%;\n }\n .col-md-push-0 {\n left: auto;\n }\n .col-md-offset-12 {\n margin-left: 100%;\n }\n .col-md-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-md-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-md-offset-9 {\n margin-left: 75%;\n }\n .col-md-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-md-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-md-offset-6 {\n margin-left: 50%;\n }\n .col-md-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-md-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-md-offset-3 {\n margin-left: 25%;\n }\n .col-md-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-md-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-md-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 1200px) {\n .col-lg-1,\n .col-lg-2,\n .col-lg-3,\n .col-lg-4,\n .col-lg-5,\n .col-lg-6,\n .col-lg-7,\n .col-lg-8,\n .col-lg-9,\n .col-lg-10,\n .col-lg-11,\n .col-lg-12 {\n float: left;\n }\n .col-lg-12 {\n width: 100%;\n }\n .col-lg-11 {\n width: 91.66666667%;\n }\n .col-lg-10 {\n width: 83.33333333%;\n }\n .col-lg-9 {\n width: 75%;\n }\n .col-lg-8 {\n width: 66.66666667%;\n }\n .col-lg-7 {\n width: 58.33333333%;\n }\n .col-lg-6 {\n width: 50%;\n }\n .col-lg-5 {\n width: 41.66666667%;\n }\n .col-lg-4 {\n width: 33.33333333%;\n }\n .col-lg-3 {\n width: 25%;\n }\n .col-lg-2 {\n width: 16.66666667%;\n }\n .col-lg-1 {\n width: 8.33333333%;\n }\n .col-lg-pull-12 {\n right: 100%;\n }\n .col-lg-pull-11 {\n right: 91.66666667%;\n }\n .col-lg-pull-10 {\n right: 83.33333333%;\n }\n .col-lg-pull-9 {\n right: 75%;\n }\n .col-lg-pull-8 {\n right: 66.66666667%;\n }\n .col-lg-pull-7 {\n right: 58.33333333%;\n }\n .col-lg-pull-6 {\n right: 50%;\n }\n .col-lg-pull-5 {\n right: 41.66666667%;\n }\n .col-lg-pull-4 {\n right: 33.33333333%;\n }\n .col-lg-pull-3 {\n right: 25%;\n }\n .col-lg-pull-2 {\n right: 16.66666667%;\n }\n .col-lg-pull-1 {\n right: 8.33333333%;\n }\n .col-lg-pull-0 {\n right: auto;\n }\n .col-lg-push-12 {\n left: 100%;\n }\n .col-lg-push-11 {\n left: 91.66666667%;\n }\n .col-lg-push-10 {\n left: 83.33333333%;\n }\n .col-lg-push-9 {\n left: 75%;\n }\n .col-lg-push-8 {\n left: 66.66666667%;\n }\n .col-lg-push-7 {\n left: 58.33333333%;\n }\n .col-lg-push-6 {\n left: 50%;\n }\n .col-lg-push-5 {\n left: 41.66666667%;\n }\n .col-lg-push-4 {\n left: 33.33333333%;\n }\n .col-lg-push-3 {\n left: 25%;\n }\n .col-lg-push-2 {\n left: 16.66666667%;\n }\n .col-lg-push-1 {\n left: 8.33333333%;\n }\n .col-lg-push-0 {\n left: auto;\n }\n .col-lg-offset-12 {\n margin-left: 100%;\n }\n .col-lg-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-lg-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-lg-offset-9 {\n margin-left: 75%;\n }\n .col-lg-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-lg-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-lg-offset-6 {\n margin-left: 50%;\n }\n .col-lg-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-lg-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-lg-offset-3 {\n margin-left: 25%;\n }\n .col-lg-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-lg-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-lg-offset-0 {\n margin-left: 0%;\n }\n}\ntable {\n background-color: transparent;\n}\ntable col[class*=\"col-\"] {\n position: static;\n display: table-column;\n float: none;\n}\ntable td[class*=\"col-\"],\ntable th[class*=\"col-\"] {\n position: static;\n display: table-cell;\n float: none;\n}\ncaption {\n padding-top: 8px;\n padding-bottom: 8px;\n color: #777777;\n text-align: left;\n}\nth {\n text-align: left;\n}\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: 20px;\n}\n.table > thead > tr > th,\n.table > tbody > tr > th,\n.table > tfoot > tr > th,\n.table > thead > tr > td,\n.table > tbody > tr > td,\n.table > tfoot > tr > td {\n padding: 8px;\n line-height: 1.42857143;\n vertical-align: top;\n border-top: 1px solid #ddd;\n}\n.table > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid #ddd;\n}\n.table > caption + thead > tr:first-child > th,\n.table > colgroup + thead > tr:first-child > th,\n.table > thead:first-child > tr:first-child > th,\n.table > caption + thead > tr:first-child > td,\n.table > colgroup + thead > tr:first-child > td,\n.table > thead:first-child > tr:first-child > td {\n border-top: 0;\n}\n.table > tbody + tbody {\n border-top: 2px solid #ddd;\n}\n.table .table {\n background-color: #fff;\n}\n.table-condensed > thead > tr > th,\n.table-condensed > tbody > tr > th,\n.table-condensed > tfoot > tr > th,\n.table-condensed > thead > tr > td,\n.table-condensed > tbody > tr > td,\n.table-condensed > tfoot > tr > td {\n padding: 5px;\n}\n.table-bordered {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > tbody > tr > th,\n.table-bordered > tfoot > tr > th,\n.table-bordered > thead > tr > td,\n.table-bordered > tbody > tr > td,\n.table-bordered > tfoot > tr > td {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td {\n border-bottom-width: 2px;\n}\n.table-striped > tbody > tr:nth-of-type(odd) {\n background-color: #f9f9f9;\n}\n.table-hover > tbody > tr:hover {\n background-color: #f5f5f5;\n}\n.table > thead > tr > td.active,\n.table > tbody > tr > td.active,\n.table > tfoot > tr > td.active,\n.table > thead > tr > th.active,\n.table > tbody > tr > th.active,\n.table > tfoot > tr > th.active,\n.table > thead > tr.active > td,\n.table > tbody > tr.active > td,\n.table > tfoot > tr.active > td,\n.table > thead > tr.active > th,\n.table > tbody > tr.active > th,\n.table > tfoot > tr.active > th {\n background-color: #f5f5f5;\n}\n.table-hover > tbody > tr > td.active:hover,\n.table-hover > tbody > tr > th.active:hover,\n.table-hover > tbody > tr.active:hover > td,\n.table-hover > tbody > tr:hover > .active,\n.table-hover > tbody > tr.active:hover > th {\n background-color: #e8e8e8;\n}\n.table > thead > tr > td.success,\n.table > tbody > tr > td.success,\n.table > tfoot > tr > td.success,\n.table > thead > tr > th.success,\n.table > tbody > tr > th.success,\n.table > tfoot > tr > th.success,\n.table > thead > tr.success > td,\n.table > tbody > tr.success > td,\n.table > tfoot > tr.success > td,\n.table > thead > tr.success > th,\n.table > tbody > tr.success > th,\n.table > tfoot > tr.success > th {\n background-color: #dff0d8;\n}\n.table-hover > tbody > tr > td.success:hover,\n.table-hover > tbody > tr > th.success:hover,\n.table-hover > tbody > tr.success:hover > td,\n.table-hover > tbody > tr:hover > .success,\n.table-hover > tbody > tr.success:hover > th {\n background-color: #d0e9c6;\n}\n.table > thead > tr > td.info,\n.table > tbody > tr > td.info,\n.table > tfoot > tr > td.info,\n.table > thead > tr > th.info,\n.table > tbody > tr > th.info,\n.table > tfoot > tr > th.info,\n.table > thead > tr.info > td,\n.table > tbody > tr.info > td,\n.table > tfoot > tr.info > td,\n.table > thead > tr.info > th,\n.table > tbody > tr.info > th,\n.table > tfoot > tr.info > th {\n background-color: #d9edf7;\n}\n.table-hover > tbody > tr > td.info:hover,\n.table-hover > tbody > tr > th.info:hover,\n.table-hover > tbody > tr.info:hover > td,\n.table-hover > tbody > tr:hover > .info,\n.table-hover > tbody > tr.info:hover > th {\n background-color: #c4e3f3;\n}\n.table > thead > tr > td.warning,\n.table > tbody > tr > td.warning,\n.table > tfoot > tr > td.warning,\n.table > thead > tr > th.warning,\n.table > tbody > tr > th.warning,\n.table > tfoot > tr > th.warning,\n.table > thead > tr.warning > td,\n.table > tbody > tr.warning > td,\n.table > tfoot > tr.warning > td,\n.table > thead > tr.warning > th,\n.table > tbody > tr.warning > th,\n.table > tfoot > tr.warning > th {\n background-color: #fcf8e3;\n}\n.table-hover > tbody > tr > td.warning:hover,\n.table-hover > tbody > tr > th.warning:hover,\n.table-hover > tbody > tr.warning:hover > td,\n.table-hover > tbody > tr:hover > .warning,\n.table-hover > tbody > tr.warning:hover > th {\n background-color: #faf2cc;\n}\n.table > thead > tr > td.danger,\n.table > tbody > tr > td.danger,\n.table > tfoot > tr > td.danger,\n.table > thead > tr > th.danger,\n.table > tbody > tr > th.danger,\n.table > tfoot > tr > th.danger,\n.table > thead > tr.danger > td,\n.table > tbody > tr.danger > td,\n.table > tfoot > tr.danger > td,\n.table > thead > tr.danger > th,\n.table > tbody > tr.danger > th,\n.table > tfoot > tr.danger > th {\n background-color: #f2dede;\n}\n.table-hover > tbody > tr > td.danger:hover,\n.table-hover > tbody > tr > th.danger:hover,\n.table-hover > tbody > tr.danger:hover > td,\n.table-hover > tbody > tr:hover > .danger,\n.table-hover > tbody > tr.danger:hover > th {\n background-color: #ebcccc;\n}\n.table-responsive {\n min-height: 0.01%;\n overflow-x: auto;\n}\n@media screen and (max-width: 767px) {\n .table-responsive {\n width: 100%;\n margin-bottom: 15px;\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid #ddd;\n }\n .table-responsive > .table {\n margin-bottom: 0;\n }\n .table-responsive > .table > thead > tr > th,\n .table-responsive > .table > tbody > tr > th,\n .table-responsive > .table > tfoot > tr > th,\n .table-responsive > .table > thead > tr > td,\n .table-responsive > .table > tbody > tr > td,\n .table-responsive > .table > tfoot > tr > td {\n white-space: nowrap;\n }\n .table-responsive > .table-bordered {\n border: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:first-child,\n .table-responsive > .table-bordered > tbody > tr > th:first-child,\n .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n .table-responsive > .table-bordered > thead > tr > td:first-child,\n .table-responsive > .table-bordered > tbody > tr > td:first-child,\n .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:last-child,\n .table-responsive > .table-bordered > tbody > tr > th:last-child,\n .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n .table-responsive > .table-bordered > thead > tr > td:last-child,\n .table-responsive > .table-bordered > tbody > tr > td:last-child,\n .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n }\n .table-responsive > .table-bordered > tbody > tr:last-child > th,\n .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n .table-responsive > .table-bordered > tbody > tr:last-child > td,\n .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n border-bottom: 0;\n }\n}\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: 20px;\n font-size: 21px;\n line-height: inherit;\n color: #333333;\n border: 0;\n border-bottom: 1px solid #e5e5e5;\n}\nlabel {\n display: inline-block;\n max-width: 100%;\n margin-bottom: 5px;\n font-weight: 700;\n}\ninput[type=\"search\"] {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n -webkit-appearance: none;\n appearance: none;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9;\n line-height: normal;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"].disabled,\ninput[type=\"checkbox\"].disabled,\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"] {\n cursor: not-allowed;\n}\ninput[type=\"file\"] {\n display: block;\n}\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\nselect[multiple],\nselect[size] {\n height: auto;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\noutput {\n display: block;\n padding-top: 7px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n}\n.form-control {\n display: block;\n width: 100%;\n height: 34px;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n background-color: #fff;\n background-image: none;\n border: 1px solid #ccc;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n}\n.form-control:focus {\n border-color: #66afe9;\n outline: 0;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.6);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.6);\n}\n.form-control::-moz-placeholder {\n color: #999;\n opacity: 1;\n}\n.form-control:-ms-input-placeholder {\n color: #999;\n}\n.form-control::-webkit-input-placeholder {\n color: #999;\n}\n.form-control::-ms-expand {\n background-color: transparent;\n border: 0;\n}\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n background-color: #eeeeee;\n opacity: 1;\n}\n.form-control[disabled],\nfieldset[disabled] .form-control {\n cursor: not-allowed;\n}\ntextarea.form-control {\n height: auto;\n}\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n input[type=\"date\"].form-control,\n input[type=\"time\"].form-control,\n input[type=\"datetime-local\"].form-control,\n input[type=\"month\"].form-control {\n line-height: 34px;\n }\n input[type=\"date\"].input-sm,\n input[type=\"time\"].input-sm,\n input[type=\"datetime-local\"].input-sm,\n input[type=\"month\"].input-sm,\n .input-group-sm input[type=\"date\"],\n .input-group-sm input[type=\"time\"],\n .input-group-sm input[type=\"datetime-local\"],\n .input-group-sm input[type=\"month\"] {\n line-height: 30px;\n }\n input[type=\"date\"].input-lg,\n input[type=\"time\"].input-lg,\n input[type=\"datetime-local\"].input-lg,\n input[type=\"month\"].input-lg,\n .input-group-lg input[type=\"date\"],\n .input-group-lg input[type=\"time\"],\n .input-group-lg input[type=\"datetime-local\"],\n .input-group-lg input[type=\"month\"] {\n line-height: 46px;\n }\n}\n.form-group {\n margin-bottom: 15px;\n}\n.radio,\n.checkbox {\n position: relative;\n display: block;\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.radio.disabled label,\n.checkbox.disabled label,\nfieldset[disabled] .radio label,\nfieldset[disabled] .checkbox label {\n cursor: not-allowed;\n}\n.radio label,\n.checkbox label {\n min-height: 20px;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: 400;\n cursor: pointer;\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-top: 4px \\9;\n margin-left: -20px;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px;\n}\n.radio-inline,\n.checkbox-inline {\n position: relative;\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: 400;\n vertical-align: middle;\n cursor: pointer;\n}\n.radio-inline.disabled,\n.checkbox-inline.disabled,\nfieldset[disabled] .radio-inline,\nfieldset[disabled] .checkbox-inline {\n cursor: not-allowed;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px;\n}\n.form-control-static {\n min-height: 34px;\n padding-top: 7px;\n padding-bottom: 7px;\n margin-bottom: 0;\n}\n.form-control-static.input-lg,\n.form-control-static.input-sm {\n padding-right: 0;\n padding-left: 0;\n}\n.input-sm {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-sm {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-sm,\nselect[multiple].input-sm {\n height: auto;\n}\n.form-group-sm .form-control {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.form-group-sm select.form-control {\n height: 30px;\n line-height: 30px;\n}\n.form-group-sm textarea.form-control,\n.form-group-sm select[multiple].form-control {\n height: auto;\n}\n.form-group-sm .form-control-static {\n height: 30px;\n min-height: 32px;\n padding: 6px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.input-lg {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-lg {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-lg,\nselect[multiple].input-lg {\n height: auto;\n}\n.form-group-lg .form-control {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.form-group-lg select.form-control {\n height: 46px;\n line-height: 46px;\n}\n.form-group-lg textarea.form-control,\n.form-group-lg select[multiple].form-control {\n height: auto;\n}\n.form-group-lg .form-control-static {\n height: 46px;\n min-height: 38px;\n padding: 11px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.has-feedback {\n position: relative;\n}\n.has-feedback .form-control {\n padding-right: 42.5px;\n}\n.form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2;\n display: block;\n width: 34px;\n height: 34px;\n line-height: 34px;\n text-align: center;\n pointer-events: none;\n}\n.input-lg + .form-control-feedback,\n.input-group-lg + .form-control-feedback,\n.form-group-lg .form-control + .form-control-feedback {\n width: 46px;\n height: 46px;\n line-height: 46px;\n}\n.input-sm + .form-control-feedback,\n.input-group-sm + .form-control-feedback,\n.form-group-sm .form-control + .form-control-feedback {\n width: 30px;\n height: 30px;\n line-height: 30px;\n}\n.has-success .help-block,\n.has-success .control-label,\n.has-success .radio,\n.has-success .checkbox,\n.has-success .radio-inline,\n.has-success .checkbox-inline,\n.has-success.radio label,\n.has-success.checkbox label,\n.has-success.radio-inline label,\n.has-success.checkbox-inline label {\n color: #3c763d;\n}\n.has-success .form-control {\n border-color: #3c763d;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-success .form-control:focus {\n border-color: #2b542c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n}\n.has-success .input-group-addon {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #3c763d;\n}\n.has-success .form-control-feedback {\n color: #3c763d;\n}\n.has-warning .help-block,\n.has-warning .control-label,\n.has-warning .radio,\n.has-warning .checkbox,\n.has-warning .radio-inline,\n.has-warning .checkbox-inline,\n.has-warning.radio label,\n.has-warning.checkbox label,\n.has-warning.radio-inline label,\n.has-warning.checkbox-inline label {\n color: #8a6d3b;\n}\n.has-warning .form-control {\n border-color: #8a6d3b;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-warning .form-control:focus {\n border-color: #66512c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n}\n.has-warning .input-group-addon {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #8a6d3b;\n}\n.has-warning .form-control-feedback {\n color: #8a6d3b;\n}\n.has-error .help-block,\n.has-error .control-label,\n.has-error .radio,\n.has-error .checkbox,\n.has-error .radio-inline,\n.has-error .checkbox-inline,\n.has-error.radio label,\n.has-error.checkbox label,\n.has-error.radio-inline label,\n.has-error.checkbox-inline label {\n color: #a94442;\n}\n.has-error .form-control {\n border-color: #a94442;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-error .form-control:focus {\n border-color: #843534;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n}\n.has-error .input-group-addon {\n color: #a94442;\n background-color: #f2dede;\n border-color: #a94442;\n}\n.has-error .form-control-feedback {\n color: #a94442;\n}\n.has-feedback label ~ .form-control-feedback {\n top: 25px;\n}\n.has-feedback label.sr-only ~ .form-control-feedback {\n top: 0;\n}\n.help-block {\n display: block;\n margin-top: 5px;\n margin-bottom: 10px;\n color: #737373;\n}\n@media (min-width: 768px) {\n .form-inline .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .form-inline .form-control-static {\n display: inline-block;\n }\n .form-inline .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .form-inline .input-group .input-group-addon,\n .form-inline .input-group .input-group-btn,\n .form-inline .input-group .form-control {\n width: auto;\n }\n .form-inline .input-group > .form-control {\n width: 100%;\n }\n .form-inline .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio,\n .form-inline .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio label,\n .form-inline .checkbox label {\n padding-left: 0;\n }\n .form-inline .radio input[type=\"radio\"],\n .form-inline .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .form-inline .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n padding-top: 7px;\n margin-top: 0;\n margin-bottom: 0;\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox {\n min-height: 27px;\n}\n.form-horizontal .form-group {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .control-label {\n padding-top: 7px;\n margin-bottom: 0;\n text-align: right;\n }\n}\n.form-horizontal .has-feedback .form-control-feedback {\n right: 15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-lg .control-label {\n padding-top: 11px;\n font-size: 18px;\n }\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-sm .control-label {\n padding-top: 6px;\n font-size: 12px;\n }\n}\n.btn {\n display: inline-block;\n margin-bottom: 0;\n font-weight: normal;\n text-align: center;\n white-space: nowrap;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none;\n border: 1px solid transparent;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n border-radius: 4px;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n}\n.btn:focus,\n.btn:active:focus,\n.btn.active:focus,\n.btn.focus,\n.btn:active.focus,\n.btn.active.focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n.btn:hover,\n.btn:focus,\n.btn.focus {\n color: #333;\n text-decoration: none;\n}\n.btn:active,\n.btn.active {\n background-image: none;\n outline: 0;\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n cursor: not-allowed;\n filter: alpha(opacity=65);\n opacity: 0.65;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\na.btn.disabled,\nfieldset[disabled] a.btn {\n pointer-events: none;\n}\n.btn-default {\n color: #333;\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default:focus,\n.btn-default.focus {\n color: #333;\n background-color: #e6e6e6;\n border-color: #8c8c8c;\n}\n.btn-default:hover {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n color: #333;\n background-color: #e6e6e6;\n background-image: none;\n border-color: #adadad;\n}\n.btn-default:active:hover,\n.btn-default.active:hover,\n.open > .dropdown-toggle.btn-default:hover,\n.btn-default:active:focus,\n.btn-default.active:focus,\n.open > .dropdown-toggle.btn-default:focus,\n.btn-default:active.focus,\n.btn-default.active.focus,\n.open > .dropdown-toggle.btn-default.focus {\n color: #333;\n background-color: #d4d4d4;\n border-color: #8c8c8c;\n}\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus {\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default .badge {\n color: #fff;\n background-color: #333;\n}\n.btn-primary {\n color: #fff;\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary:focus,\n.btn-primary.focus {\n color: #fff;\n background-color: #286090;\n border-color: #122b40;\n}\n.btn-primary:hover {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n color: #fff;\n background-color: #286090;\n background-image: none;\n border-color: #204d74;\n}\n.btn-primary:active:hover,\n.btn-primary.active:hover,\n.open > .dropdown-toggle.btn-primary:hover,\n.btn-primary:active:focus,\n.btn-primary.active:focus,\n.open > .dropdown-toggle.btn-primary:focus,\n.btn-primary:active.focus,\n.btn-primary.active.focus,\n.open > .dropdown-toggle.btn-primary.focus {\n color: #fff;\n background-color: #204d74;\n border-color: #122b40;\n}\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus {\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.btn-success {\n color: #fff;\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success:focus,\n.btn-success.focus {\n color: #fff;\n background-color: #449d44;\n border-color: #255625;\n}\n.btn-success:hover {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n color: #fff;\n background-color: #449d44;\n background-image: none;\n border-color: #398439;\n}\n.btn-success:active:hover,\n.btn-success.active:hover,\n.open > .dropdown-toggle.btn-success:hover,\n.btn-success:active:focus,\n.btn-success.active:focus,\n.open > .dropdown-toggle.btn-success:focus,\n.btn-success:active.focus,\n.btn-success.active.focus,\n.open > .dropdown-toggle.btn-success.focus {\n color: #fff;\n background-color: #398439;\n border-color: #255625;\n}\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus {\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success .badge {\n color: #5cb85c;\n background-color: #fff;\n}\n.btn-info {\n color: #fff;\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info:focus,\n.btn-info.focus {\n color: #fff;\n background-color: #31b0d5;\n border-color: #1b6d85;\n}\n.btn-info:hover {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n color: #fff;\n background-color: #31b0d5;\n background-image: none;\n border-color: #269abc;\n}\n.btn-info:active:hover,\n.btn-info.active:hover,\n.open > .dropdown-toggle.btn-info:hover,\n.btn-info:active:focus,\n.btn-info.active:focus,\n.open > .dropdown-toggle.btn-info:focus,\n.btn-info:active.focus,\n.btn-info.active.focus,\n.open > .dropdown-toggle.btn-info.focus {\n color: #fff;\n background-color: #269abc;\n border-color: #1b6d85;\n}\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus {\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info .badge {\n color: #5bc0de;\n background-color: #fff;\n}\n.btn-warning {\n color: #fff;\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning:focus,\n.btn-warning.focus {\n color: #fff;\n background-color: #ec971f;\n border-color: #985f0d;\n}\n.btn-warning:hover {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n color: #fff;\n background-color: #ec971f;\n background-image: none;\n border-color: #d58512;\n}\n.btn-warning:active:hover,\n.btn-warning.active:hover,\n.open > .dropdown-toggle.btn-warning:hover,\n.btn-warning:active:focus,\n.btn-warning.active:focus,\n.open > .dropdown-toggle.btn-warning:focus,\n.btn-warning:active.focus,\n.btn-warning.active.focus,\n.open > .dropdown-toggle.btn-warning.focus {\n color: #fff;\n background-color: #d58512;\n border-color: #985f0d;\n}\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus {\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning .badge {\n color: #f0ad4e;\n background-color: #fff;\n}\n.btn-danger {\n color: #fff;\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger:focus,\n.btn-danger.focus {\n color: #fff;\n background-color: #c9302c;\n border-color: #761c19;\n}\n.btn-danger:hover {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n color: #fff;\n background-color: #c9302c;\n background-image: none;\n border-color: #ac2925;\n}\n.btn-danger:active:hover,\n.btn-danger.active:hover,\n.open > .dropdown-toggle.btn-danger:hover,\n.btn-danger:active:focus,\n.btn-danger.active:focus,\n.open > .dropdown-toggle.btn-danger:focus,\n.btn-danger:active.focus,\n.btn-danger.active.focus,\n.open > .dropdown-toggle.btn-danger.focus {\n color: #fff;\n background-color: #ac2925;\n border-color: #761c19;\n}\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus {\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger .badge {\n color: #d9534f;\n background-color: #fff;\n}\n.btn-link {\n font-weight: 400;\n color: #337ab7;\n border-radius: 0;\n}\n.btn-link,\n.btn-link:active,\n.btn-link.active,\n.btn-link[disabled],\nfieldset[disabled] .btn-link {\n background-color: transparent;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n border-color: transparent;\n}\n.btn-link:hover,\n.btn-link:focus {\n color: #23527c;\n text-decoration: underline;\n background-color: transparent;\n}\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n color: #777777;\n text-decoration: none;\n}\n.btn-lg,\n.btn-group-lg > .btn {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.btn-sm,\n.btn-group-sm > .btn {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-xs,\n.btn-group-xs > .btn {\n padding: 1px 5px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-block {\n display: block;\n width: 100%;\n}\n.btn-block + .btn-block {\n margin-top: 5px;\n}\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n width: 100%;\n}\n.fade {\n opacity: 0;\n -webkit-transition: opacity 0.15s linear;\n -o-transition: opacity 0.15s linear;\n transition: opacity 0.15s linear;\n}\n.fade.in {\n opacity: 1;\n}\n.collapse {\n display: none;\n}\n.collapse.in {\n display: block;\n}\ntr.collapse.in {\n display: table-row;\n}\ntbody.collapse.in {\n display: table-row-group;\n}\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n -webkit-transition-property: height, visibility;\n transition-property: height, visibility;\n -webkit-transition-duration: 0.35s;\n transition-duration: 0.35s;\n -webkit-transition-timing-function: ease;\n transition-timing-function: ease;\n}\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: 4px dashed;\n border-top: 4px solid \\9;\n border-right: 4px solid transparent;\n border-left: 4px solid transparent;\n}\n.dropup,\n.dropdown {\n position: relative;\n}\n.dropdown-toggle:focus {\n outline: 0;\n}\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0;\n font-size: 14px;\n text-align: left;\n list-style: none;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, 0.15);\n border-radius: 4px;\n -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n}\n.dropdown-menu.pull-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu .divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.dropdown-menu > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: 400;\n line-height: 1.42857143;\n color: #333333;\n white-space: nowrap;\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n color: #262626;\n text-decoration: none;\n background-color: #f5f5f5;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n color: #fff;\n text-decoration: none;\n background-color: #337ab7;\n outline: 0;\n}\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n color: #777777;\n}\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n text-decoration: none;\n cursor: not-allowed;\n background-color: transparent;\n background-image: none;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n}\n.open > .dropdown-menu {\n display: block;\n}\n.open > a {\n outline: 0;\n}\n.dropdown-menu-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu-left {\n right: auto;\n left: 0;\n}\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: 12px;\n line-height: 1.42857143;\n color: #777777;\n white-space: nowrap;\n}\n.dropdown-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 990;\n}\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n content: \"\";\n border-top: 0;\n border-bottom: 4px dashed;\n border-bottom: 4px solid \\9;\n}\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n}\n@media (min-width: 768px) {\n .navbar-right .dropdown-menu {\n right: 0;\n left: auto;\n }\n .navbar-right .dropdown-menu-left {\n right: auto;\n left: 0;\n }\n}\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle;\n}\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n position: relative;\n float: left;\n}\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus,\n.btn-group > .btn:active,\n.btn-group-vertical > .btn:active,\n.btn-group > .btn.active,\n.btn-group-vertical > .btn.active {\n z-index: 2;\n}\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group {\n margin-left: -1px;\n}\n.btn-toolbar {\n margin-left: -5px;\n}\n.btn-toolbar .btn,\n.btn-toolbar .btn-group,\n.btn-toolbar .input-group {\n float: left;\n}\n.btn-toolbar > .btn,\n.btn-toolbar > .btn-group,\n.btn-toolbar > .input-group {\n margin-left: 5px;\n}\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n.btn-group > .btn:first-child {\n margin-left: 0;\n}\n.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n.btn-group > .btn + .dropdown-toggle {\n padding-right: 8px;\n padding-left: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-right: 12px;\n padding-left: 12px;\n}\n.btn-group.open .dropdown-toggle {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-group.open .dropdown-toggle.btn-link {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn .caret {\n margin-left: 0;\n}\n.btn-lg .caret {\n border-width: 5px 5px 0;\n border-bottom-width: 0;\n}\n.dropup .btn-lg .caret {\n border-width: 0 5px 5px;\n}\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group,\n.btn-group-vertical > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n}\n.btn-group-vertical > .btn-group > .btn {\n float: none;\n}\n.btn-group-vertical > .btn + .btn,\n.btn-group-vertical > .btn + .btn-group,\n.btn-group-vertical > .btn-group + .btn,\n.btn-group-vertical > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n}\n.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.btn-group-vertical > .btn:first-child:not(:last-child) {\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn:last-child:not(:first-child) {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n}\n.btn-group-justified > .btn,\n.btn-group-justified > .btn-group {\n display: table-cell;\n float: none;\n width: 1%;\n}\n.btn-group-justified > .btn-group .btn {\n width: 100%;\n}\n.btn-group-justified > .btn-group .dropdown-menu {\n left: auto;\n}\n[data-toggle=\"buttons\"] > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn input[type=\"checkbox\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n}\n.input-group {\n position: relative;\n display: table;\n border-collapse: separate;\n}\n.input-group[class*=\"col-\"] {\n float: none;\n padding-right: 0;\n padding-left: 0;\n}\n.input-group .form-control {\n position: relative;\n z-index: 2;\n float: left;\n width: 100%;\n margin-bottom: 0;\n}\n.input-group .form-control:focus {\n z-index: 3;\n}\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-group-lg > .form-control,\nselect.input-group-lg > .input-group-addon,\nselect.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-group-lg > .form-control,\ntextarea.input-group-lg > .input-group-addon,\ntextarea.input-group-lg > .input-group-btn > .btn,\nselect[multiple].input-group-lg > .form-control,\nselect[multiple].input-group-lg > .input-group-addon,\nselect[multiple].input-group-lg > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-group-sm > .form-control,\nselect.input-group-sm > .input-group-addon,\nselect.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-group-sm > .form-control,\ntextarea.input-group-sm > .input-group-addon,\ntextarea.input-group-sm > .input-group-btn > .btn,\nselect[multiple].input-group-sm > .form-control,\nselect[multiple].input-group-sm > .input-group-addon,\nselect[multiple].input-group-sm > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n}\n.input-group-addon:not(:first-child):not(:last-child),\n.input-group-btn:not(:first-child):not(:last-child),\n.input-group .form-control:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle;\n}\n.input-group-addon {\n padding: 6px 12px;\n font-size: 14px;\n font-weight: 400;\n line-height: 1;\n color: #555555;\n text-align: center;\n background-color: #eeeeee;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\n.input-group-addon.input-sm {\n padding: 5px 10px;\n font-size: 12px;\n border-radius: 3px;\n}\n.input-group-addon.input-lg {\n padding: 10px 16px;\n font-size: 18px;\n border-radius: 6px;\n}\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n margin-top: 0;\n}\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n.input-group-btn {\n position: relative;\n font-size: 0;\n white-space: nowrap;\n}\n.input-group-btn > .btn {\n position: relative;\n}\n.input-group-btn > .btn + .btn {\n margin-left: -1px;\n}\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:focus,\n.input-group-btn > .btn:active {\n z-index: 2;\n}\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group {\n margin-right: -1px;\n}\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group {\n z-index: 2;\n margin-left: -1px;\n}\n.nav {\n padding-left: 0;\n margin-bottom: 0;\n list-style: none;\n}\n.nav > li {\n position: relative;\n display: block;\n}\n.nav > li > a {\n position: relative;\n display: block;\n padding: 10px 15px;\n}\n.nav > li > a:hover,\n.nav > li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.nav > li.disabled > a {\n color: #777777;\n}\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n color: #777777;\n text-decoration: none;\n cursor: not-allowed;\n background-color: transparent;\n}\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n background-color: #eeeeee;\n border-color: #337ab7;\n}\n.nav .nav-divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.nav > li > a > img {\n max-width: none;\n}\n.nav-tabs {\n border-bottom: 1px solid #ddd;\n}\n.nav-tabs > li {\n float: left;\n margin-bottom: -1px;\n}\n.nav-tabs > li > a {\n margin-right: 2px;\n line-height: 1.42857143;\n border: 1px solid transparent;\n border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n border-color: #eeeeee #eeeeee #ddd;\n}\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n color: #555555;\n cursor: default;\n background-color: #fff;\n border: 1px solid #ddd;\n border-bottom-color: transparent;\n}\n.nav-tabs.nav-justified {\n width: 100%;\n border-bottom: 0;\n}\n.nav-tabs.nav-justified > li {\n float: none;\n}\n.nav-tabs.nav-justified > li > a {\n margin-bottom: 5px;\n text-align: center;\n}\n.nav-tabs.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-tabs.nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs.nav-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs.nav-justified > .active > a,\n.nav-tabs.nav-justified > .active > a:hover,\n.nav-tabs.nav-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs.nav-justified > .active > a,\n .nav-tabs.nav-justified > .active > a:hover,\n .nav-tabs.nav-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.nav-pills > li {\n float: left;\n}\n.nav-pills > li > a {\n border-radius: 4px;\n}\n.nav-pills > li + li {\n margin-left: 2px;\n}\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n color: #fff;\n background-color: #337ab7;\n}\n.nav-stacked > li {\n float: none;\n}\n.nav-stacked > li + li {\n margin-top: 2px;\n margin-left: 0;\n}\n.nav-justified {\n width: 100%;\n}\n.nav-justified > li {\n float: none;\n}\n.nav-justified > li > a {\n margin-bottom: 5px;\n text-align: center;\n}\n.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs-justified {\n border-bottom: 0;\n}\n.nav-tabs-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs-justified > .active > a,\n.nav-tabs-justified > .active > a:hover,\n.nav-tabs-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs-justified > .active > a,\n .nav-tabs-justified > .active > a:hover,\n .nav-tabs-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.tab-content > .tab-pane {\n display: none;\n}\n.tab-content > .active {\n display: block;\n}\n.nav-tabs .dropdown-menu {\n margin-top: -1px;\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.navbar {\n position: relative;\n min-height: 50px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n}\n@media (min-width: 768px) {\n .navbar {\n border-radius: 4px;\n }\n}\n@media (min-width: 768px) {\n .navbar-header {\n float: left;\n }\n}\n.navbar-collapse {\n padding-right: 15px;\n padding-left: 15px;\n overflow-x: visible;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);\n -webkit-overflow-scrolling: touch;\n}\n.navbar-collapse.in {\n overflow-y: auto;\n}\n@media (min-width: 768px) {\n .navbar-collapse {\n width: auto;\n border-top: 0;\n box-shadow: none;\n }\n .navbar-collapse.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0;\n overflow: visible !important;\n }\n .navbar-collapse.in {\n overflow-y: visible;\n }\n .navbar-fixed-top .navbar-collapse,\n .navbar-static-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n padding-right: 0;\n padding-left: 0;\n }\n}\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: 1030;\n}\n.navbar-fixed-top .navbar-collapse,\n.navbar-fixed-bottom .navbar-collapse {\n max-height: 340px;\n}\n@media (max-device-width: 480px) and (orientation: landscape) {\n .navbar-fixed-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n max-height: 200px;\n }\n}\n@media (min-width: 768px) {\n .navbar-fixed-top,\n .navbar-fixed-bottom {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0;\n border-width: 1px 0 0;\n}\n.container > .navbar-header,\n.container-fluid > .navbar-header,\n.container > .navbar-collapse,\n.container-fluid > .navbar-collapse {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .container > .navbar-header,\n .container-fluid > .navbar-header,\n .container > .navbar-collapse,\n .container-fluid > .navbar-collapse {\n margin-right: 0;\n margin-left: 0;\n }\n}\n.navbar-static-top {\n z-index: 1000;\n border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n .navbar-static-top {\n border-radius: 0;\n }\n}\n.navbar-brand {\n float: left;\n height: 50px;\n padding: 15px 15px;\n font-size: 18px;\n line-height: 20px;\n}\n.navbar-brand:hover,\n.navbar-brand:focus {\n text-decoration: none;\n}\n.navbar-brand > img {\n display: block;\n}\n@media (min-width: 768px) {\n .navbar > .container .navbar-brand,\n .navbar > .container-fluid .navbar-brand {\n margin-left: -15px;\n }\n}\n.navbar-toggle {\n position: relative;\n float: right;\n padding: 9px 10px;\n margin-right: 15px;\n margin-top: 8px;\n margin-bottom: 8px;\n background-color: transparent;\n background-image: none;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.navbar-toggle:focus {\n outline: 0;\n}\n.navbar-toggle .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n}\n.navbar-toggle .icon-bar + .icon-bar {\n margin-top: 4px;\n}\n@media (min-width: 768px) {\n .navbar-toggle {\n display: none;\n }\n}\n.navbar-nav {\n margin: 7.5px -15px;\n}\n.navbar-nav > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: 20px;\n}\n@media (max-width: 767px) {\n .navbar-nav .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n }\n .navbar-nav .open .dropdown-menu > li > a,\n .navbar-nav .open .dropdown-menu .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n .navbar-nav .open .dropdown-menu > li > a {\n line-height: 20px;\n }\n .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-nav .open .dropdown-menu > li > a:focus {\n background-image: none;\n }\n}\n@media (min-width: 768px) {\n .navbar-nav {\n float: left;\n margin: 0;\n }\n .navbar-nav > li {\n float: left;\n }\n .navbar-nav > li > a {\n padding-top: 15px;\n padding-bottom: 15px;\n }\n}\n.navbar-form {\n padding: 10px 15px;\n margin-right: -15px;\n margin-left: -15px;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n margin-top: 8px;\n margin-bottom: 8px;\n}\n@media (min-width: 768px) {\n .navbar-form .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .navbar-form .form-control-static {\n display: inline-block;\n }\n .navbar-form .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .navbar-form .input-group .input-group-addon,\n .navbar-form .input-group .input-group-btn,\n .navbar-form .input-group .form-control {\n width: auto;\n }\n .navbar-form .input-group > .form-control {\n width: 100%;\n }\n .navbar-form .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio,\n .navbar-form .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio label,\n .navbar-form .checkbox label {\n padding-left: 0;\n }\n .navbar-form .radio input[type=\"radio\"],\n .navbar-form .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .navbar-form .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n@media (max-width: 767px) {\n .navbar-form .form-group {\n margin-bottom: 5px;\n }\n .navbar-form .form-group:last-child {\n margin-bottom: 0;\n }\n}\n@media (min-width: 768px) {\n .navbar-form {\n width: auto;\n padding-top: 0;\n padding-bottom: 0;\n margin-right: 0;\n margin-left: 0;\n border: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n}\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.navbar-btn {\n margin-top: 8px;\n margin-bottom: 8px;\n}\n.navbar-btn.btn-sm {\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.navbar-btn.btn-xs {\n margin-top: 14px;\n margin-bottom: 14px;\n}\n.navbar-text {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n@media (min-width: 768px) {\n .navbar-text {\n float: left;\n margin-right: 15px;\n margin-left: 15px;\n }\n}\n@media (min-width: 768px) {\n .navbar-left {\n float: left !important;\n }\n .navbar-right {\n float: right !important;\n margin-right: -15px;\n }\n .navbar-right ~ .navbar-right {\n margin-right: 0;\n }\n}\n.navbar-default {\n background-color: #f8f8f8;\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-brand {\n color: #777;\n}\n.navbar-default .navbar-brand:hover,\n.navbar-default .navbar-brand:focus {\n color: #5e5e5e;\n background-color: transparent;\n}\n.navbar-default .navbar-text {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a:hover,\n.navbar-default .navbar-nav > li > a:focus {\n color: #333;\n background-color: transparent;\n}\n.navbar-default .navbar-nav > .active > a,\n.navbar-default .navbar-nav > .active > a:hover,\n.navbar-default .navbar-nav > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .disabled > a,\n.navbar-default .navbar-nav > .disabled > a:hover,\n.navbar-default .navbar-nav > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .open > a:hover,\n.navbar-default .navbar-nav > .open > a:focus {\n color: #555;\n background-color: #e7e7e7;\n}\n@media (max-width: 767px) {\n .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n color: #777;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #333;\n background-color: transparent;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n }\n}\n.navbar-default .navbar-toggle {\n border-color: #ddd;\n}\n.navbar-default .navbar-toggle:hover,\n.navbar-default .navbar-toggle:focus {\n background-color: #ddd;\n}\n.navbar-default .navbar-toggle .icon-bar {\n background-color: #888;\n}\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-link {\n color: #777;\n}\n.navbar-default .navbar-link:hover {\n color: #333;\n}\n.navbar-default .btn-link {\n color: #777;\n}\n.navbar-default .btn-link:hover,\n.navbar-default .btn-link:focus {\n color: #333;\n}\n.navbar-default .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-default .btn-link:hover,\n.navbar-default .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-default .btn-link:focus {\n color: #ccc;\n}\n.navbar-inverse {\n background-color: #222;\n border-color: #080808;\n}\n.navbar-inverse .navbar-brand {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-text {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .active > a,\n.navbar-inverse .navbar-nav > .active > a:hover,\n.navbar-inverse .navbar-nav > .active > a:focus {\n color: #fff;\n background-color: #080808;\n}\n.navbar-inverse .navbar-nav > .disabled > a,\n.navbar-inverse .navbar-nav > .disabled > a:hover,\n.navbar-inverse .navbar-nav > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .open > a:hover,\n.navbar-inverse .navbar-nav > .open > a:focus {\n color: #fff;\n background-color: #080808;\n}\n@media (max-width: 767px) {\n .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n border-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu .divider {\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n color: #9d9d9d;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #fff;\n background-color: transparent;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n }\n}\n.navbar-inverse .navbar-toggle {\n border-color: #333;\n}\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n background-color: #333;\n}\n.navbar-inverse .navbar-toggle .icon-bar {\n background-color: #fff;\n}\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n border-color: #101010;\n}\n.navbar-inverse .navbar-link {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-link:hover {\n color: #fff;\n}\n.navbar-inverse .btn-link {\n color: #9d9d9d;\n}\n.navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link:focus {\n color: #fff;\n}\n.navbar-inverse .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-inverse .btn-link:focus {\n color: #444;\n}\n.breadcrumb {\n padding: 8px 15px;\n margin-bottom: 20px;\n list-style: none;\n background-color: #f5f5f5;\n border-radius: 4px;\n}\n.breadcrumb > li {\n display: inline-block;\n}\n.breadcrumb > li + li:before {\n padding: 0 5px;\n color: #ccc;\n content: \"/\\00a0\";\n}\n.breadcrumb > .active {\n color: #777777;\n}\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: 20px 0;\n border-radius: 4px;\n}\n.pagination > li {\n display: inline;\n}\n.pagination > li > a,\n.pagination > li > span {\n position: relative;\n float: left;\n padding: 6px 12px;\n margin-left: -1px;\n line-height: 1.42857143;\n color: #337ab7;\n text-decoration: none;\n background-color: #fff;\n border: 1px solid #ddd;\n}\n.pagination > li > a:hover,\n.pagination > li > span:hover,\n.pagination > li > a:focus,\n.pagination > li > span:focus {\n z-index: 2;\n color: #23527c;\n background-color: #eeeeee;\n border-color: #ddd;\n}\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n margin-left: 0;\n border-top-left-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.pagination > li:last-child > a,\n.pagination > li:last-child > span {\n border-top-right-radius: 4px;\n border-bottom-right-radius: 4px;\n}\n.pagination > .active > a,\n.pagination > .active > span,\n.pagination > .active > a:hover,\n.pagination > .active > span:hover,\n.pagination > .active > a:focus,\n.pagination > .active > span:focus {\n z-index: 3;\n color: #fff;\n cursor: default;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.pagination > .disabled > span,\n.pagination > .disabled > span:hover,\n.pagination > .disabled > span:focus,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n color: #777777;\n cursor: not-allowed;\n background-color: #fff;\n border-color: #ddd;\n}\n.pagination-lg > li > a,\n.pagination-lg > li > span {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.pagination-lg > li:first-child > a,\n.pagination-lg > li:first-child > span {\n border-top-left-radius: 6px;\n border-bottom-left-radius: 6px;\n}\n.pagination-lg > li:last-child > a,\n.pagination-lg > li:last-child > span {\n border-top-right-radius: 6px;\n border-bottom-right-radius: 6px;\n}\n.pagination-sm > li > a,\n.pagination-sm > li > span {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n border-top-left-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.pagination-sm > li:last-child > a,\n.pagination-sm > li:last-child > span {\n border-top-right-radius: 3px;\n border-bottom-right-radius: 3px;\n}\n.pager {\n padding-left: 0;\n margin: 20px 0;\n text-align: center;\n list-style: none;\n}\n.pager li {\n display: inline;\n}\n.pager li > a,\n.pager li > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 15px;\n}\n.pager li > a:hover,\n.pager li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.pager .next > a,\n.pager .next > span {\n float: right;\n}\n.pager .previous > a,\n.pager .previous > span {\n float: left;\n}\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n color: #777777;\n cursor: not-allowed;\n background-color: #fff;\n}\n.label {\n display: inline;\n padding: 0.2em 0.6em 0.3em;\n font-size: 75%;\n font-weight: 700;\n line-height: 1;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: 0.25em;\n}\na.label:hover,\na.label:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.label:empty {\n display: none;\n}\n.btn .label {\n position: relative;\n top: -1px;\n}\n.label-default {\n background-color: #777777;\n}\n.label-default[href]:hover,\n.label-default[href]:focus {\n background-color: #5e5e5e;\n}\n.label-primary {\n background-color: #337ab7;\n}\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n background-color: #286090;\n}\n.label-success {\n background-color: #5cb85c;\n}\n.label-success[href]:hover,\n.label-success[href]:focus {\n background-color: #449d44;\n}\n.label-info {\n background-color: #5bc0de;\n}\n.label-info[href]:hover,\n.label-info[href]:focus {\n background-color: #31b0d5;\n}\n.label-warning {\n background-color: #f0ad4e;\n}\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n background-color: #ec971f;\n}\n.label-danger {\n background-color: #d9534f;\n}\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n background-color: #c9302c;\n}\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: 12px;\n font-weight: bold;\n line-height: 1;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n vertical-align: middle;\n background-color: #777777;\n border-radius: 10px;\n}\n.badge:empty {\n display: none;\n}\n.btn .badge {\n position: relative;\n top: -1px;\n}\n.btn-xs .badge,\n.btn-group-xs > .btn .badge {\n top: 0;\n padding: 1px 5px;\n}\na.badge:hover,\na.badge:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.list-group-item > .badge {\n float: right;\n}\n.list-group-item > .badge + .badge {\n margin-right: 5px;\n}\n.nav-pills > li > a > .badge {\n margin-left: 3px;\n}\n.jumbotron {\n padding-top: 30px;\n padding-bottom: 30px;\n margin-bottom: 30px;\n color: inherit;\n background-color: #eeeeee;\n}\n.jumbotron h1,\n.jumbotron .h1 {\n color: inherit;\n}\n.jumbotron p {\n margin-bottom: 15px;\n font-size: 21px;\n font-weight: 200;\n}\n.jumbotron > hr {\n border-top-color: #d5d5d5;\n}\n.container .jumbotron,\n.container-fluid .jumbotron {\n padding-right: 15px;\n padding-left: 15px;\n border-radius: 6px;\n}\n.jumbotron .container {\n max-width: 100%;\n}\n@media screen and (min-width: 768px) {\n .jumbotron {\n padding-top: 48px;\n padding-bottom: 48px;\n }\n .container .jumbotron,\n .container-fluid .jumbotron {\n padding-right: 60px;\n padding-left: 60px;\n }\n .jumbotron h1,\n .jumbotron .h1 {\n font-size: 63px;\n }\n}\n.thumbnail {\n display: block;\n padding: 4px;\n margin-bottom: 20px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: border 0.2s ease-in-out;\n -o-transition: border 0.2s ease-in-out;\n transition: border 0.2s ease-in-out;\n}\n.thumbnail > img,\n.thumbnail a > img {\n margin-right: auto;\n margin-left: auto;\n}\na.thumbnail:hover,\na.thumbnail:focus,\na.thumbnail.active {\n border-color: #337ab7;\n}\n.thumbnail .caption {\n padding: 9px;\n color: #333333;\n}\n.alert {\n padding: 15px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.alert h4 {\n margin-top: 0;\n color: inherit;\n}\n.alert .alert-link {\n font-weight: bold;\n}\n.alert > p,\n.alert > ul {\n margin-bottom: 0;\n}\n.alert > p + p {\n margin-top: 5px;\n}\n.alert-dismissable,\n.alert-dismissible {\n padding-right: 35px;\n}\n.alert-dismissable .close,\n.alert-dismissible .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n}\n.alert-success {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.alert-success hr {\n border-top-color: #c9e2b3;\n}\n.alert-success .alert-link {\n color: #2b542c;\n}\n.alert-info {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.alert-info hr {\n border-top-color: #a6e1ec;\n}\n.alert-info .alert-link {\n color: #245269;\n}\n.alert-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.alert-warning hr {\n border-top-color: #f7e1b5;\n}\n.alert-warning .alert-link {\n color: #66512c;\n}\n.alert-danger {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.alert-danger hr {\n border-top-color: #e4b9c0;\n}\n.alert-danger .alert-link {\n color: #843534;\n}\n@-webkit-keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n@keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n.progress {\n height: 20px;\n margin-bottom: 20px;\n overflow: hidden;\n background-color: #f5f5f5;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: 12px;\n line-height: 20px;\n color: #fff;\n text-align: center;\n background-color: #337ab7;\n -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n -webkit-transition: width 0.6s ease;\n -o-transition: width 0.6s ease;\n transition: width 0.6s ease;\n}\n.progress-striped .progress-bar,\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-size: 40px 40px;\n}\n.progress.active .progress-bar,\n.progress-bar.active {\n -webkit-animation: progress-bar-stripes 2s linear infinite;\n -o-animation: progress-bar-stripes 2s linear infinite;\n animation: progress-bar-stripes 2s linear infinite;\n}\n.progress-bar-success {\n background-color: #5cb85c;\n}\n.progress-striped .progress-bar-success {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-info {\n background-color: #5bc0de;\n}\n.progress-striped .progress-bar-info {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-warning {\n background-color: #f0ad4e;\n}\n.progress-striped .progress-bar-warning {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-danger {\n background-color: #d9534f;\n}\n.progress-striped .progress-bar-danger {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.media {\n margin-top: 15px;\n}\n.media:first-child {\n margin-top: 0;\n}\n.media,\n.media-body {\n overflow: hidden;\n zoom: 1;\n}\n.media-body {\n width: 10000px;\n}\n.media-object {\n display: block;\n}\n.media-object.img-thumbnail {\n max-width: none;\n}\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n.media-middle {\n vertical-align: middle;\n}\n.media-bottom {\n vertical-align: bottom;\n}\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n.list-group {\n padding-left: 0;\n margin-bottom: 20px;\n}\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n margin-bottom: -1px;\n background-color: #fff;\n border: 1px solid #ddd;\n}\n.list-group-item:first-child {\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n}\n.list-group-item:last-child {\n margin-bottom: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.list-group-item.disabled,\n.list-group-item.disabled:hover,\n.list-group-item.disabled:focus {\n color: #777777;\n cursor: not-allowed;\n background-color: #eeeeee;\n}\n.list-group-item.disabled .list-group-item-heading,\n.list-group-item.disabled:hover .list-group-item-heading,\n.list-group-item.disabled:focus .list-group-item-heading {\n color: inherit;\n}\n.list-group-item.disabled .list-group-item-text,\n.list-group-item.disabled:hover .list-group-item-text,\n.list-group-item.disabled:focus .list-group-item-text {\n color: #777777;\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n z-index: 2;\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.list-group-item.active .list-group-item-heading,\n.list-group-item.active:hover .list-group-item-heading,\n.list-group-item.active:focus .list-group-item-heading,\n.list-group-item.active .list-group-item-heading > small,\n.list-group-item.active:hover .list-group-item-heading > small,\n.list-group-item.active:focus .list-group-item-heading > small,\n.list-group-item.active .list-group-item-heading > .small,\n.list-group-item.active:hover .list-group-item-heading > .small,\n.list-group-item.active:focus .list-group-item-heading > .small {\n color: inherit;\n}\n.list-group-item.active .list-group-item-text,\n.list-group-item.active:hover .list-group-item-text,\n.list-group-item.active:focus .list-group-item-text {\n color: #c7ddef;\n}\na.list-group-item,\nbutton.list-group-item {\n color: #555;\n}\na.list-group-item .list-group-item-heading,\nbutton.list-group-item .list-group-item-heading {\n color: #333;\n}\na.list-group-item:hover,\nbutton.list-group-item:hover,\na.list-group-item:focus,\nbutton.list-group-item:focus {\n color: #555;\n text-decoration: none;\n background-color: #f5f5f5;\n}\nbutton.list-group-item {\n width: 100%;\n text-align: left;\n}\n.list-group-item-success {\n color: #3c763d;\n background-color: #dff0d8;\n}\na.list-group-item-success,\nbutton.list-group-item-success {\n color: #3c763d;\n}\na.list-group-item-success .list-group-item-heading,\nbutton.list-group-item-success .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-success:hover,\nbutton.list-group-item-success:hover,\na.list-group-item-success:focus,\nbutton.list-group-item-success:focus {\n color: #3c763d;\n background-color: #d0e9c6;\n}\na.list-group-item-success.active,\nbutton.list-group-item-success.active,\na.list-group-item-success.active:hover,\nbutton.list-group-item-success.active:hover,\na.list-group-item-success.active:focus,\nbutton.list-group-item-success.active:focus {\n color: #fff;\n background-color: #3c763d;\n border-color: #3c763d;\n}\n.list-group-item-info {\n color: #31708f;\n background-color: #d9edf7;\n}\na.list-group-item-info,\nbutton.list-group-item-info {\n color: #31708f;\n}\na.list-group-item-info .list-group-item-heading,\nbutton.list-group-item-info .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-info:hover,\nbutton.list-group-item-info:hover,\na.list-group-item-info:focus,\nbutton.list-group-item-info:focus {\n color: #31708f;\n background-color: #c4e3f3;\n}\na.list-group-item-info.active,\nbutton.list-group-item-info.active,\na.list-group-item-info.active:hover,\nbutton.list-group-item-info.active:hover,\na.list-group-item-info.active:focus,\nbutton.list-group-item-info.active:focus {\n color: #fff;\n background-color: #31708f;\n border-color: #31708f;\n}\n.list-group-item-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n}\na.list-group-item-warning,\nbutton.list-group-item-warning {\n color: #8a6d3b;\n}\na.list-group-item-warning .list-group-item-heading,\nbutton.list-group-item-warning .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-warning:hover,\nbutton.list-group-item-warning:hover,\na.list-group-item-warning:focus,\nbutton.list-group-item-warning:focus {\n color: #8a6d3b;\n background-color: #faf2cc;\n}\na.list-group-item-warning.active,\nbutton.list-group-item-warning.active,\na.list-group-item-warning.active:hover,\nbutton.list-group-item-warning.active:hover,\na.list-group-item-warning.active:focus,\nbutton.list-group-item-warning.active:focus {\n color: #fff;\n background-color: #8a6d3b;\n border-color: #8a6d3b;\n}\n.list-group-item-danger {\n color: #a94442;\n background-color: #f2dede;\n}\na.list-group-item-danger,\nbutton.list-group-item-danger {\n color: #a94442;\n}\na.list-group-item-danger .list-group-item-heading,\nbutton.list-group-item-danger .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-danger:hover,\nbutton.list-group-item-danger:hover,\na.list-group-item-danger:focus,\nbutton.list-group-item-danger:focus {\n color: #a94442;\n background-color: #ebcccc;\n}\na.list-group-item-danger.active,\nbutton.list-group-item-danger.active,\na.list-group-item-danger.active:hover,\nbutton.list-group-item-danger.active:hover,\na.list-group-item-danger.active:focus,\nbutton.list-group-item-danger.active:focus {\n color: #fff;\n background-color: #a94442;\n border-color: #a94442;\n}\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n.panel {\n margin-bottom: 20px;\n background-color: #fff;\n border: 1px solid transparent;\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.panel-body {\n padding: 15px;\n}\n.panel-heading {\n padding: 10px 15px;\n border-bottom: 1px solid transparent;\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel-heading > .dropdown .dropdown-toggle {\n color: inherit;\n}\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: 16px;\n color: inherit;\n}\n.panel-title > a,\n.panel-title > small,\n.panel-title > .small,\n.panel-title > small > a,\n.panel-title > .small > a {\n color: inherit;\n}\n.panel-footer {\n padding: 10px 15px;\n background-color: #f5f5f5;\n border-top: 1px solid #ddd;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .list-group,\n.panel > .panel-collapse > .list-group {\n margin-bottom: 0;\n}\n.panel > .list-group .list-group-item,\n.panel > .panel-collapse > .list-group .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n}\n.panel > .list-group:first-child .list-group-item:first-child,\n.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {\n border-top: 0;\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .list-group:last-child .list-group-item:last-child,\n.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {\n border-bottom: 0;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.panel-heading + .list-group .list-group-item:first-child {\n border-top-width: 0;\n}\n.list-group + .panel-footer {\n border-top-width: 0;\n}\n.panel > .table,\n.panel > .table-responsive > .table,\n.panel > .panel-collapse > .table {\n margin-bottom: 0;\n}\n.panel > .table caption,\n.panel > .table-responsive > .table caption,\n.panel > .panel-collapse > .table caption {\n padding-right: 15px;\n padding-left: 15px;\n}\n.panel > .table:first-child,\n.panel > .table-responsive:first-child > .table:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {\n border-top-right-radius: 3px;\n}\n.panel > .table:last-child,\n.panel > .table-responsive:last-child > .table:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {\n border-bottom-right-radius: 3px;\n}\n.panel > .panel-body + .table,\n.panel > .panel-body + .table-responsive,\n.panel > .table + .panel-body,\n.panel > .table-responsive + .panel-body {\n border-top: 1px solid #ddd;\n}\n.panel > .table > tbody:first-child > tr:first-child th,\n.panel > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n}\n.panel > .table-bordered,\n.panel > .table-responsive > .table-bordered {\n border: 0;\n}\n.panel > .table-bordered > thead > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,\n.panel > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-bordered > thead > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,\n.panel > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-bordered > tfoot > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n}\n.panel > .table-bordered > thead > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,\n.panel > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-bordered > thead > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,\n.panel > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-bordered > tfoot > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n}\n.panel > .table-bordered > thead > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,\n.panel > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-bordered > thead > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,\n.panel > .table-bordered > tbody > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {\n border-bottom: 0;\n}\n.panel > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {\n border-bottom: 0;\n}\n.panel > .table-responsive {\n margin-bottom: 0;\n border: 0;\n}\n.panel-group {\n margin-bottom: 20px;\n}\n.panel-group .panel {\n margin-bottom: 0;\n border-radius: 4px;\n}\n.panel-group .panel + .panel {\n margin-top: 5px;\n}\n.panel-group .panel-heading {\n border-bottom: 0;\n}\n.panel-group .panel-heading + .panel-collapse > .panel-body,\n.panel-group .panel-heading + .panel-collapse > .list-group {\n border-top: 1px solid #ddd;\n}\n.panel-group .panel-footer {\n border-top: 0;\n}\n.panel-group .panel-footer + .panel-collapse .panel-body {\n border-bottom: 1px solid #ddd;\n}\n.panel-default {\n border-color: #ddd;\n}\n.panel-default > .panel-heading {\n color: #333333;\n background-color: #f5f5f5;\n border-color: #ddd;\n}\n.panel-default > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ddd;\n}\n.panel-default > .panel-heading .badge {\n color: #f5f5f5;\n background-color: #333333;\n}\n.panel-default > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ddd;\n}\n.panel-primary {\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading {\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #337ab7;\n}\n.panel-primary > .panel-heading .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.panel-primary > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #337ab7;\n}\n.panel-success {\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #d6e9c6;\n}\n.panel-success > .panel-heading .badge {\n color: #dff0d8;\n background-color: #3c763d;\n}\n.panel-success > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #d6e9c6;\n}\n.panel-info {\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #bce8f1;\n}\n.panel-info > .panel-heading .badge {\n color: #d9edf7;\n background-color: #31708f;\n}\n.panel-info > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #bce8f1;\n}\n.panel-warning {\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #faebcc;\n}\n.panel-warning > .panel-heading .badge {\n color: #fcf8e3;\n background-color: #8a6d3b;\n}\n.panel-warning > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #faebcc;\n}\n.panel-danger {\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ebccd1;\n}\n.panel-danger > .panel-heading .badge {\n color: #f2dede;\n background-color: #a94442;\n}\n.panel-danger > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ebccd1;\n}\n.embed-responsive {\n position: relative;\n display: block;\n height: 0;\n padding: 0;\n overflow: hidden;\n}\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 100%;\n height: 100%;\n border: 0;\n}\n.embed-responsive-16by9 {\n padding-bottom: 56.25%;\n}\n.embed-responsive-4by3 {\n padding-bottom: 75%;\n}\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border: 1px solid #e3e3e3;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.well blockquote {\n border-color: #ddd;\n border-color: rgba(0, 0, 0, 0.15);\n}\n.well-lg {\n padding: 24px;\n border-radius: 6px;\n}\n.well-sm {\n padding: 9px;\n border-radius: 3px;\n}\n.close {\n float: right;\n font-size: 21px;\n font-weight: bold;\n line-height: 1;\n color: #000;\n text-shadow: 0 1px 0 #fff;\n filter: alpha(opacity=20);\n opacity: 0.2;\n}\n.close:hover,\n.close:focus {\n color: #000;\n text-decoration: none;\n cursor: pointer;\n filter: alpha(opacity=50);\n opacity: 0.5;\n}\nbutton.close {\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n -webkit-appearance: none;\n appearance: none;\n}\n.modal-open {\n overflow: hidden;\n}\n.modal {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1050;\n display: none;\n overflow: hidden;\n -webkit-overflow-scrolling: touch;\n outline: 0;\n}\n.modal.fade .modal-dialog {\n -webkit-transform: translate(0, -25%);\n -ms-transform: translate(0, -25%);\n -o-transform: translate(0, -25%);\n transform: translate(0, -25%);\n -webkit-transition: -webkit-transform 0.3s ease-out;\n -moz-transition: -moz-transform 0.3s ease-out;\n -o-transition: -o-transform 0.3s ease-out;\n transition: transform 0.3s ease-out;\n}\n.modal.in .modal-dialog {\n -webkit-transform: translate(0, 0);\n -ms-transform: translate(0, 0);\n -o-transform: translate(0, 0);\n transform: translate(0, 0);\n}\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n.modal-content {\n position: relative;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid #999;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n outline: 0;\n}\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1040;\n background-color: #000;\n}\n.modal-backdrop.fade {\n filter: alpha(opacity=0);\n opacity: 0;\n}\n.modal-backdrop.in {\n filter: alpha(opacity=50);\n opacity: 0.5;\n}\n.modal-header {\n padding: 15px;\n border-bottom: 1px solid #e5e5e5;\n}\n.modal-header .close {\n margin-top: -2px;\n}\n.modal-title {\n margin: 0;\n line-height: 1.42857143;\n}\n.modal-body {\n position: relative;\n padding: 15px;\n}\n.modal-footer {\n padding: 15px;\n text-align: right;\n border-top: 1px solid #e5e5e5;\n}\n.modal-footer .btn + .btn {\n margin-bottom: 0;\n margin-left: 5px;\n}\n.modal-footer .btn-group .btn + .btn {\n margin-left: -1px;\n}\n.modal-footer .btn-block + .btn-block {\n margin-left: 0;\n}\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n@media (min-width: 768px) {\n .modal-dialog {\n width: 600px;\n margin: 30px auto;\n }\n .modal-content {\n -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n }\n .modal-sm {\n width: 300px;\n }\n}\n@media (min-width: 992px) {\n .modal-lg {\n width: 900px;\n }\n}\n.tooltip {\n position: absolute;\n z-index: 1070;\n display: block;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: 400;\n line-height: 1.42857143;\n line-break: auto;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n letter-spacing: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n white-space: normal;\n font-size: 12px;\n filter: alpha(opacity=0);\n opacity: 0;\n}\n.tooltip.in {\n filter: alpha(opacity=90);\n opacity: 0.9;\n}\n.tooltip.top {\n padding: 5px 0;\n margin-top: -3px;\n}\n.tooltip.right {\n padding: 0 5px;\n margin-left: 3px;\n}\n.tooltip.bottom {\n padding: 5px 0;\n margin-top: 3px;\n}\n.tooltip.left {\n padding: 0 5px;\n margin-left: -3px;\n}\n.tooltip.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-left .tooltip-arrow {\n right: 5px;\n bottom: 0;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-right .tooltip-arrow {\n bottom: 0;\n left: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -5px;\n border-width: 5px 5px 5px 0;\n border-right-color: #000;\n}\n.tooltip.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -5px;\n border-width: 5px 0 5px 5px;\n border-left-color: #000;\n}\n.tooltip.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-left .tooltip-arrow {\n top: 0;\n right: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-right .tooltip-arrow {\n top: 0;\n left: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip-inner {\n max-width: 200px;\n padding: 3px 8px;\n color: #fff;\n text-align: center;\n background-color: #000;\n border-radius: 4px;\n}\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1060;\n display: none;\n max-width: 276px;\n padding: 1px;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: 400;\n line-height: 1.42857143;\n line-break: auto;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n letter-spacing: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n white-space: normal;\n font-size: 14px;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n}\n.popover.top {\n margin-top: -10px;\n}\n.popover.right {\n margin-left: 10px;\n}\n.popover.bottom {\n margin-top: 10px;\n}\n.popover.left {\n margin-left: -10px;\n}\n.popover > .arrow {\n border-width: 11px;\n}\n.popover > .arrow,\n.popover > .arrow:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.popover > .arrow:after {\n content: \"\";\n border-width: 10px;\n}\n.popover.top > .arrow {\n bottom: -11px;\n left: 50%;\n margin-left: -11px;\n border-top-color: #999999;\n border-top-color: rgba(0, 0, 0, 0.25);\n border-bottom-width: 0;\n}\n.popover.top > .arrow:after {\n bottom: 1px;\n margin-left: -10px;\n content: \" \";\n border-top-color: #fff;\n border-bottom-width: 0;\n}\n.popover.right > .arrow {\n top: 50%;\n left: -11px;\n margin-top: -11px;\n border-right-color: #999999;\n border-right-color: rgba(0, 0, 0, 0.25);\n border-left-width: 0;\n}\n.popover.right > .arrow:after {\n bottom: -10px;\n left: 1px;\n content: \" \";\n border-right-color: #fff;\n border-left-width: 0;\n}\n.popover.bottom > .arrow {\n top: -11px;\n left: 50%;\n margin-left: -11px;\n border-top-width: 0;\n border-bottom-color: #999999;\n border-bottom-color: rgba(0, 0, 0, 0.25);\n}\n.popover.bottom > .arrow:after {\n top: 1px;\n margin-left: -10px;\n content: \" \";\n border-top-width: 0;\n border-bottom-color: #fff;\n}\n.popover.left > .arrow {\n top: 50%;\n right: -11px;\n margin-top: -11px;\n border-right-width: 0;\n border-left-color: #999999;\n border-left-color: rgba(0, 0, 0, 0.25);\n}\n.popover.left > .arrow:after {\n right: 1px;\n bottom: -10px;\n content: \" \";\n border-right-width: 0;\n border-left-color: #fff;\n}\n.popover-title {\n padding: 8px 14px;\n margin: 0;\n font-size: 14px;\n background-color: #f7f7f7;\n border-bottom: 1px solid #ebebeb;\n border-radius: 5px 5px 0 0;\n}\n.popover-content {\n padding: 9px 14px;\n}\n.carousel {\n position: relative;\n}\n.carousel-inner {\n position: relative;\n width: 100%;\n overflow: hidden;\n}\n.carousel-inner > .item {\n position: relative;\n display: none;\n -webkit-transition: 0.6s ease-in-out left;\n -o-transition: 0.6s ease-in-out left;\n transition: 0.6s ease-in-out left;\n}\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n line-height: 1;\n}\n@media all and (transform-3d), (-webkit-transform-3d) {\n .carousel-inner > .item {\n -webkit-transition: -webkit-transform 0.6s ease-in-out;\n -moz-transition: -moz-transform 0.6s ease-in-out;\n -o-transition: -o-transform 0.6s ease-in-out;\n transition: transform 0.6s ease-in-out;\n -webkit-backface-visibility: hidden;\n -moz-backface-visibility: hidden;\n backface-visibility: hidden;\n -webkit-perspective: 1000px;\n -moz-perspective: 1000px;\n perspective: 1000px;\n }\n .carousel-inner > .item.next,\n .carousel-inner > .item.active.right {\n -webkit-transform: translate3d(100%, 0, 0);\n transform: translate3d(100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.prev,\n .carousel-inner > .item.active.left {\n -webkit-transform: translate3d(-100%, 0, 0);\n transform: translate3d(-100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.next.left,\n .carousel-inner > .item.prev.right,\n .carousel-inner > .item.active {\n -webkit-transform: translate3d(0, 0, 0);\n transform: translate3d(0, 0, 0);\n left: 0;\n }\n}\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n display: block;\n}\n.carousel-inner > .active {\n left: 0;\n}\n.carousel-inner > .next,\n.carousel-inner > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n}\n.carousel-inner > .next {\n left: 100%;\n}\n.carousel-inner > .prev {\n left: -100%;\n}\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n left: 0;\n}\n.carousel-inner > .active.left {\n left: -100%;\n}\n.carousel-inner > .active.right {\n left: 100%;\n}\n.carousel-control {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 15%;\n font-size: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n background-color: rgba(0, 0, 0, 0);\n filter: alpha(opacity=50);\n opacity: 0.5;\n}\n.carousel-control.left {\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n background-repeat: repeat-x;\n}\n.carousel-control.right {\n right: 0;\n left: auto;\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n background-repeat: repeat-x;\n}\n.carousel-control:hover,\n.carousel-control:focus {\n color: #fff;\n text-decoration: none;\n outline: 0;\n filter: alpha(opacity=90);\n opacity: 0.9;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-left,\n.carousel-control .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n z-index: 5;\n display: inline-block;\n margin-top: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .glyphicon-chevron-left {\n left: 50%;\n margin-left: -10px;\n}\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-right {\n right: 50%;\n margin-right: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n width: 20px;\n height: 20px;\n font-family: serif;\n line-height: 1;\n}\n.carousel-control .icon-prev:before {\n content: \"\\2039\";\n}\n.carousel-control .icon-next:before {\n content: \"\\203a\";\n}\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n padding-left: 0;\n margin-left: -30%;\n text-align: center;\n list-style: none;\n}\n.carousel-indicators li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n cursor: pointer;\n background-color: #000 \\9;\n background-color: rgba(0, 0, 0, 0);\n border: 1px solid #fff;\n border-radius: 10px;\n}\n.carousel-indicators .active {\n width: 12px;\n height: 12px;\n margin: 0;\n background-color: #fff;\n}\n.carousel-caption {\n position: absolute;\n right: 15%;\n bottom: 20px;\n left: 15%;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n}\n.carousel-caption .btn {\n text-shadow: none;\n}\n@media screen and (min-width: 768px) {\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-prev,\n .carousel-control .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -10px;\n font-size: 30px;\n }\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .icon-prev {\n margin-left: -10px;\n }\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-next {\n margin-right: -10px;\n }\n .carousel-caption {\n right: 20%;\n left: 20%;\n padding-bottom: 30px;\n }\n .carousel-indicators {\n bottom: 20px;\n }\n}\n.clearfix:before,\n.clearfix:after,\n.dl-horizontal dd:before,\n.dl-horizontal dd:after,\n.container:before,\n.container:after,\n.container-fluid:before,\n.container-fluid:after,\n.row:before,\n.row:after,\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after,\n.btn-toolbar:before,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after,\n.nav:before,\n.nav:after,\n.navbar:before,\n.navbar:after,\n.navbar-header:before,\n.navbar-header:after,\n.navbar-collapse:before,\n.navbar-collapse:after,\n.pager:before,\n.pager:after,\n.panel-body:before,\n.panel-body:after,\n.modal-header:before,\n.modal-header:after,\n.modal-footer:before,\n.modal-footer:after {\n display: table;\n content: \" \";\n}\n.clearfix:after,\n.dl-horizontal dd:after,\n.container:after,\n.container-fluid:after,\n.row:after,\n.form-horizontal .form-group:after,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:after,\n.nav:after,\n.navbar:after,\n.navbar-header:after,\n.navbar-collapse:after,\n.pager:after,\n.panel-body:after,\n.modal-header:after,\n.modal-footer:after {\n clear: both;\n}\n.center-block {\n display: block;\n margin-right: auto;\n margin-left: auto;\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n.hidden {\n display: none !important;\n}\n.affix {\n position: fixed;\n}\n@-ms-viewport {\n width: device-width;\n}\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n display: none !important;\n}\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n display: none !important;\n}\n@media (max-width: 767px) {\n .visible-xs {\n display: block !important;\n }\n table.visible-xs {\n display: table !important;\n }\n tr.visible-xs {\n display: table-row !important;\n }\n th.visible-xs,\n td.visible-xs {\n display: table-cell !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-block {\n display: block !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline {\n display: inline !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm {\n display: block !important;\n }\n table.visible-sm {\n display: table !important;\n }\n tr.visible-sm {\n display: table-row !important;\n }\n th.visible-sm,\n td.visible-sm {\n display: table-cell !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-block {\n display: block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline {\n display: inline !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md {\n display: block !important;\n }\n table.visible-md {\n display: table !important;\n }\n tr.visible-md {\n display: table-row !important;\n }\n th.visible-md,\n td.visible-md {\n display: table-cell !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-block {\n display: block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline {\n display: inline !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg {\n display: block !important;\n }\n table.visible-lg {\n display: table !important;\n }\n tr.visible-lg {\n display: table-row !important;\n }\n th.visible-lg,\n td.visible-lg {\n display: table-cell !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-block {\n display: block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline {\n display: inline !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline-block {\n display: inline-block !important;\n }\n}\n@media (max-width: 767px) {\n .hidden-xs {\n display: none !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .hidden-sm {\n display: none !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .hidden-md {\n display: none !important;\n }\n}\n@media (min-width: 1200px) {\n .hidden-lg {\n display: none !important;\n }\n}\n.visible-print {\n display: none !important;\n}\n@media print {\n .visible-print {\n display: block !important;\n }\n table.visible-print {\n display: table !important;\n }\n tr.visible-print {\n display: table-row !important;\n }\n th.visible-print,\n td.visible-print {\n display: table-cell !important;\n }\n}\n.visible-print-block {\n display: none !important;\n}\n@media print {\n .visible-print-block {\n display: block !important;\n }\n}\n.visible-print-inline {\n display: none !important;\n}\n@media print {\n .visible-print-inline {\n display: inline !important;\n }\n}\n.visible-print-inline-block {\n display: none !important;\n}\n@media print {\n .visible-print-inline-block {\n display: inline-block !important;\n }\n}\n@media print {\n .hidden-print {\n display: none !important;\n }\n}\n/*# sourceMappingURL=bootstrap.css.map */","// stylelint-disable\n\n/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\n\n//\n// 1. Set default font family to sans-serif.\n// 2. Prevent iOS and IE text size adjust after device orientation change,\n// without disabling user zoom.\n//\n\nhtml {\n font-family: sans-serif; // 1\n -ms-text-size-adjust: 100%; // 2\n -webkit-text-size-adjust: 100%; // 2\n}\n\n//\n// Remove default margin.\n//\n\nbody {\n margin: 0;\n}\n\n// HTML5 display definitions\n// ==========================================================================\n\n//\n// Correct `block` display not defined for any HTML5 element in IE 8/9.\n// Correct `block` display not defined for `details` or `summary` in IE 10/11\n// and Firefox.\n// Correct `block` display not defined for `main` in IE 11.\n//\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\n\n//\n// 1. Correct `inline-block` display not defined in IE 8/9.\n// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n//\n\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block; // 1\n vertical-align: baseline; // 2\n}\n\n//\n// Prevent modern browsers from displaying `audio` without controls.\n// Remove excess height in iOS 5 devices.\n//\n\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n\n//\n// Address `[hidden]` styling not present in IE 8/9/10.\n// Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.\n//\n\n[hidden],\ntemplate {\n display: none;\n}\n\n// Links\n// ==========================================================================\n\n//\n// Remove the gray background color from active links in IE 10.\n//\n\na {\n background-color: transparent;\n}\n\n//\n// Improve readability of focused elements when they are also in an\n// active/hover state.\n//\n\na:active,\na:hover {\n outline: 0;\n}\n\n// Text-level semantics\n// ==========================================================================\n\n//\n// 1. Remove the bottom border in Chrome 57- and Firefox 39-.\n// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n//\n\nabbr[title] {\n border-bottom: none; // 1\n text-decoration: underline; // 2\n text-decoration: underline dotted; // 2\n}\n\n//\n// Address style set to `bolder` in Firefox 4+, Safari, and Chrome.\n//\n\nb,\nstrong {\n font-weight: bold;\n}\n\n//\n// Address styling not present in Safari and Chrome.\n//\n\ndfn {\n font-style: italic;\n}\n\n//\n// Address variable `h1` font-size and margin within `section` and `article`\n// contexts in Firefox 4+, Safari, and Chrome.\n//\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n//\n// Address styling not present in IE 8/9.\n//\n\nmark {\n background: #ff0;\n color: #000;\n}\n\n//\n// Address inconsistent and variable font size in all browsers.\n//\n\nsmall {\n font-size: 80%;\n}\n\n//\n// Prevent `sub` and `sup` affecting `line-height` in all browsers.\n//\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsup {\n top: -0.5em;\n}\n\nsub {\n bottom: -0.25em;\n}\n\n// Embedded content\n// ==========================================================================\n\n//\n// Remove border when inside `a` element in IE 8/9/10.\n//\n\nimg {\n border: 0;\n}\n\n//\n// Correct overflow not hidden in IE 9/10/11.\n//\n\nsvg:not(:root) {\n overflow: hidden;\n}\n\n// Grouping content\n// ==========================================================================\n\n//\n// Address margin not present in IE 8/9 and Safari.\n//\n\nfigure {\n margin: 1em 40px;\n}\n\n//\n// Address differences between Firefox and other browsers.\n//\n\nhr {\n box-sizing: content-box;\n height: 0;\n}\n\n//\n// Contain overflow in all browsers.\n//\n\npre {\n overflow: auto;\n}\n\n//\n// Address odd `em`-unit font size rendering in all browsers.\n//\n\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\n\n// Forms\n// ==========================================================================\n\n//\n// Known limitation: by default, Chrome and Safari on OS X allow very limited\n// styling of `select`, unless a `border` property is set.\n//\n\n//\n// 1. Correct color not being inherited.\n// Known issue: affects color of disabled elements.\n// 2. Correct font properties not being inherited.\n// 3. Address margins set differently in Firefox 4+, Safari, and Chrome.\n//\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit; // 1\n font: inherit; // 2\n margin: 0; // 3\n}\n\n//\n// Address `overflow` set to `hidden` in IE 8/9/10/11.\n//\n\nbutton {\n overflow: visible;\n}\n\n//\n// Address inconsistent `text-transform` inheritance for `button` and `select`.\n// All other form control elements do not inherit `text-transform` values.\n// Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n// Correct `select` style inheritance in Firefox.\n//\n\nbutton,\nselect {\n text-transform: none;\n}\n\n//\n// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n// and `video` controls.\n// 2. Correct inability to style clickable `input` types in iOS.\n// 3. Improve usability and consistency of cursor style between image-type\n// `input` and others.\n//\n\nbutton,\nhtml input[type=\"button\"], // 1\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button; // 2\n cursor: pointer; // 3\n}\n\n//\n// Re-set default cursor for disabled elements.\n//\n\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\n\n//\n// Remove inner padding and border in Firefox 4+.\n//\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\n\n//\n// Address Firefox 4+ setting `line-height` on `input` using `!important` in\n// the UA stylesheet.\n//\n\ninput {\n line-height: normal;\n}\n\n//\n// It's recommended that you don't attempt to style these elements.\n// Firefox's implementation doesn't respect box-sizing, padding, or width.\n//\n// 1. Address box sizing set to `content-box` in IE 8/9/10.\n// 2. Remove excess padding in IE 8/9/10.\n//\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box; // 1\n padding: 0; // 2\n}\n\n//\n// Fix the cursor style for Chrome's increment/decrement buttons. For certain\n// `font-size` values of the `input`, it causes the cursor style of the\n// decrement button to change from `default` to `text`.\n//\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n//\n// 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n// 2. Address `box-sizing` set to `border-box` in Safari and Chrome.\n//\n\ninput[type=\"search\"] {\n -webkit-appearance: textfield; // 1\n box-sizing: content-box; //2\n}\n\n//\n// Remove inner padding and search cancel button in Safari and Chrome on OS X.\n// Safari (but not Chrome) clips the cancel button when the search input has\n// padding (and `textfield` appearance).\n//\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// Define consistent border, margin, and padding.\n//\n\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\n\n//\n// 1. Correct `color` not being inherited in IE 8/9/10/11.\n// 2. Remove padding so people aren't caught out if they zero out fieldsets.\n//\n\nlegend {\n border: 0; // 1\n padding: 0; // 2\n}\n\n//\n// Remove default vertical scrollbar in IE 8/9/10/11.\n//\n\ntextarea {\n overflow: auto;\n}\n\n//\n// Don't inherit the `font-weight` (applied by a rule above).\n// NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n//\n\noptgroup {\n font-weight: bold;\n}\n\n// Tables\n// ==========================================================================\n\n//\n// Remove most spacing between table cells.\n//\n\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\n\ntd,\nth {\n padding: 0;\n}\n","// stylelint-disable declaration-no-important, selector-no-qualifying-type\n\n/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n\n// ==========================================================================\n// Print styles.\n// Inlined to avoid the additional HTTP request: h5bp.com/r\n// ==========================================================================\n\n@media print {\n *,\n *:before,\n *:after {\n color: #000 !important; // Black prints faster: h5bp.com/s\n text-shadow: none !important;\n background: transparent !important;\n box-shadow: none !important;\n }\n\n a,\n a:visited {\n text-decoration: underline;\n }\n\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n\n // Don't show links that are fragment identifiers,\n // or use the `javascript:` pseudo protocol\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n\n thead {\n display: table-header-group; // h5bp.com/t\n }\n\n tr,\n img {\n page-break-inside: avoid;\n }\n\n img {\n max-width: 100% !important;\n }\n\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n\n h2,\n h3 {\n page-break-after: avoid;\n }\n\n // Bootstrap specific changes start\n\n // Bootstrap components\n .navbar {\n display: none;\n }\n .btn,\n .dropup > .btn {\n > .caret {\n border-top-color: #000 !important;\n }\n }\n .label {\n border: 1px solid #000;\n }\n\n .table {\n border-collapse: collapse !important;\n\n td,\n th {\n background-color: #fff !important;\n }\n }\n .table-bordered {\n th,\n td {\n border: 1px solid #ddd !important;\n }\n }\n}\n","// stylelint-disable value-list-comma-newline-after, value-list-comma-space-after, indentation, declaration-colon-newline-after, font-family-no-missing-generic-family-keyword\n\n//\n// Glyphicons for Bootstrap\n//\n// Since icons are fonts, they can be placed anywhere text is placed and are\n// thus automatically sized to match the surrounding child. To use, create an\n// inline element with the appropriate classes, like so:\n//\n// Star\n\n// Import the fonts\n@font-face {\n font-family: \"Glyphicons Halflings\";\n src: url(\"@{icon-font-path}@{icon-font-name}.eot\");\n src: url(\"@{icon-font-path}@{icon-font-name}.eot?#iefix\") format(\"embedded-opentype\"),\n url(\"@{icon-font-path}@{icon-font-name}.woff2\") format(\"woff2\"),\n url(\"@{icon-font-path}@{icon-font-name}.woff\") format(\"woff\"),\n url(\"@{icon-font-path}@{icon-font-name}.ttf\") format(\"truetype\"),\n url(\"@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}\") format(\"svg\");\n}\n\n// Catchall baseclass\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: \"Glyphicons Halflings\";\n font-style: normal;\n font-weight: 400;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n// Individual icons\n.glyphicon-asterisk { &:before { content: \"\\002a\"; } }\n.glyphicon-plus { &:before { content: \"\\002b\"; } }\n.glyphicon-euro,\n.glyphicon-eur { &:before { content: \"\\20ac\"; } }\n.glyphicon-minus { &:before { content: \"\\2212\"; } }\n.glyphicon-cloud { &:before { content: \"\\2601\"; } }\n.glyphicon-envelope { &:before { content: \"\\2709\"; } }\n.glyphicon-pencil { &:before { content: \"\\270f\"; } }\n.glyphicon-glass { &:before { content: \"\\e001\"; } }\n.glyphicon-music { &:before { content: \"\\e002\"; } }\n.glyphicon-search { &:before { content: \"\\e003\"; } }\n.glyphicon-heart { &:before { content: \"\\e005\"; } }\n.glyphicon-star { &:before { content: \"\\e006\"; } }\n.glyphicon-star-empty { &:before { content: \"\\e007\"; } }\n.glyphicon-user { &:before { content: \"\\e008\"; } }\n.glyphicon-film { &:before { content: \"\\e009\"; } }\n.glyphicon-th-large { &:before { content: \"\\e010\"; } }\n.glyphicon-th { &:before { content: \"\\e011\"; } }\n.glyphicon-th-list { &:before { content: \"\\e012\"; } }\n.glyphicon-ok { &:before { content: \"\\e013\"; } }\n.glyphicon-remove { &:before { content: \"\\e014\"; } }\n.glyphicon-zoom-in { &:before { content: \"\\e015\"; } }\n.glyphicon-zoom-out { &:before { content: \"\\e016\"; } }\n.glyphicon-off { &:before { content: \"\\e017\"; } }\n.glyphicon-signal { &:before { content: \"\\e018\"; } }\n.glyphicon-cog { &:before { content: \"\\e019\"; } }\n.glyphicon-trash { &:before { content: \"\\e020\"; } }\n.glyphicon-home { &:before { content: \"\\e021\"; } }\n.glyphicon-file { &:before { content: \"\\e022\"; } }\n.glyphicon-time { &:before { content: \"\\e023\"; } }\n.glyphicon-road { &:before { content: \"\\e024\"; } }\n.glyphicon-download-alt { &:before { content: \"\\e025\"; } }\n.glyphicon-download { &:before { content: \"\\e026\"; } }\n.glyphicon-upload { &:before { content: \"\\e027\"; } }\n.glyphicon-inbox { &:before { content: \"\\e028\"; } }\n.glyphicon-play-circle { &:before { content: \"\\e029\"; } }\n.glyphicon-repeat { &:before { content: \"\\e030\"; } }\n.glyphicon-refresh { &:before { content: \"\\e031\"; } }\n.glyphicon-list-alt { &:before { content: \"\\e032\"; } }\n.glyphicon-lock { &:before { content: \"\\e033\"; } }\n.glyphicon-flag { &:before { content: \"\\e034\"; } }\n.glyphicon-headphones { &:before { content: \"\\e035\"; } }\n.glyphicon-volume-off { &:before { content: \"\\e036\"; } }\n.glyphicon-volume-down { &:before { content: \"\\e037\"; } }\n.glyphicon-volume-up { &:before { content: \"\\e038\"; } }\n.glyphicon-qrcode { &:before { content: \"\\e039\"; } }\n.glyphicon-barcode { &:before { content: \"\\e040\"; } }\n.glyphicon-tag { &:before { content: \"\\e041\"; } }\n.glyphicon-tags { &:before { content: \"\\e042\"; } }\n.glyphicon-book { &:before { content: \"\\e043\"; } }\n.glyphicon-bookmark { &:before { content: \"\\e044\"; } }\n.glyphicon-print { &:before { content: \"\\e045\"; } }\n.glyphicon-camera { &:before { content: \"\\e046\"; } }\n.glyphicon-font { &:before { content: \"\\e047\"; } }\n.glyphicon-bold { &:before { content: \"\\e048\"; } }\n.glyphicon-italic { &:before { content: \"\\e049\"; } }\n.glyphicon-text-height { &:before { content: \"\\e050\"; } }\n.glyphicon-text-width { &:before { content: \"\\e051\"; } }\n.glyphicon-align-left { &:before { content: \"\\e052\"; } }\n.glyphicon-align-center { &:before { content: \"\\e053\"; } }\n.glyphicon-align-right { &:before { content: \"\\e054\"; } }\n.glyphicon-align-justify { &:before { content: \"\\e055\"; } }\n.glyphicon-list { &:before { content: \"\\e056\"; } }\n.glyphicon-indent-left { &:before { content: \"\\e057\"; } }\n.glyphicon-indent-right { &:before { content: \"\\e058\"; } }\n.glyphicon-facetime-video { &:before { content: \"\\e059\"; } }\n.glyphicon-picture { &:before { content: \"\\e060\"; } }\n.glyphicon-map-marker { &:before { content: \"\\e062\"; } }\n.glyphicon-adjust { &:before { content: \"\\e063\"; } }\n.glyphicon-tint { &:before { content: \"\\e064\"; } }\n.glyphicon-edit { &:before { content: \"\\e065\"; } }\n.glyphicon-share { &:before { content: \"\\e066\"; } }\n.glyphicon-check { &:before { content: \"\\e067\"; } }\n.glyphicon-move { &:before { content: \"\\e068\"; } }\n.glyphicon-step-backward { &:before { content: \"\\e069\"; } }\n.glyphicon-fast-backward { &:before { content: \"\\e070\"; } }\n.glyphicon-backward { &:before { content: \"\\e071\"; } }\n.glyphicon-play { &:before { content: \"\\e072\"; } }\n.glyphicon-pause { &:before { content: \"\\e073\"; } }\n.glyphicon-stop { &:before { content: \"\\e074\"; } }\n.glyphicon-forward { &:before { content: \"\\e075\"; } }\n.glyphicon-fast-forward { &:before { content: \"\\e076\"; } }\n.glyphicon-step-forward { &:before { content: \"\\e077\"; } }\n.glyphicon-eject { &:before { content: \"\\e078\"; } }\n.glyphicon-chevron-left { &:before { content: \"\\e079\"; } }\n.glyphicon-chevron-right { &:before { content: \"\\e080\"; } }\n.glyphicon-plus-sign { &:before { content: \"\\e081\"; } }\n.glyphicon-minus-sign { &:before { content: \"\\e082\"; } }\n.glyphicon-remove-sign { &:before { content: \"\\e083\"; } }\n.glyphicon-ok-sign { &:before { content: \"\\e084\"; } }\n.glyphicon-question-sign { &:before { content: \"\\e085\"; } }\n.glyphicon-info-sign { &:before { content: \"\\e086\"; } }\n.glyphicon-screenshot { &:before { content: \"\\e087\"; } }\n.glyphicon-remove-circle { &:before { content: \"\\e088\"; } }\n.glyphicon-ok-circle { &:before { content: \"\\e089\"; } }\n.glyphicon-ban-circle { &:before { content: \"\\e090\"; } }\n.glyphicon-arrow-left { &:before { content: \"\\e091\"; } }\n.glyphicon-arrow-right { &:before { content: \"\\e092\"; } }\n.glyphicon-arrow-up { &:before { content: \"\\e093\"; } }\n.glyphicon-arrow-down { &:before { content: \"\\e094\"; } }\n.glyphicon-share-alt { &:before { content: \"\\e095\"; } }\n.glyphicon-resize-full { &:before { content: \"\\e096\"; } }\n.glyphicon-resize-small { &:before { content: \"\\e097\"; } }\n.glyphicon-exclamation-sign { &:before { content: \"\\e101\"; } }\n.glyphicon-gift { &:before { content: \"\\e102\"; } }\n.glyphicon-leaf { &:before { content: \"\\e103\"; } }\n.glyphicon-fire { &:before { content: \"\\e104\"; } }\n.glyphicon-eye-open { &:before { content: \"\\e105\"; } }\n.glyphicon-eye-close { &:before { content: \"\\e106\"; } }\n.glyphicon-warning-sign { &:before { content: \"\\e107\"; } }\n.glyphicon-plane { &:before { content: \"\\e108\"; } }\n.glyphicon-calendar { &:before { content: \"\\e109\"; } }\n.glyphicon-random { &:before { content: \"\\e110\"; } }\n.glyphicon-comment { &:before { content: \"\\e111\"; } }\n.glyphicon-magnet { &:before { content: \"\\e112\"; } }\n.glyphicon-chevron-up { &:before { content: \"\\e113\"; } }\n.glyphicon-chevron-down { &:before { content: \"\\e114\"; } }\n.glyphicon-retweet { &:before { content: \"\\e115\"; } }\n.glyphicon-shopping-cart { &:before { content: \"\\e116\"; } }\n.glyphicon-folder-close { &:before { content: \"\\e117\"; } }\n.glyphicon-folder-open { &:before { content: \"\\e118\"; } }\n.glyphicon-resize-vertical { &:before { content: \"\\e119\"; } }\n.glyphicon-resize-horizontal { &:before { content: \"\\e120\"; } }\n.glyphicon-hdd { &:before { content: \"\\e121\"; } }\n.glyphicon-bullhorn { &:before { content: \"\\e122\"; } }\n.glyphicon-bell { &:before { content: \"\\e123\"; } }\n.glyphicon-certificate { &:before { content: \"\\e124\"; } }\n.glyphicon-thumbs-up { &:before { content: \"\\e125\"; } }\n.glyphicon-thumbs-down { &:before { content: \"\\e126\"; } }\n.glyphicon-hand-right { &:before { content: \"\\e127\"; } }\n.glyphicon-hand-left { &:before { content: \"\\e128\"; } }\n.glyphicon-hand-up { &:before { content: \"\\e129\"; } }\n.glyphicon-hand-down { &:before { content: \"\\e130\"; } }\n.glyphicon-circle-arrow-right { &:before { content: \"\\e131\"; } }\n.glyphicon-circle-arrow-left { &:before { content: \"\\e132\"; } }\n.glyphicon-circle-arrow-up { &:before { content: \"\\e133\"; } }\n.glyphicon-circle-arrow-down { &:before { content: \"\\e134\"; } }\n.glyphicon-globe { &:before { content: \"\\e135\"; } }\n.glyphicon-wrench { &:before { content: \"\\e136\"; } }\n.glyphicon-tasks { &:before { content: \"\\e137\"; } }\n.glyphicon-filter { &:before { content: \"\\e138\"; } }\n.glyphicon-briefcase { &:before { content: \"\\e139\"; } }\n.glyphicon-fullscreen { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard { &:before { content: \"\\e141\"; } }\n.glyphicon-paperclip { &:before { content: \"\\e142\"; } }\n.glyphicon-heart-empty { &:before { content: \"\\e143\"; } }\n.glyphicon-link { &:before { content: \"\\e144\"; } }\n.glyphicon-phone { &:before { content: \"\\e145\"; } }\n.glyphicon-pushpin { &:before { content: \"\\e146\"; } }\n.glyphicon-usd { &:before { content: \"\\e148\"; } }\n.glyphicon-gbp { &:before { content: \"\\e149\"; } }\n.glyphicon-sort { &:before { content: \"\\e150\"; } }\n.glyphicon-sort-by-alphabet { &:before { content: \"\\e151\"; } }\n.glyphicon-sort-by-alphabet-alt { &:before { content: \"\\e152\"; } }\n.glyphicon-sort-by-order { &:before { content: \"\\e153\"; } }\n.glyphicon-sort-by-order-alt { &:before { content: \"\\e154\"; } }\n.glyphicon-sort-by-attributes { &:before { content: \"\\e155\"; } }\n.glyphicon-sort-by-attributes-alt { &:before { content: \"\\e156\"; } }\n.glyphicon-unchecked { &:before { content: \"\\e157\"; } }\n.glyphicon-expand { &:before { content: \"\\e158\"; } }\n.glyphicon-collapse-down { &:before { content: \"\\e159\"; } }\n.glyphicon-collapse-up { &:before { content: \"\\e160\"; } }\n.glyphicon-log-in { &:before { content: \"\\e161\"; } }\n.glyphicon-flash { &:before { content: \"\\e162\"; } }\n.glyphicon-log-out { &:before { content: \"\\e163\"; } }\n.glyphicon-new-window { &:before { content: \"\\e164\"; } }\n.glyphicon-record { &:before { content: \"\\e165\"; } }\n.glyphicon-save { &:before { content: \"\\e166\"; } }\n.glyphicon-open { &:before { content: \"\\e167\"; } }\n.glyphicon-saved { &:before { content: \"\\e168\"; } }\n.glyphicon-import { &:before { content: \"\\e169\"; } }\n.glyphicon-export { &:before { content: \"\\e170\"; } }\n.glyphicon-send { &:before { content: \"\\e171\"; } }\n.glyphicon-floppy-disk { &:before { content: \"\\e172\"; } }\n.glyphicon-floppy-saved { &:before { content: \"\\e173\"; } }\n.glyphicon-floppy-remove { &:before { content: \"\\e174\"; } }\n.glyphicon-floppy-save { &:before { content: \"\\e175\"; } }\n.glyphicon-floppy-open { &:before { content: \"\\e176\"; } }\n.glyphicon-credit-card { &:before { content: \"\\e177\"; } }\n.glyphicon-transfer { &:before { content: \"\\e178\"; } }\n.glyphicon-cutlery { &:before { content: \"\\e179\"; } }\n.glyphicon-header { &:before { content: \"\\e180\"; } }\n.glyphicon-compressed { &:before { content: \"\\e181\"; } }\n.glyphicon-earphone { &:before { content: \"\\e182\"; } }\n.glyphicon-phone-alt { &:before { content: \"\\e183\"; } }\n.glyphicon-tower { &:before { content: \"\\e184\"; } }\n.glyphicon-stats { &:before { content: \"\\e185\"; } }\n.glyphicon-sd-video { &:before { content: \"\\e186\"; } }\n.glyphicon-hd-video { &:before { content: \"\\e187\"; } }\n.glyphicon-subtitles { &:before { content: \"\\e188\"; } }\n.glyphicon-sound-stereo { &:before { content: \"\\e189\"; } }\n.glyphicon-sound-dolby { &:before { content: \"\\e190\"; } }\n.glyphicon-sound-5-1 { &:before { content: \"\\e191\"; } }\n.glyphicon-sound-6-1 { &:before { content: \"\\e192\"; } }\n.glyphicon-sound-7-1 { &:before { content: \"\\e193\"; } }\n.glyphicon-copyright-mark { &:before { content: \"\\e194\"; } }\n.glyphicon-registration-mark { &:before { content: \"\\e195\"; } }\n.glyphicon-cloud-download { &:before { content: \"\\e197\"; } }\n.glyphicon-cloud-upload { &:before { content: \"\\e198\"; } }\n.glyphicon-tree-conifer { &:before { content: \"\\e199\"; } }\n.glyphicon-tree-deciduous { &:before { content: \"\\e200\"; } }\n.glyphicon-cd { &:before { content: \"\\e201\"; } }\n.glyphicon-save-file { &:before { content: \"\\e202\"; } }\n.glyphicon-open-file { &:before { content: \"\\e203\"; } }\n.glyphicon-level-up { &:before { content: \"\\e204\"; } }\n.glyphicon-copy { &:before { content: \"\\e205\"; } }\n.glyphicon-paste { &:before { content: \"\\e206\"; } }\n// The following 2 Glyphicons are omitted for the time being because\n// they currently use Unicode codepoints that are outside the\n// Basic Multilingual Plane (BMP). Older buggy versions of WebKit can't handle\n// non-BMP codepoints in CSS string escapes, and thus can't display these two icons.\n// Notably, the bug affects some older versions of the Android Browser.\n// More info: https://github.com/twbs/bootstrap/issues/10106\n// .glyphicon-door { &:before { content: \"\\1f6aa\"; } }\n// .glyphicon-key { &:before { content: \"\\1f511\"; } }\n.glyphicon-alert { &:before { content: \"\\e209\"; } }\n.glyphicon-equalizer { &:before { content: \"\\e210\"; } }\n.glyphicon-king { &:before { content: \"\\e211\"; } }\n.glyphicon-queen { &:before { content: \"\\e212\"; } }\n.glyphicon-pawn { &:before { content: \"\\e213\"; } }\n.glyphicon-bishop { &:before { content: \"\\e214\"; } }\n.glyphicon-knight { &:before { content: \"\\e215\"; } }\n.glyphicon-baby-formula { &:before { content: \"\\e216\"; } }\n.glyphicon-tent { &:before { content: \"\\26fa\"; } }\n.glyphicon-blackboard { &:before { content: \"\\e218\"; } }\n.glyphicon-bed { &:before { content: \"\\e219\"; } }\n.glyphicon-apple { &:before { content: \"\\f8ff\"; } }\n.glyphicon-erase { &:before { content: \"\\e221\"; } }\n.glyphicon-hourglass { &:before { content: \"\\231b\"; } }\n.glyphicon-lamp { &:before { content: \"\\e223\"; } }\n.glyphicon-duplicate { &:before { content: \"\\e224\"; } }\n.glyphicon-piggy-bank { &:before { content: \"\\e225\"; } }\n.glyphicon-scissors { &:before { content: \"\\e226\"; } }\n.glyphicon-bitcoin { &:before { content: \"\\e227\"; } }\n.glyphicon-btc { &:before { content: \"\\e227\"; } }\n.glyphicon-xbt { &:before { content: \"\\e227\"; } }\n.glyphicon-yen { &:before { content: \"\\00a5\"; } }\n.glyphicon-jpy { &:before { content: \"\\00a5\"; } }\n.glyphicon-ruble { &:before { content: \"\\20bd\"; } }\n.glyphicon-rub { &:before { content: \"\\20bd\"; } }\n.glyphicon-scale { &:before { content: \"\\e230\"; } }\n.glyphicon-ice-lolly { &:before { content: \"\\e231\"; } }\n.glyphicon-ice-lolly-tasted { &:before { content: \"\\e232\"; } }\n.glyphicon-education { &:before { content: \"\\e233\"; } }\n.glyphicon-option-horizontal { &:before { content: \"\\e234\"; } }\n.glyphicon-option-vertical { &:before { content: \"\\e235\"; } }\n.glyphicon-menu-hamburger { &:before { content: \"\\e236\"; } }\n.glyphicon-modal-window { &:before { content: \"\\e237\"; } }\n.glyphicon-oil { &:before { content: \"\\e238\"; } }\n.glyphicon-grain { &:before { content: \"\\e239\"; } }\n.glyphicon-sunglasses { &:before { content: \"\\e240\"; } }\n.glyphicon-text-size { &:before { content: \"\\e241\"; } }\n.glyphicon-text-color { &:before { content: \"\\e242\"; } }\n.glyphicon-text-background { &:before { content: \"\\e243\"; } }\n.glyphicon-object-align-top { &:before { content: \"\\e244\"; } }\n.glyphicon-object-align-bottom { &:before { content: \"\\e245\"; } }\n.glyphicon-object-align-horizontal{ &:before { content: \"\\e246\"; } }\n.glyphicon-object-align-left { &:before { content: \"\\e247\"; } }\n.glyphicon-object-align-vertical { &:before { content: \"\\e248\"; } }\n.glyphicon-object-align-right { &:before { content: \"\\e249\"; } }\n.glyphicon-triangle-right { &:before { content: \"\\e250\"; } }\n.glyphicon-triangle-left { &:before { content: \"\\e251\"; } }\n.glyphicon-triangle-bottom { &:before { content: \"\\e252\"; } }\n.glyphicon-triangle-top { &:before { content: \"\\e253\"; } }\n.glyphicon-console { &:before { content: \"\\e254\"; } }\n.glyphicon-superscript { &:before { content: \"\\e255\"; } }\n.glyphicon-subscript { &:before { content: \"\\e256\"; } }\n.glyphicon-menu-left { &:before { content: \"\\e257\"; } }\n.glyphicon-menu-right { &:before { content: \"\\e258\"; } }\n.glyphicon-menu-down { &:before { content: \"\\e259\"; } }\n.glyphicon-menu-up { &:before { content: \"\\e260\"; } }\n","//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Reset the box-sizing\n//\n// Heads up! This reset may cause conflicts with some third-party widgets.\n// For recommendations on resolving such conflicts, see\n// https://getbootstrap.com/docs/3.4/getting-started/#third-box-sizing\n* {\n .box-sizing(border-box);\n}\n*:before,\n*:after {\n .box-sizing(border-box);\n}\n\n\n// Body reset\n\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\nbody {\n font-family: @font-family-base;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @text-color;\n background-color: @body-bg;\n}\n\n// Reset fonts for relevant elements\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\n\n// Links\n\na {\n color: @link-color;\n text-decoration: none;\n\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n }\n\n &:focus {\n .tab-focus();\n }\n}\n\n\n// Figures\n//\n// We reset this here because previously Normalize had no `figure` margins. This\n// ensures we don't break anyone's use of the element.\n\nfigure {\n margin: 0;\n}\n\n\n// Images\n\nimg {\n vertical-align: middle;\n}\n\n// Responsive images (ensure images don't scale beyond their parents)\n.img-responsive {\n .img-responsive();\n}\n\n// Rounded corners\n.img-rounded {\n border-radius: @border-radius-large;\n}\n\n// Image thumbnails\n//\n// Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.\n.img-thumbnail {\n padding: @thumbnail-padding;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(all .2s ease-in-out);\n\n // Keep them at most 100% wide\n .img-responsive(inline-block);\n}\n\n// Perfect circle\n.img-circle {\n border-radius: 50%; // set radius in percents\n}\n\n\n// Horizontal rules\n\nhr {\n margin-top: @line-height-computed;\n margin-bottom: @line-height-computed;\n border: 0;\n border-top: 1px solid @hr-border;\n}\n\n\n// Only display content to screen readers\n//\n// See: https://a11yproject.com/posts/how-to-hide-content\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n\n// Use in conjunction with .sr-only to only display content when it's focused.\n// Useful for \"Skip to main content\" links; see https://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1\n// Credit: HTML5 Boilerplate\n\n.sr-only-focusable {\n &:active,\n &:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n }\n}\n\n\n// iOS \"clickable elements\" fix for role=\"button\"\n//\n// Fixes \"clickability\" issue (and more generally, the firing of events such as focus as well)\n// for traditionally non-focusable elements with role=\"button\"\n// see https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile\n\n[role=\"button\"] {\n cursor: pointer;\n}\n","// stylelint-disable indentation, property-no-vendor-prefix, selector-no-vendor-prefix\n\n// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They have been removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility) {\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n word-wrap: break-word;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// WebKit-style focus\n\n.tab-focus() {\n // WebKit-specific. Other browsers will keep their default outline style.\n // (Initially tried to also force default via `outline: initial`,\n // but that seems to erroneously remove the outline in Firefox altogether.)\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n","// stylelint-disable media-feature-name-no-vendor-prefix, media-feature-parentheses-space-inside, media-feature-name-no-unknown, indentation, at-rule-name-space-after\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n.img-responsive(@display: block) {\n display: @display;\n max-width: 100%; // Part 1: Set a maximum relative to the parent\n height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching\n}\n\n\n// Retina image\n//\n// Short retina mixin for setting background-image and -size. Note that the\n// spelling of `min--moz-device-pixel-ratio` is intentional.\n.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {\n background-image: url(\"@{file-1x}\");\n\n @media\n only screen and (-webkit-min-device-pixel-ratio: 2),\n only screen and ( min--moz-device-pixel-ratio: 2),\n only screen and ( -o-min-device-pixel-ratio: 2/1),\n only screen and ( min-device-pixel-ratio: 2),\n only screen and ( min-resolution: 192dpi),\n only screen and ( min-resolution: 2dppx) {\n background-image: url(\"@{file-2x}\");\n background-size: @width-1x @height-1x;\n }\n}\n","// stylelint-disable selector-list-comma-newline-after, selector-no-qualifying-type\n\n//\n// Typography\n// --------------------------------------------------\n\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n font-family: @headings-font-family;\n font-weight: @headings-font-weight;\n line-height: @headings-line-height;\n color: @headings-color;\n\n small,\n .small {\n font-weight: 400;\n line-height: 1;\n color: @headings-small-color;\n }\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3 {\n margin-top: @line-height-computed;\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 65%;\n }\n}\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n margin-top: (@line-height-computed / 2);\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 75%;\n }\n}\n\nh1, .h1 { font-size: @font-size-h1; }\nh2, .h2 { font-size: @font-size-h2; }\nh3, .h3 { font-size: @font-size-h3; }\nh4, .h4 { font-size: @font-size-h4; }\nh5, .h5 { font-size: @font-size-h5; }\nh6, .h6 { font-size: @font-size-h6; }\n\n\n// Body text\n// -------------------------\n\np {\n margin: 0 0 (@line-height-computed / 2);\n}\n\n.lead {\n margin-bottom: @line-height-computed;\n font-size: floor((@font-size-base * 1.15));\n font-weight: 300;\n line-height: 1.4;\n\n @media (min-width: @screen-sm-min) {\n font-size: (@font-size-base * 1.5);\n }\n}\n\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: (12px small font / 14px base font) * 100% = about 85%\nsmall,\n.small {\n font-size: floor((100% * @font-size-small / @font-size-base));\n}\n\nmark,\n.mark {\n padding: .2em;\n background-color: @state-warning-bg;\n}\n\n// Alignment\n.text-left { text-align: left; }\n.text-right { text-align: right; }\n.text-center { text-align: center; }\n.text-justify { text-align: justify; }\n.text-nowrap { white-space: nowrap; }\n\n// Transformation\n.text-lowercase { text-transform: lowercase; }\n.text-uppercase { text-transform: uppercase; }\n.text-capitalize { text-transform: capitalize; }\n\n// Contextual colors\n.text-muted {\n color: @text-muted;\n}\n.text-primary {\n .text-emphasis-variant(@brand-primary);\n}\n.text-success {\n .text-emphasis-variant(@state-success-text);\n}\n.text-info {\n .text-emphasis-variant(@state-info-text);\n}\n.text-warning {\n .text-emphasis-variant(@state-warning-text);\n}\n.text-danger {\n .text-emphasis-variant(@state-danger-text);\n}\n\n// Contextual backgrounds\n// For now we'll leave these alongside the text classes until v4 when we can\n// safely shift things around (per SemVer rules).\n.bg-primary {\n // Given the contrast here, this is the only class to have its color inverted\n // automatically.\n color: #fff;\n .bg-variant(@brand-primary);\n}\n.bg-success {\n .bg-variant(@state-success-bg);\n}\n.bg-info {\n .bg-variant(@state-info-bg);\n}\n.bg-warning {\n .bg-variant(@state-warning-bg);\n}\n.bg-danger {\n .bg-variant(@state-danger-bg);\n}\n\n\n// Page header\n// -------------------------\n\n.page-header {\n padding-bottom: ((@line-height-computed / 2) - 1);\n margin: (@line-height-computed * 2) 0 @line-height-computed;\n border-bottom: 1px solid @page-header-border-color;\n}\n\n\n// Lists\n// -------------------------\n\n// Unordered and Ordered lists\nul,\nol {\n margin-top: 0;\n margin-bottom: (@line-height-computed / 2);\n ul,\n ol {\n margin-bottom: 0;\n }\n}\n\n// List options\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n .list-unstyled();\n margin-left: -5px;\n\n > li {\n display: inline-block;\n padding-right: 5px;\n padding-left: 5px;\n }\n}\n\n// Description Lists\ndl {\n margin-top: 0; // Remove browser default\n margin-bottom: @line-height-computed;\n}\ndt,\ndd {\n line-height: @line-height-base;\n}\ndt {\n font-weight: 700;\n}\ndd {\n margin-left: 0; // Undo browser default\n}\n\n// Horizontal description lists\n//\n// Defaults to being stacked without any of the below styles applied, until the\n// grid breakpoint is reached (default of ~768px).\n\n.dl-horizontal {\n dd {\n &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present\n }\n\n @media (min-width: @dl-horizontal-breakpoint) {\n dt {\n float: left;\n width: (@dl-horizontal-offset - 20);\n clear: left;\n text-align: right;\n .text-overflow();\n }\n dd {\n margin-left: @dl-horizontal-offset;\n }\n }\n}\n\n\n// Misc\n// -------------------------\n\n// Abbreviations and acronyms\n// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\nabbr[title],\nabbr[data-original-title] {\n cursor: help;\n}\n\n.initialism {\n font-size: 90%;\n .text-uppercase();\n}\n\n// Blockquotes\nblockquote {\n padding: (@line-height-computed / 2) @line-height-computed;\n margin: 0 0 @line-height-computed;\n font-size: @blockquote-font-size;\n border-left: 5px solid @blockquote-border-color;\n\n p,\n ul,\n ol {\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n // Note: Deprecated small and .small as of v3.1.0\n // Context: https://github.com/twbs/bootstrap/issues/11660\n footer,\n small,\n .small {\n display: block;\n font-size: 80%; // back to default font-size\n line-height: @line-height-base;\n color: @blockquote-small-color;\n\n &:before {\n content: \"\\2014 \\00A0\"; // em dash, nbsp\n }\n }\n}\n\n// Opposite alignment of blockquote\n//\n// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n text-align: right;\n border-right: 5px solid @blockquote-border-color;\n border-left: 0;\n\n // Account for citation\n footer,\n small,\n .small {\n &:before { content: \"\"; }\n &:after {\n content: \"\\00A0 \\2014\"; // nbsp, em dash\n }\n }\n}\n\n// Addresses\naddress {\n margin-bottom: @line-height-computed;\n font-style: normal;\n line-height: @line-height-base;\n}\n","// Typography\n\n.text-emphasis-variant(@color) {\n color: @color;\n a&:hover,\n a&:focus {\n color: darken(@color, 10%);\n }\n}\n","// Contextual backgrounds\n\n.bg-variant(@color) {\n background-color: @color;\n a&:hover,\n a&:focus {\n background-color: darken(@color, 10%);\n }\n}\n","// Text overflow\n// Requires inline-block or block for proper styling\n\n.text-overflow() {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n","//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\nkbd,\npre,\nsamp {\n font-family: @font-family-monospace;\n}\n\n// Inline code\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: @code-color;\n background-color: @code-bg;\n border-radius: @border-radius-base;\n}\n\n// User input typically entered via keyboard\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: @kbd-color;\n background-color: @kbd-bg;\n border-radius: @border-radius-small;\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);\n\n kbd {\n padding: 0;\n font-size: 100%;\n font-weight: 700;\n box-shadow: none;\n }\n}\n\n// Blocks of code\npre {\n display: block;\n padding: ((@line-height-computed - 1) / 2);\n margin: 0 0 (@line-height-computed / 2);\n font-size: (@font-size-base - 1); // 14px to 13px\n line-height: @line-height-base;\n color: @pre-color;\n word-break: break-all;\n word-wrap: break-word;\n background-color: @pre-bg;\n border: 1px solid @pre-border-color;\n border-radius: @border-radius-base;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n max-height: @pre-scrollable-max-height;\n overflow-y: scroll;\n}\n","//\n// Grid system\n// --------------------------------------------------\n\n\n// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n.container {\n .container-fixed();\n\n @media (min-width: @screen-sm-min) {\n width: @container-sm;\n }\n @media (min-width: @screen-md-min) {\n width: @container-md;\n }\n @media (min-width: @screen-lg-min) {\n width: @container-lg;\n }\n}\n\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but without any defined\n// width for fluid, full width layouts.\n\n.container-fluid {\n .container-fixed();\n}\n\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n.row {\n .make-row();\n}\n\n.row-no-gutters {\n margin-right: 0;\n margin-left: 0;\n\n [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n }\n}\n\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n.make-grid-columns();\n\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid(xs);\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n .make-grid(sm);\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n .make-grid(md);\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n .make-grid(lg);\n}\n","// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n// Centered container element\n.container-fixed(@gutter: @grid-gutter-width) {\n padding-right: ceil((@gutter / 2));\n padding-left: floor((@gutter / 2));\n margin-right: auto;\n margin-left: auto;\n &:extend(.clearfix all);\n}\n\n// Creates a wrapper for a series of columns\n.make-row(@gutter: @grid-gutter-width) {\n margin-right: floor((@gutter / -2));\n margin-left: ceil((@gutter / -2));\n &:extend(.clearfix all);\n}\n\n// Generate the extra small columns\n.make-xs-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n float: left;\n width: percentage((@columns / @grid-columns));\n min-height: 1px;\n padding-right: (@gutter / 2);\n padding-left: (@gutter / 2);\n}\n.make-xs-column-offset(@columns) {\n margin-left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-push(@columns) {\n left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-pull(@columns) {\n right: percentage((@columns / @grid-columns));\n}\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-right: (@gutter / 2);\n padding-left: (@gutter / 2);\n\n @media (min-width: @screen-sm-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-offset(@columns) {\n @media (min-width: @screen-sm-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-push(@columns) {\n @media (min-width: @screen-sm-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-pull(@columns) {\n @media (min-width: @screen-sm-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-right: (@gutter / 2);\n padding-left: (@gutter / 2);\n\n @media (min-width: @screen-md-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-offset(@columns) {\n @media (min-width: @screen-md-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-push(@columns) {\n @media (min-width: @screen-md-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-pull(@columns) {\n @media (min-width: @screen-md-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-right: (@gutter / 2);\n padding-left: (@gutter / 2);\n\n @media (min-width: @screen-lg-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-offset(@columns) {\n @media (min-width: @screen-lg-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-push(@columns) {\n @media (min-width: @screen-lg-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-pull(@columns) {\n @media (min-width: @screen-lg-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `@grid-columns`.\n\n.make-grid-columns() {\n // Common styles for all sizes of grid columns, widths 1-12\n .col(@index) { // initial\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general; \"=<\" isn't a typo\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n position: relative;\n // Prevent columns from collapsing when empty\n min-height: 1px;\n // Inner gutter via padding\n padding-right: floor((@grid-gutter-width / 2));\n padding-left: ceil((@grid-gutter-width / 2));\n }\n }\n .col(1); // kickstart it\n}\n\n.float-grid-columns(@class) {\n .col(@index) { // initial\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n float: left;\n }\n }\n .col(1); // kickstart it\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {\n .col-@{class}-@{index} {\n width: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index > 0) {\n .col-@{class}-push-@{index} {\n left: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index = 0) {\n .col-@{class}-push-0 {\n left: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index > 0) {\n .col-@{class}-pull-@{index} {\n right: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index = 0) {\n .col-@{class}-pull-0 {\n right: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = offset) {\n .col-@{class}-offset-@{index} {\n margin-left: percentage((@index / @grid-columns));\n }\n}\n\n// Basic looping in LESS\n.loop-grid-columns(@index, @class, @type) when (@index >= 0) {\n .calc-grid-column(@index, @class, @type);\n // next iteration\n .loop-grid-columns((@index - 1), @class, @type);\n}\n\n// Create grid for specific class\n.make-grid(@class) {\n .float-grid-columns(@class);\n .loop-grid-columns(@grid-columns, @class, width);\n .loop-grid-columns(@grid-columns, @class, pull);\n .loop-grid-columns(@grid-columns, @class, push);\n .loop-grid-columns(@grid-columns, @class, offset);\n}\n","// stylelint-disable selector-max-type, selector-max-compound-selectors, selector-no-qualifying-type\n\n//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n background-color: @table-bg;\n\n // Table cell sizing\n //\n // Reset default table behavior\n\n col[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n display: table-column;\n float: none;\n }\n\n td,\n th {\n &[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n display: table-cell;\n float: none;\n }\n }\n}\n\ncaption {\n padding-top: @table-cell-padding;\n padding-bottom: @table-cell-padding;\n color: @text-muted;\n text-align: left;\n}\n\nth {\n text-align: left;\n}\n\n\n// Baseline styles\n\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: @line-height-computed;\n // Cells\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-cell-padding;\n line-height: @line-height-base;\n vertical-align: top;\n border-top: 1px solid @table-border-color;\n }\n }\n }\n // Bottom align for column headings\n > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid @table-border-color;\n }\n // Remove top border from thead by default\n > caption + thead,\n > colgroup + thead,\n > thead:first-child {\n > tr:first-child {\n > th,\n > td {\n border-top: 0;\n }\n }\n }\n // Account for multiple tbody instances\n > tbody + tbody {\n border-top: 2px solid @table-border-color;\n }\n\n // Nesting\n .table {\n background-color: @body-bg;\n }\n}\n\n\n// Condensed table w/ half padding\n\n.table-condensed {\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-condensed-cell-padding;\n }\n }\n }\n}\n\n\n// Bordered version\n//\n// Add borders all around the table and between all the columns.\n\n.table-bordered {\n border: 1px solid @table-border-color;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n border: 1px solid @table-border-color;\n }\n }\n }\n > thead > tr {\n > th,\n > td {\n border-bottom-width: 2px;\n }\n }\n}\n\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n > tbody > tr:nth-of-type(odd) {\n background-color: @table-bg-accent;\n }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n > tbody > tr:hover {\n background-color: @table-bg-hover;\n }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n// Generate the contextual variants\n.table-row-variant(active; @table-bg-active);\n.table-row-variant(success; @state-success-bg);\n.table-row-variant(info; @state-info-bg);\n.table-row-variant(warning; @state-warning-bg);\n.table-row-variant(danger; @state-danger-bg);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-responsive` and we'll make them mobile friendly\n// by enabling horizontal scrolling. Only applies <768px. Everything above that\n// will display normally.\n\n.table-responsive {\n min-height: .01%; // Workaround for IE9 bug (see https://github.com/twbs/bootstrap/issues/14837)\n overflow-x: auto;\n\n @media screen and (max-width: @screen-xs-max) {\n width: 100%;\n margin-bottom: (@line-height-computed * .75);\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid @table-border-color;\n\n // Tighten up spacing\n > .table {\n margin-bottom: 0;\n\n // Ensure the content doesn't wrap\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n white-space: nowrap;\n }\n }\n }\n }\n\n // Special overrides for the bordered tables\n > .table-bordered {\n border: 0;\n\n // Nuke the appropriate borders so that the parent can handle them\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n\n // Only nuke the last row's bottom-border in `tbody` and `tfoot` since\n // chances are there will be only one `tr` in a `thead` and that would\n // remove the border altogether.\n > tbody,\n > tfoot {\n > tr:last-child {\n > th,\n > td {\n border-bottom: 0;\n }\n }\n }\n\n }\n }\n}\n","// Tables\n\n.table-row-variant(@state; @background) {\n // Exact selectors below required to override `.table-striped` and prevent\n // inheritance to nested tables.\n .table > thead > tr,\n .table > tbody > tr,\n .table > tfoot > tr {\n > td.@{state},\n > th.@{state},\n &.@{state} > td,\n &.@{state} > th {\n background-color: @background;\n }\n }\n\n // Hover states for `.table-hover`\n // Note: this is not available for cells or rows within `thead` or `tfoot`.\n .table-hover > tbody > tr {\n > td.@{state}:hover,\n > th.@{state}:hover,\n &.@{state}:hover > td,\n &:hover > .@{state},\n &.@{state}:hover > th {\n background-color: darken(@background, 5%);\n }\n }\n}\n","// stylelint-disable selector-no-qualifying-type, property-no-vendor-prefix, media-feature-name-no-vendor-prefix\n\n//\n// Forms\n// --------------------------------------------------\n\n\n// Normalize non-controls\n//\n// Restyle and baseline non-control form elements.\n\nfieldset {\n // Chrome and Firefox set a `min-width: min-content;` on fieldsets,\n // so we reset that to ensure it behaves more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359.\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: @line-height-computed;\n font-size: (@font-size-base * 1.5);\n line-height: inherit;\n color: @legend-color;\n border: 0;\n border-bottom: 1px solid @legend-border-color;\n}\n\nlabel {\n display: inline-block;\n max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141)\n margin-bottom: 5px;\n font-weight: 700;\n}\n\n\n// Normalize form controls\n//\n// While most of our form styles require extra classes, some basic normalization\n// is required to ensure optimum display with or without those classes to better\n// address browser inconsistencies.\n\ninput[type=\"search\"] {\n // Override content-box in Normalize (* isn't specific enough)\n .box-sizing(border-box);\n\n // Search inputs in iOS\n //\n // This overrides the extra rounded corners on search inputs in iOS so that our\n // `.form-control` class can properly style them. Note that this cannot simply\n // be added to `.form-control` as it's not specific enough. For details, see\n // https://github.com/twbs/bootstrap/issues/11586.\n -webkit-appearance: none;\n appearance: none;\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9; // IE8-9\n line-height: normal;\n\n // Apply same disabled cursor tweak as for inputs\n // Some special care is needed because