diff --git a/modules/cms/README.md b/modules/cms/README.md new file mode 100644 index 00000000..4c1b1cd2 --- /dev/null +++ b/modules/cms/README.md @@ -0,0 +1,91 @@ +# jeesite4-cms + +## 项目介绍 + +JeeSite4 CMS 内容管理模块 + +包含功能:站点管理、栏目管理、模板管理、内容发布 + +规划内容:站内统计、站内搜索、标签管理、留言管理、权限及审核、相关文章选取、文章多栏目 + +## 快速体验 + +### 在线演示 + +1. 前端演示: +2. 后端演示: +3. 账号:system +4. 密码:admin + +### 本地运行 + +1. 环境准备:`JDK 1.8 or 11`、`Maven 3.6+`、`MySQL 5.7 or 8.0` +2. 下载源码: +3. 打开文件:/web`/src/main/resources/config/application.yml` 配置JDBC连接 +4. 执行脚本:/web`/bin/init-data.bat` 初始化数据库 +5. 执行脚本:/web`/bin/run-tomcat.bat` 启动服务即可 +6. 浏览器访问: 账号 system 密码 admin +7. 部署常见问题: + +### 开发环境 + +1. 部署运行: +2. 常见问题: + +## 在线文档 + +* + +## 授权协议声明 + +1. 已开源的代码,授权协议采用 AGPL v3 + Apache Licence v2 进行发行。 +2. 您可以免费使用、修改和衍生代码,但不允许修改后和衍生的代码做为闭源软件发布。 +3. 修改后和衍生的代码必须也按照AGPL协议进行流通,对修改后和衍生的代码必须向社会公开。 +4. 如果您修改了代码,需要在被修改的文件中进行说明,并遵守代码格式规范,帮助他人更好的理解您的用意。 +5. 在延伸的代码中(修改和有源代码衍生的代码中)需要带有原来代码中的协议、版权声明和其他原作者规定 +需要包含的说明(请尊重原作者的著作权,不要删除或修改文件中的`@author`信息)。 +6. 您可以应用于商业软件,但必须遵循以上条款原则(请协助改进本作品)。 +7. 关系平台的发展战略考虑,底层部分代码暂未开源,但这不影响您的二次开发。 +8. 请知悉社区版,用户数不可超过100个,最大允许20个用户同时在线(不含匿名)。 + +## 技术服务与支持 + +* 没有资金的支撑就很难得到发展,特别是一个好的产品,如果 JeeSite 帮助了您,请为我们点赞。支持我们,您可以得到一些回报,有了这些我们会把公益事业做的更好,回报社区和社会,请给我们一些动力吧,在此非常感谢已支持我们的朋友! +* **联系方式(官方商务)QQ:[1766571055](http://wpa.qq.com/msgrd?v=3&uin=1766571055&site=qq&menu=yes)** +* 技术服务支持网页: + +# 技术交流方式 + +* QQ 群号:`127515876`、`209330483`、`223507718`、`709534275`、`730390092`、`1373527`、`183903863(外包)` +* 问题反馈:  [【新手必读】](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/master/README-zh_CN.md) +* 码云Gitee: +* GitHub: +* 作者博客: +* **技术服务:** +* 官方网站: +* 官方论坛: +* 微信公众号(关注动态): + +![JeeSite4微信公众号](https://static.oschina.net/uploads/space/2018/0302/145133_OGZf_941661.jpg "JeeSite4微信公众号") + +## 今后如何升级? + +尽量不修改 web 项目以外的源码项目,如 jeesite-common、jeesite-modele-core,如果修改了,请 Pull Requests 上来,否则代码与官方不同步,会将对你的日后升级增加难度。 + +如果您修改了依赖模块代码,也没关系,这时你需要利用 Git 版本控制工具,与官方仓库代码进行同步,合并代码即可。 + +每个版本升级,我们都会附带详细更新日志:。 + +在这里,你可以看到 JeeSite 新增哪些新功能和改进,在每个版本下都有对应升级方法。 + +# Git 全局设置技巧 + +``` +1、提交检出均不转换换行符 + +git config --global core.autocrlf false + +2、拒绝提交包含混合换行符的文件 + +git config --global core.safecrlf true +``` diff --git a/modules/cms/bin/deploy.bat b/modules/cms/bin/deploy.bat new file mode 100644 index 00000000..6ce0b6ad --- /dev/null +++ b/modules/cms/bin/deploy.bat @@ -0,0 +1,19 @@ +@echo off +rem /** +rem * Copyright (c) 2013-Now http://jeesite.com All rights reserved. +rem * +rem * Author: ThinkGem@163.com +rem */ +echo. +echo [Ϣ] 𹤳̰汾Nexus +echo. + +%~d0 +cd %~dp0 + +cd .. +call mvn clean deploy -Dmaven.test.skip=true -Pdeploy + +cd bin +cmd /c msg %username% /time:0 /w "..." +pause \ No newline at end of file diff --git a/modules/cms/bin/javadoc.bat b/modules/cms/bin/javadoc.bat new file mode 100644 index 00000000..fe8258da --- /dev/null +++ b/modules/cms/bin/javadoc.bat @@ -0,0 +1,18 @@ +@echo off +rem /** +rem * Copyright (c) 2013-Now http://jeesite.com All rights reserved. +rem * +rem * Author: ThinkGem@163.com +rem */ +echo. +echo [Ϣ] 빤Javadocjarļ +echo. + +%~d0 +cd %~dp0 + +cd .. +call mvn clean package -Pjavadoc + +cd bin +pause \ No newline at end of file diff --git a/modules/cms/bin/package.bat b/modules/cms/bin/package.bat new file mode 100644 index 00000000..87a98f4e --- /dev/null +++ b/modules/cms/bin/package.bat @@ -0,0 +1,19 @@ +@echo off +rem /** +rem * Copyright (c) 2013-Now http://jeesite.com All rights reserved. +rem * +rem * Author: ThinkGem@163.com +rem */ +echo. +echo [Ϣ] װ̣jarļ +echo. + +%~d0 +cd %~dp0 + +cd .. +call mvn clean install -Dmaven.test.skip=true -Ppackage + +cd bin +cmd /c msg %username% /time:0 /w "..." +pause \ No newline at end of file diff --git a/modules/cms/db/cms.erm b/modules/cms/db/cms.erm new file mode 100644 index 00000000..222c1125 --- /dev/null +++ b/modules/cms/db/cms.erm @@ -0,0 +1,8847 @@ + + + + true + 100 + A4 210 x 297 mm + 30 + 30 + 30 + 30 + + 0 + 1.0 + 0 + 7 + + 128 + 128 + 192 + + + 255 + 255 + 255 + + Segoe UI + 9 + + StandardSQL + false + + + 0 + true + 2 + 1 + 1 + false + true + false + false + + + db\cms.sql + UTF-8 + CR+LF + false + 7be191506f9daa8070b3ac14921dffd44063d2bb + null + + true + false + true + false + true + false + false + false + false + false + false + false + false + false + false + true + false + true + false + false + + + + + null + C:\Users\47155\Desktop\tpl.xls + + + en + + true + true + true + + + C:\Users\47155\Desktop\cms + true + true + true + + + db\tpl.png + + true + true + + + + + + + false + + + + + 0 + + + + false + false + + + + + false + + + + + + -1 + -1 + Microsoft YaHei UI + 9 + 50 + 50 + + 255 + 255 + 255 + + + + false + 2016-12-25 17:25:00 + + Project Name + + + + Model Name + + + + Version + + + + Company + + + + Author + + + + + + + + + 7be191506f9daa8070b3ac14921dffd44063d2bb + Default + + + + + + 18423fee68730dc1c22be45168acf153e015b39b + 255 + null + false + null + false + false + false + + false + 栏目内容的标题 + 内容标题 + article_title + nvarchar(n) + + + 276f29162989f309d85806ece156f0a9c37484f1 + 200 + null + false + null + false + false + false + + false + + 审核意见 + audit_comment + nvarchar(n) + + + 7a327bcd0e95fbbf6b724d05c14f085950fa0928 + null + null + false + null + false + false + false + + false + 审核时间 + 审核时间 + audit_date + datetime + + + 15c9658569b24151180e771838432db066fe41f1 + 64 + null + false + null + false + false + false + + false + 审核人 + 审核人 + audit_user_code + varchar(n) + + + 162641e8c144235ea0f2fb55ed4b88c7e1c006bf + 64 + null + false + null + false + false + false + + false + 栏目编码 + 栏目编码 + category_code + varchar(n) + + + b0280df85be5321ac35dd7904bd04fe457b7d09f + 100 + null + false + null + false + false + false + + false + 栏目名称 + 栏目名称 + category_name + nvarchar(n) + + + 581244a112411170ac52781772032cf085b650c6 + 10 + null + false + null + false + false + false + + false + + 点击次数 + clicknum + numeric(p) + + + 45d160c563e186ec25cd93a0f7f56f0f9707d452 + 50 + null + false + null + false + false + false + + false + 标题颜色 + 标题颜色 + color + varchar(n) + + + cb2bc616bce32c0f61c17738422060cd80323cc2 + null + null + false + null + false + false + false + + false + 文章内容 + 文章内容 + content + longtext + + + 376234bf5c48cb23f4962ddbf0c3377580dd0630 + 255 + null + false + null + false + false + false + + false + 留言内容 + 留言内容 + content + varchar(n) + + + 71e860010ee137570b1fe15d54f8fc3ee5ccf7e5 + 255 + null + false + null + false + false + false + + false + 评论内容 + 评论内容 + content + nvarchar(n) + + + bc6982437f1b0a13481990caca7792beba6b3be8 + 64 + null + false + null + false + false + false + + false + 栏目内容的编号 + 栏目内容编号 + content_id + varchar(n) + + + cf0c2dbf00cefef058b14c8080038e97bd0d0f3b + 255 + null + false + null + false + false + false + + false + 访问页面标题 + 访问页面标题 + content_title + nvarchar(n) + + + 4fd30a9613db6a1f261f57904adc7b0534734276 + 255 + null + false + null + false + false + false + + false + 文章来源出处 + 文章来源出处 + copyfrom + nvarchar(n) + + + cd22c62ad8eff35c93dc3f7753fc82fa8a63e34d + 1000 + null + false + null + false + false + false + + false + 版权信息 + 版权信息 + copyright + nvarchar(n) + + + 136ca02f1b3a96a8f2e242d5dd64d48f566143ef + 64 + null + false + null + false + false + false + + false + 租户代码 + 租户代码 + corp_code + varchar(n) + + + f116706ac00cd3a3ee88b2a88debf7ebc3eeb12d + 100 + null + false + null + false + false + false + + false + 租户名称 + 租户名称 + corp_name + nvarchar(n) + + + 1a3b3f8bccfce8894d117d6bdb0a6b104bfb80ef + 64 + null + false + null + false + false + false + + false + + 创建者 + create_by + varchar(n) + + + dba1aec0c72d79ea73ed4ebde07696cf4df174b7 + null + null + false + null + false + false + false + + false + + 创建时间 + create_date + datetime + + + cf1c7c6cb10c709dc1a30a0626bd36e5bfa571d1 + 32 + null + false + null + false + false + false + + false + + 控制类型(view查看、edit编辑) + ctrl_type + varchar(n) + + + 98dd48bc416b1ce6872885df8cec3e40044b1ea3 + 255 + null + false + null + false + false + false + + false + 自定义内容视图 + 自定义内容视图 + custom_content_view + varchar(n) + + + 79a00041672d16ea35bc08c824f8b9200a4acf9a + 500 + null + false + null + false + false + false + + false + 自定义站点首页视图 + 自定义站点首页视图 + custom_index_view + varchar(n) + + + 549ced1875f9f9d6e9cdf6ba3a51eb75781a886e + 255 + null + false + null + false + false + false + + false + 自定义列表视图 + 自定义列表视图 + custom_list_view + varchar(n) + + + 4f08e0e3e3e8b8c34be9e05d95118c5add3d0b13 + 500 + null + false + null + false + false + false + + false + 描述、摘要 + 描述 + description + nvarchar(n) + + + 7f40f312d59375e237ed0de76e696040d9550c13 + 500 + null + false + null + false + false + false + + false + 站点域名 + 站点域名 + domain + nvarchar(n) + + + eb7c174e7534886be14f65e91dfbfdd7ee98a555 + 100 + null + false + null + false + false + false + + false + 邮箱 + 邮箱 + email + varchar(n) + + + f01926071736b56b898949cc0720149c71504324 + null + null + false + null + false + false + false + + false + + 扩展 Date 1 + extend_d1 + datetime + + + 942700093ab61c3be0bdf6b23bcba210bcc30281 + null + null + false + null + false + false + false + + false + + 扩展 Date 2 + extend_d2 + datetime + + + f221902bf89fe94dece8ccf309f59cc2c479d63f + null + null + false + null + false + false + false + + false + + 扩展 Date 3 + extend_d3 + datetime + + + c8d21e24bc69aac295703b0bae56269035b729f0 + null + null + false + null + false + false + false + + false + + 扩展 Date 4 + extend_d4 + datetime + + + 4c0cc4ae32f8774cc319f516784430204aef0bdb + 19 + 4 + false + null + false + false + false + + false + + 扩展 Float 1 + extend_f1 + decimal(p,s) + + + 2e958c528620621985af4394590198feed57cdf9 + 19 + 4 + false + null + false + false + false + + false + + 扩展 Float 2 + extend_f2 + decimal(p,s) + + + 7c25ad75662553c7d4a58fa66eb50ca7c0ffee59 + 19 + 4 + false + null + false + false + false + + false + + 扩展 Float 3 + extend_f3 + decimal(p,s) + + + 1f81990c9694963f032c302d1834b972a6f2eb74 + 19 + 4 + false + null + false + false + false + + false + + 扩展 Float 4 + extend_f4 + decimal(p,s) + + + a1d747cd40768ac9f85176518ee48cb513bae110 + 19 + null + false + null + false + false + false + + false + + 扩展 Integer 1 + extend_i1 + decimal(p) + + + a9f0e14d6691c397990abe4ef1ff21674dccf401 + 19 + null + false + null + false + false + false + + false + + 扩展 Integer 2 + extend_i2 + decimal(p) + + + 2ce06c5cf87d93bb1e3f47268dbc679be4b6dd8d + 19 + null + false + null + false + false + false + + false + + 扩展 Integer 3 + extend_i3 + decimal(p) + + + 53d8c730fcec69d341f44089817ae06eb4844278 + 19 + null + false + null + false + false + false + + false + + 扩展 Integer 4 + extend_i4 + decimal(p) + + + ad6f9eff50476669df62b7601cbc3a2e0c905d36 + 500 + null + false + null + false + false + false + + false + + 扩展 String 1 + extend_s1 + nvarchar(n) + + + 3a24133d2be4831e99d1319983e5393bcf964ff9 + 500 + null + false + null + false + false + false + + false + + 扩展 String 2 + extend_s2 + nvarchar(n) + + + 40e1afbbad28d28e371dd1ab77fb56640b1cb66b + 500 + null + false + null + false + false + false + + false + + 扩展 String 3 + extend_s3 + nvarchar(n) + + + a2d6b5a494fc1a3d29360d922296521c6640856b + 500 + null + false + null + false + false + false + + false + + 扩展 String 4 + extend_s4 + nvarchar(n) + + + 29f701cc6a308fbfc5b12b80fee621ceeb231dcc + 500 + null + false + null + false + false + false + + false + + 扩展 String 5 + extend_s5 + nvarchar(n) + + + c9a37a7b6a5451930ca63e36814767f742cd1393 + 500 + null + false + null + false + false + false + + false + + 扩展 String 6 + extend_s6 + nvarchar(n) + + + 8c26203d310a4e602cf0c0fc8a7b2c818219c1dc + 500 + null + false + null + false + false + false + + false + + 扩展 String 7 + extend_s7 + nvarchar(n) + + + 54448f19b0f5d1630bf29f9f99787802c36ebddb + 500 + null + false + null + false + false + false + + false + + 扩展 String 8 + extend_s8 + nvarchar(n) + + + c06fbfe37373cf6e7b81cef738d9889861026080 + 20 + null + false + null + false + false + false + + false + 首次访问时间戳(30分钟内) + 首次访问时间戳(30分钟内) + first_visit_time + decimal(p) + + + 64d3c520e91a13dcd9f63fae7b177bb06e05be7a + 20 + null + false + null + false + false + false + + false + 点击数 + 点击数 + hits + decimal(p) + + + 47c3a25657ac2f136e12188e0134fe30928477f9 + 10 + null + false + null + false + false + false + + false + + 反对数 + hits_minus + numeric(p) + + + b8d8a57b107565584ffde420f188c8c0d444487b + 10 + null + false + null + false + false + false + + false + + 支持数 + hits_plus + numeric(p) + + + f46eac64abba3044db1451ea94dbc46f4d888e9a + 1000 + null + false + null + false + false + false + + false + 外部链接 + 外部链接 + href + nvarchar(n) + + + 7df5a5ec366af21eeab7cf932b6c36a908570001 + 255 + null + false + null + false + false + false + + false + 链接 + 链接 + href + varchar(n) + + + 869fc70cf3a4e92e8056b40814df8e03f9f9efde + 64 + null + false + null + false + false + false + + false + + 编号 + id + varchar(n) + + + cdfdb56f0ba0532d4e4c01bb054ce75cbf07e959 + 1000 + null + false + null + false + false + false + + false + 内容图片 + 内容图片 + image + nvarchar(n) + + + 38677895fbddee2a778976096fc554af0dbe3ede + 255 + null + false + null + false + false + false + + false + 栏目图片 + 栏目图片 + image + varchar(n) + + + 43fdb5b94b461a22605d5cd4488a59655fa00dc5 + 1 + null + false + null + false + false + false + + false + 是否在分类页中显示列表 + 是否在分类页中显示列表 + in_list + character(n) + + + a01a65e5fb2a04c46595d7d11cadd36673b441ad + 1 + null + false + null + false + false + false + + false + 是否在导航中显示 + 是否在导航中显示 + in_menu + character(n) + + + 3138f8d288350701cc88f8e7b35df4353f4d30ea + 100 + null + false + null + false + false + false + + false + IP + IP + ip + varchar(n) + + + 9264d171a6799492e2556fcd2ef63de54f817bb7 + 100 + null + false + null + false + false + false + + false + 评论IP + 评论IP + ip + varchar(n) + + + f780d22bd4bf8e279c5016565e37f1b2cace44d7 + 1 + null + false + null + false + false + false + + false + 是否允许评论 + 是否允许评论 + is_can_comment + character(n) + + + 76d25011f19ac67544dc8af547b2715c85df01cd + 1 + null + false + null + false + false + false + + false + 是否需要审核 + 是否需要审核 + is_need_audit + character(n) + + + 72f4b00b6f706098095195f66bed1dd8f83c48b3 + 1 + null + false + null + false + false + false + + false + 是否新访问(30分内) + 是否新访问(30分内) + is_new_visit + character(n) + + + 146b4ca3cafb932a0474b6885799a84179426683 + 500 + null + false + null + false + false + false + + false + 关键字(搜索引擎优化,5个关键词以内) + 关键字 + keywords + nvarchar(n) + + + be34a39fc2bdae09f8bc815c9994b6fff2eaaac5 + 1000 + null + false + null + false + false + false + + false + 站点Logo + 站点Logo + logo + nvarchar(n) + + + a478faefac3b31fe451d144c115eab04e02533d1 + 50 + null + false + null + false + false + false + + false + 模块类型(none未定义、article文章、link链接、picture图片、video视频、down下载) + 模块类型 + module_type + varchar(n) + + + 2ff476b57a1464663b6c316ecbe069add468704a + 100 + null + false + null + false + false + false + + false + 姓名 + 姓名 + name + varchar(n) + + + ac4749308c644019a83c0a1932603bce674e8997 + 50 + null + false + null + false + false + false + + false + 评论姓名 + 评论姓名 + name + nvarchar(n) + + + b18ce64a2a72d00b26515583d8bbfea282f30ea8 + 64 + null + false + null + false + false + false + + false + + 父级编号 + parent_code + varchar(n) + + + 63772c051414452204e91e8d0dabd1dbfd640326 + 1000 + null + false + null + false + false + false + + false + + 所有父级编号 + parent_codes + varchar(n) + + + 6ba94d61743eaf1154092edf58fa87fcba5aaf3c + 64 + null + false + null + false + false + false + + false + + 父级评论 + parent_id + varchar(n) + + + 4def76c4bb013e807e5f9e85305fae58c1014598 + 100 + null + false + null + false + false + false + + false + 电话 + 电话 + phone + varchar(n) + + + 4882d2e2de114e7546c9b73add64c6bffbb0125d + 1 + null + false + null + false + false + false + + false + 推荐位置(1轮播图 2首页推荐 3栏目页面) + 推荐位置(1轮播图 2首页推荐 3栏目页面) + postid + character(n) + + + e4c17b0a5b5c7a749a78e4065e9880a864ee175e + 20 + null + false + null + false + false + false + + false + 上页面停留时间(秒) + 上页面停留时间(秒) + prev_remain_time + decimal(p) + + + f07d30b38dcf7c8a155495225eed8fb6f8fe706a + 1000 + null + false + null + false + false + false + + false + 相关文章 + 相关文章 + relation + varchar(n) + + + 8f7d3761c17a1b8632d186a3c67cb08dca18c498 + 500 + null + false + null + false + false + false + + false + + 备注信息 + remarks + nvarchar(n) + + + de0a86ea90c71e5cb459e9519cc04d3888aef682 + 50 + null + false + null + false + false + false + + false + 客户IP地址 + 客户IP地址 + remote_addr + varchar(n) + + + 2113020e467d973a4e0c408a0a26e74d6bb78e6e + 500 + null + false + null + false + false + false + + false + + 举报原因 + report_cause + nvarchar(n) + + + 8c838100145c0a8fd3f1ceba92027886c916c7f5 + 500 + null + false + null + false + false + false + + false + 内容简要 + 举报内容(文章标题 评论内容) + report_content + nvarchar(n) + + + 023f9dc616498f60530767741bd543ca80070de3 + 1 + null + false + null + false + false + false + + false + + 举报来源(1文章、2评论) + report_source + character(n) + + + f4c59d5bc735102301e4e1d2ad1d5168d12e53f5 + 1 + null + false + null + false + false + false + + false + 诈骗 色情 政治 广告 抄袭 招聘 骂人 其它 + 举报类型(色情 政治...) + report_type + character(n) + + + 3129303292f943bb8b9d07908286f0c6ed4aedcd + 1000 + null + false + null + false + false + false + + false + + 举报的URL + report_url + nvarchar(n) + + + 19264b2f174056dc96020df8eab77231b02006c6 + 1000 + null + false + null + false + false + false + + false + 请求的URL地址 + 请求的URL地址 + request_url + nvarchar(n) + + + cdfa87aaa2aa70a3821d4786ecf5797abc33dbb1 + 128 + null + false + null + false + false + false + + false + 受访域名 + 受访域名 + request_url_host + varchar(n) + + + 9f5b7aeaf2afaabd7678145370baeb6b1a23164e + 100 + null + false + null + false + false + false + + false + 回复内容 + 回复内容 + re_content + varchar(n) + + + fc06eec9e29a0f2ff1ec3a6b8274e6545eef61f5 + null + null + false + null + false + false + false + + false + 回复时间 + 回复时间 + re_date + datetime + + + 62794b6f565e28ca544f726999f655bcb089e6f6 + 64 + null + false + null + false + false + false + + false + 回复人 + 回复人 + re_user_code + varchar(n) + + + 0939f982d8d703b2e27b802da88b1ba1eeb11c63 + 64 + null + false + null + false + false + false + + false + 角色编码 + 角色编码 + role_code + varchar(n) + + + 626f13010fad1c5b688e9d775634e9e3a15aa4ec + 200 + null + false + null + false + false + false + + false + 使用的搜索引擎 + 使用的搜索引擎 + search_engine + varchar(n) + + + fb356519870eeb1925bc287f5334c520e5976a23 + 200 + null + false + null + false + false + false + + false + 搜索的关键词 + 搜索的关键词 + search_word + nvarchar(n) + + + e9bcb01788ca210c5282fe9df263880768a8a421 + 1 + null + false + null + false + false + false + + false + 展现模式(1自动、2栏目列表、3第一条内容) + 展现模式 + show_modes + character(n) + + + f240879d6a1a961e639649e02beabfd37ef5319b + 64 + null + false + null + false + false + false + + false + 站点编码 + 站点编码 + site_code + varchar(n) + + + 74dad2ed7366e74f74b96590df8b6bd758748b52 + 100 + null + false + null + false + false + false + + false + 站点名称 + 站点名称 + site_name + nvarchar(n) + + + a602c1eeebe58e1a0a6d735ad1c32431059001fb + 10 + null + false + null + false + false + false + + false + + 站点排序号 + site_sort + decimal(p) + + + 80153420ce49ce7c3dde6b7bd1e0dce4efa88311 + 1 + null + false + null + false + false + false + + false + 来源(转载/原创) + 来源(转载/原创) + source + character(n) + + + 1f84206ebb5d9ec004683cdc149c7c084996783f + 1000 + null + false + null + false + false + false + + false + 来源页面/上一个页面 + 来源页面/上一个页面 + source_referer + nvarchar(n) + + + 6fe4763312dd285fc23b1b89b48818b62c4413b5 + 128 + null + false + null + false + false + false + + false + 来源域名 + 来源域名 + source_referer_host + varchar(n) + + + 7d7995d828c0914d911159edf137555d0a6e2abd + 1 + null + false + null + false + false + false + + false + 访问来源类型(1直接访问 2搜索引擎 3外部链接 4内部访问) + 访问来源类型(1直接访问 2搜索引擎 3外部链接 4内部访问) + source_type + character(n) + + + ba0fb53af3ccc8b0e5d73baa58ec27fbb7973097 + 1 + null + false + null + false + false + false + + false + + 状态(0正常 1删除 2停用 3冻结 4审核 5驳回 9草稿) + status + character(n) + + + 17718c2364a2368c2072da279c927d7ad3bfcf08 + 1 + null + false + null + false + false + false + + false + + 状态(0正常 1删除 2停用) + status + character(n) + + + da70970cf1f73a8092ba0abd5d7da6c2dfec55ce + 1 + null + false + null + false + false + false + + false + 状态(0正常 1删除 2停用) + 状态(0正常 1删除 2停用) + status + character(n) + + + fd1fe2bc7c729e16f6a70c1a3da1cbfbfdabb2e7 + 200 + null + false + null + false + false + false + + false + 保存前验证:不能包含空格、特殊字符 + 标签名称 + tag_name + nvarchar(n) + + + dc3463864d84a4527e93c3d687067776de971558 + 20 + null + false + null + false + false + false + + false + 目标 + 目标 + target + varchar(n) + + + 61c82eaa83caf2d162e87179e8beb2f76d1af8ec + 500 + null + false + null + false + false + false + + false + 主题 + 主题 + theme + nvarchar(n) + + + 2ade064238f63bf942781dc39267fe7f54e4692f + 255 + null + false + null + false + false + false + + false + 标题 + 内容标题 + title + nvarchar(n) + + + 189344c9d7084fbc3e0cb35296704bbdf757d5dd + 100 + null + false + null + false + false + false + + false + 站点标题 + 站点标题 + title + nvarchar(n) + + + 579af65311bc12dd812b2ed39be655cee97c8aa7 + 20 + null + false + null + false + false + false + + false + 本次访问总停留时间(秒) + 本次访问总停留时间(秒) + total_remain_time + decimal(p) + + + 40b63ab3e485fd55370d6d04b063c4397483ebc1 + 1 + null + false + null + false + false + false + + false + + 是否最末级 + tree_leaf + character(n) + + + 3b9c3307b7140f27edeb47ffe307a662b2856627 + 4 + null + false + null + false + false + false + + false + + 层次级别 + tree_level + decimal(p) + + + 8f1564e5646071de508d4325f3cc7f62bdeede16 + 1000 + null + false + null + false + false + false + + false + + 全节点名 + tree_names + nvarchar(n) + + + be17e27c1f73fe128f00468cc83953077b7e00a9 + 10 + null + false + null + false + false + false + + false + + 本级排序号(升序) + tree_sort + decimal(p) + + + b0bd388c14e5b2bbab9590f5247961a7edd9eb3b + 1000 + null + false + null + false + false + false + + false + + 所有级别排序号 + tree_sorts + varchar(n) + + + 010164f48d907c212ae5e7907fa4a5dbfafe362c + 1 + null + false + null + false + false + false + + false + 留言分类 + 留言分类 + type + character(n) + + + 73fe9fe9915dd5e26c836900286817b0001355f3 + 64 + null + false + null + false + false + false + + false + 唯一访问标识 + 唯一访问标识 + unique_visit_id + varchar(n) + + + 2c6b290f30c6f9e100f6c77eab0cba7bb3386768 + 64 + null + false + null + false + false + false + + false + + 更新者 + update_by + varchar(n) + + + f0bdbc4002f4a1b7fb7c5026bc21a7689c549728 + null + null + false + null + false + false + false + + false + + 更新时间 + update_date + datetime + + + 3e9a36e6532a7fe55b0fc5023799f48919763d5b + 500 + null + false + null + false + false + false + + false + 用户代理字符串 + 用户代理字符串 + user_agent + nvarchar(n) + + + a7e4710c73fbc7e258dd2265e5898d2894bd0c37 + 32 + null + false + null + false + false + false + + false + 客户机浏览器 + 客户机浏览器 + user_browser + varchar(n) + + + 1060d99506aeda5039290561437e32edc41dfb88 + 16 + null + false + null + false + false + false + + false + 浏览器版本 + 浏览器版本 + user_browser_version + varchar(n) + + + 346a0c5387bf2cf7a8f84a992179704ac34dea69 + 32 + null + false + null + false + false + false + + false + 客户机设备类型(电脑、平板、手机、未知) + 客户机设备类型(电脑、平板、手机、未知) + user_device + varchar(n) + + + 61f45ec3bac44bf148a2dc85f88125b71233098c + 32 + null + false + null + false + false + false + + false + 客户机语言 + 客户机语言 + user_language + varchar(n) + + + f55d0606429d87a6f00e802fde5456fd9549a0eb + 32 + null + false + null + false + false + false + + false + 客户机操作系统 + 客户机操作系统 + user_os_name + varchar(n) + + + 2d3da4d12a6f53fe0dab1dd91b35740e6d690d1e + 32 + null + false + null + false + false + false + + false + 客户机屏幕大小0x0 + 客户机屏幕大小0x0 + user_screen_size + varchar(n) + + + 3dadc495eadb3f2e14472ff7f2869ab7b20d4cb5 + 1000 + null + false + null + false + false + false + + false + 视图配置 + 视图配置 + view_config + nvarchar(n) + + + 0977190c44e604b4d183b11ef985a0d7584a0ef8 + 8 + null + false + null + false + false + false + + false + 本次访问日期(年月日) + 本次访问日期(年月日) + visit_date + character(n) + + + ae3ebfdb53668bb1c6d2be5049d3115ade6f0a7d + null + null + false + null + false + false + false + + false + 本次访问时间 + 本次访问时间 + visit_time + datetime + + + 1e4dff03abe041fe10914c966492460da29c8641 + 100 + null + false + null + false + false + false + + false + 访问用户编码 + 访问用户编码 + visit_user_code + varchar(n) + + + 5788894bc8fd0c267fdcbb3f94427221ce1f36e2 + 100 + null + false + null + false + false + false + + false + 访问用户姓名 + 访问用户姓名 + visit_user_name + varchar(n) + + + 1a97c7c45f8e29ecae15b06520e90702bf5cdc85 + 10 + null + false + null + false + false + false + + false + 权重,越大越靠前 + 权重,越大越靠前 + weight + decimal(p) + + + 45cc4afa6cf6ab40e9af2ce5755dfb3c7a9e1db4 + null + null + false + null + false + false + false + + false + 权重期限 + 权重期限 + weight_date + datetime + + + 98afbf96d353f87ce0478e168869e56dfd4af462 + 10 + null + false + null + false + false + false + + false + 不包含html + 字数(不包含html) + word_count + numeric(p) + + + 7eaf2cd14dc6846a588385cbecc4dc65851784c8 + 100 + null + false + null + false + false + false + + false + 单位 + 单位 + workunit + varchar(n) + + + + + + + e9faab162f8d6a9f4bed0be95c9dbb56647656e1 + 126 + 433 + Segoe UI + 9 + 47 + 1032 + + 128 + 128 + 192 + + + + b3360c18b956528f86538657fb259817fab21f34 + 7f024bd90eec8d89290f4db163b3ea077d6ce26d + e9faab162f8d6a9f4bed0be95c9dbb56647656e1 + -1 + -1 + -1 + -1 + + 0 + 0 + 0 + + 1..n + 1 + true + + RESTRICT + RESTRICT + null + null + + + js_cms_category_role + 栏目与角色关联表 + + + + + + + 7b648ef7efea218657b3201e0a0318986ff5e8cb + 0d993b7470d7bde3d20e9c7f24d1811518cf44cc + b3360c18b956528f86538657fb259817fab21f34 + + + + + varchar(n) + + + false + true + true + true + false + + + + + + + + + + + false + false + false + + + 0 + + + + 0939f982d8d703b2e27b802da88b1ba1eeb11c63 + ce2d48afb8905587f7c02d974187a1ee21e49a3e + + + + + varchar(n) + + + false + false + true + true + false + + + + + + + + + + + false + false + false + + + 0 + + + + cf1c7c6cb10c709dc1a30a0626bd36e5bfa571d1 + 70a3e7ce63bd4bf4c874d7b220a3d8d4b2b0d266 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + + + + + + + +
+ + 0052091c705499292120c4b9463e48e1681fb544 + 464 + 383 + Segoe UI + 9 + 72 + 1428 + + 128 + 128 + 192 + + + + js_cms_guestbook + 留言板表 + + + + + + + 869fc70cf3a4e92e8056b40814df8e03f9f9efde + 052814be6ac553aeaf48456c40a56b7bb07d8e1c + + + + + varchar(n) + + + false + false + true + true + false + + + + + + + + + + + false + false + false + + + 0 + + + + 010164f48d907c212ae5e7907fa4a5dbfafe362c + de62b318185bafcd83e1b67fabbc7999636fb3d9 + + + + + character(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 376234bf5c48cb23f4962ddbf0c3377580dd0630 + c9ffac35c779194ed4597e9ffad10ef5d74a241f + + + + + varchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 2ff476b57a1464663b6c316ecbe069add468704a + 9db48e0afaca1b801565f268c23e4ec16bae201c + + + + + varchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + eb7c174e7534886be14f65e91dfbfdd7ee98a555 + 0081da55676f6d2f99f03ba58f66bf68e5aee726 + + + + + varchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 4def76c4bb013e807e5f9e85305fae58c1014598 + 3dda39016f4c27f61972558cbd73b68ab50fb3ea + + + + + varchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 7eaf2cd14dc6846a588385cbecc4dc65851784c8 + f7c356eb848e5e459650a4057c7c7d1cd0215c5d + + + + + varchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 3138f8d288350701cc88f8e7b35df4353f4d30ea + cdaf26c12c897ca383fbb69716b508aecb621850 + + + + + varchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 1a3b3f8bccfce8894d117d6bdb0a6b104bfb80ef + 9dfdc2c1467655a55805a4ec37116f5865d3e2b2 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + dba1aec0c72d79ea73ed4ebde07696cf4df174b7 + 90bf3f6bc190ba2adaf843bb6a9ed721d5aead11 + + + + + datetime + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 62794b6f565e28ca544f726999f655bcb089e6f6 + 161e1e32456aceb2d5122f3b031b615175e4ff9a + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + fc06eec9e29a0f2ff1ec3a6b8274e6545eef61f5 + 30bbfd928c88a1bf1804e2adcefd63467bac27fb + + + + + datetime + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 9f5b7aeaf2afaabd7678145370baeb6b1a23164e + 75fa65cb78ce9a1ff4401d2c9a9690b3418cfa9a + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + da70970cf1f73a8092ba0abd5d7da6c2dfec55ce + ec57e1438e874c1f06b03f03d9dfdb5371d493db + + + + + character(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + ea920cba2fe0eaee64a2310ece7cda4b198b37ec + + + + false + true + idx_cms_guestbook_cc + + + + + b8ea4b73d6d32a222e5abfd453287575ae518480 + false + + + + + false + true + idx_cms_guestbook_status + + + + + ec57e1438e874c1f06b03f03d9dfdb5371d493db + false + + + + + false + true + idx_cms_guestbook_type + + + + + de62b318185bafcd83e1b67fabbc7999636fb3d9 + false + + + + + + + + + +
+ + 532c0bed9561904fcdfee70ba5c6520eae8b6430 + 906 + 623 + Segoe UI + 9 + 564 + 1548 + + 128 + 128 + 192 + + + + js_cms_visit_log + 访问日志表 + + + + + + + 869fc70cf3a4e92e8056b40814df8e03f9f9efde + 758f68adcfe7d38c1892ef7c83853af637877426 + + + + + varchar(n) + + + false + false + true + true + false + + + + + + + + + + + false + false + false + + + 0 + + + + 19264b2f174056dc96020df8eab77231b02006c6 + e5cde86b5469c9c872ca90960deb684da307db39 + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + cdfa87aaa2aa70a3821d4786ecf5797abc33dbb1 + 488bf86acbdce3d6a00a20f019f400502f71445e + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 1f84206ebb5d9ec004683cdc149c7c084996783f + 7e5a0c23f1ad7bbb4b3218ac555fcafe56898d10 + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 6fe4763312dd285fc23b1b89b48818b62c4413b5 + a3101fa6d57e6eb153290319b71e65e64e766061 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 7d7995d828c0914d911159edf137555d0a6e2abd + b52df321029b844a7bfa78010d8f3971998bf301 + + + + + character(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 626f13010fad1c5b688e9d775634e9e3a15aa4ec + 9bd3a96a7aa9a28eaaf137a1150aefacef548844 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + fb356519870eeb1925bc287f5334c520e5976a23 + 25120ab26de16de06751965ad340774ce0d263a7 + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + de0a86ea90c71e5cb459e9519cc04d3888aef682 + 5c4f4d350a1add35db1f8569b172e7c562c40f97 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 3e9a36e6532a7fe55b0fc5023799f48919763d5b + 5ab4e07953e586536e35c214ed9c218cd12395f0 + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 61f45ec3bac44bf148a2dc85f88125b71233098c + c8a22c7af18ddf0427ee32736cc71afd4c3f5757 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 2d3da4d12a6f53fe0dab1dd91b35740e6d690d1e + c516a2936a5c5353175b02eada0f17a167f8475e + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 346a0c5387bf2cf7a8f84a992179704ac34dea69 + 6cfb61364f9b1ff61d508968e9ff6c0d95274bfb + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + f55d0606429d87a6f00e802fde5456fd9549a0eb + ed5e1eb4954f339010a30de6cba5834363b50940 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + a7e4710c73fbc7e258dd2265e5898d2894bd0c37 + 6d60510a3055a28671f58dbe68dbcabc66914ed5 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 1060d99506aeda5039290561437e32edc41dfb88 + 98cda3c01ecd3f70bc0c8052fd174cfd91a7bfb7 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 73fe9fe9915dd5e26c836900286817b0001355f3 + aa81548cdaee0f75161c82ebc34ba8f6141f5672 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 0977190c44e604b4d183b11ef985a0d7584a0ef8 + daf8bca13ba345d6cdaa9301afba0c6854b4afbc + + + + + character(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + ae3ebfdb53668bb1c6d2be5049d3115ade6f0a7d + 5f233be0ca30e83b57f6abc88b524fffcd083438 + + + + + datetime + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 72f4b00b6f706098095195f66bed1dd8f83c48b3 + 144fe1a3053ef69b5afeb0a9303d9e1636983d3c + + + + + character(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + c06fbfe37373cf6e7b81cef738d9889861026080 + d11720c8999e8c32966f6fa8749801abcb6dfbce + + + + + decimal(p) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + e4c17b0a5b5c7a749a78e4065e9880a864ee175e + 203a7737a701a06b0e95477a4b878e6a930dc55c + + + + + decimal(p) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 579af65311bc12dd812b2ed39be655cee97c8aa7 + 7455ea9ba041221cabed55bfc9d593a7013b32c1 + + + + + decimal(p) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + f240879d6a1a961e639649e02beabfd37ef5319b + 422e64abc608e8fc88d0b60b9e292914b16b7b03 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 74dad2ed7366e74f74b96590df8b6bd758748b52 + 09fb8ac13825e6eb40d031d41a591d706cb98a06 + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 162641e8c144235ea0f2fb55ed4b88c7e1c006bf + f10b3487a7cc0fda6df95e104c1e40119c8b3ffd + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + b0280df85be5321ac35dd7904bd04fe457b7d09f + 7d809555199f92692e663598e1b54b06bbb92ce3 + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + bc6982437f1b0a13481990caca7792beba6b3be8 + 21d47905e8cb686fc0435ca912ffc49c2ac18cf7 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + cf0c2dbf00cefef058b14c8080038e97bd0d0f3b + 769bdb75e6da9ee88bd30b18786ed3350f8107fc + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 1e4dff03abe041fe10914c966492460da29c8641 + a788d046d20aa5cd4bbf4604999a45a8ca8400a1 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 5788894bc8fd0c267fdcbb3f94427221ce1f36e2 + 308b95d417d9ac2677c3a5ef9748330f1b757497 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + ea920cba2fe0eaee64a2310ece7cda4b198b37ec + + + + false + true + cms_visit_log_cc + + + + + f10b3487a7cc0fda6df95e104c1e40119c8b3ffd + false + + + + + false + true + cms_visit_log_ci + + + + + 21d47905e8cb686fc0435ca912ffc49c2ac18cf7 + false + + + + + false + true + cms_visit_log_fvt + + + + + d11720c8999e8c32966f6fa8749801abcb6dfbce + false + + + + + false + true + cms_visit_log_inv + + + + + 144fe1a3053ef69b5afeb0a9303d9e1636983d3c + false + + + + + false + true + cms_visit_log_ra + + + + + 5c4f4d350a1add35db1f8569b172e7c562c40f97 + false + + + + + false + true + cms_visit_log_sc + + + + + 422e64abc608e8fc88d0b60b9e292914b16b7b03 + false + + + + + false + true + cms_visit_log_uvid + + + + + aa81548cdaee0f75161c82ebc34ba8f6141f5672 + false + + + + + false + true + cms_visit_log_vd + + + + + daf8bca13ba345d6cdaa9301afba0c6854b4afbc + false + + + + + false + true + cms_visit_log_vt + + + + + 5f233be0ca30e83b57f6abc88b524fffcd083438 + false + + + + + false + true + idx_cms_visit_log_corpc + + + + + b8ea4b73d6d32a222e5abfd453287575ae518480 + false + + + + + + + + + +
+ + 9b64e1b1423721ed1a3ed528d26ce618594afada + 100 + 318 + Segoe UI + 9 + 1476 + 1032 + + 128 + 128 + 192 + + + + ba7ad6cfae5d14c954060bc6175002636dc8bfc2 + 388faee80ae30bf2d261c383395ea538ac65d139 + 9b64e1b1423721ed1a3ed528d26ce618594afada + -1 + -1 + -1 + -1 + + 0 + 0 + 0 + + 1..n + 1 + true + + RESTRICT + RESTRICT + null + null + + + 8559f44f6afb61f61673444d2a17d9a4cb43f57b + bf11ae38c484a6c743f51b05755262f3cf68e8d7 + 9b64e1b1423721ed1a3ed528d26ce618594afada + -1 + -1 + -1 + -1 + + 0 + 0 + 0 + + 1..n + 1 + true + + RESTRICT + RESTRICT + null + null + + + js_cms_article_tag + 文章与标签关系 + + + + + + + 3af42dafa08423c2c7dfe867c9cec403d09fde89 + eb5d114785c793115e222f88cbce9d6cda0f1543 + ba7ad6cfae5d14c954060bc6175002636dc8bfc2 + 栏目内容的编号 + + 内容编号 + article_id + varchar(n) + + + false + true + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 34e626c56b4e968630d15843006b3d3c34b49073 + 5045fa44fb0404a5984aab9f2cf32930b7e8df96 + 8559f44f6afb61f61673444d2a17d9a4cb43f57b + + + + + nvarchar(n) + + + false + true + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + + + + + + + +
+ + bf11ae38c484a6c743f51b05755262f3cf68e8d7 + 100 + 318 + Segoe UI + 9 + 1680 + 1176 + + 128 + 128 + 192 + + + + js_cms_tag + 内容标签 + + + + + + + fd1fe2bc7c729e16f6a70c1a3da1cbfbfdabb2e7 + 5045fa44fb0404a5984aab9f2cf32930b7e8df96 + + + + + nvarchar(n) + + + false + false + true + true + false + + + + + + + + + + + false + false + false + + + 0 + + + + 581244a112411170ac52781772032cf085b650c6 + 4d8e937f390abf82b84aaede33ccd04c973189fa + + + + + numeric(p) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + + + + + + + +
+ + 15937ffa7ff9e79679e5ee0d9aa009ae95db0348 + 204 + 478 + Segoe UI + 9 + 1480 + 1320 + + 128 + 128 + 192 + + + + js_cms_report + 内容举报表 + + + + + + + 869fc70cf3a4e92e8056b40814df8e03f9f9efde + 2358181fe16d4f3fc756d2f5c22f99eb13728c0a + + + + + varchar(n) + + + false + false + true + true + false + + + + + + + + + + + false + false + false + + + 0 + + + + 023f9dc616498f60530767741bd543ca80070de3 + d7bd7a4faed61e09992593cc523beb28a0c83b55 + + + + + character(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 8c838100145c0a8fd3f1ceba92027886c916c7f5 + 5ba1ca3f84fe6fbf34acfecc66e0031a812b3cf6 + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 3129303292f943bb8b9d07908286f0c6ed4aedcd + 260fcf70275e004e5cb7cb8707b191f1a6e483a2 + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + f4c59d5bc735102301e4e1d2ad1d5168d12e53f5 + eaae3f0c8552c2397873f87447f7eb1abdc15221 + + + + + character(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 2113020e467d973a4e0c408a0a26e74d6bb78e6e + fed117aa979da2f29a057833f25d99f2629c57b5 + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + + + + + + + +
+ + a64b64022c5b291e365f8bc84c6dcadd1a69b93f + 672 + 321 + Segoe UI + 9 + 1637 + 45 + + 128 + 128 + 192 + + + + 221fc0bc73b3badd39d437e05f24a752587a8a48 + 388faee80ae30bf2d261c383395ea538ac65d139 + a64b64022c5b291e365f8bc84c6dcadd1a69b93f + -1 + -1 + -1 + -1 + + 0 + 0 + 0 + + 1 + 1 + true + + RESTRICT + RESTRICT + null + null + + + js_cms_article_data + 文章详情表 + + + + + + + a1ea205b23430d5e2419ab6fc7b81e6a1063b163 + eb5d114785c793115e222f88cbce9d6cda0f1543 + 221fc0bc73b3badd39d437e05f24a752587a8a48 + + + + + varchar(n) + + + false + true + true + true + false + + + + + + + + + + + false + false + false + + + 0 + + + + cb2bc616bce32c0f61c17738422060cd80323cc2 + f2b4ec165eac4ea31d76132a98606f83c1b7c3f8 + + + + + longtext + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + f07d30b38dcf7c8a155495225eed8fb6f8fe706a + ab35e50baf172cfb277259d60316d292f2f6c597 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + f780d22bd4bf8e279c5016565e37f1b2cace44d7 + 52ca3f50c35dc1675c84185106a760fe5fd14211 + + + + + character(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + 118dab95fc1f792cd468b9f66af2d4fabd98c39b + + + + + + + + +
+ + 997e5f6051979df12c7498750e40f49280f37295 + 100 + 499 + Segoe UI + 9 + 1572 + 840 + + 128 + 128 + 192 + + + + e01bc71e345adba201c025470e4ea5992e610d23 + 388faee80ae30bf2d261c383395ea538ac65d139 + 997e5f6051979df12c7498750e40f49280f37295 + -1 + -1 + -1 + -1 + + 0 + 0 + 0 + + 1..n + 1 + true + + RESTRICT + RESTRICT + null + null + + + js_cms_article_posid + 文章推荐位 + + + + + + + 44aaef65b524bb63e467466470a99025376b001f + eb5d114785c793115e222f88cbce9d6cda0f1543 + e01bc71e345adba201c025470e4ea5992e610d23 + 栏目内容的编号 + + 内容编号 + article_id + varchar(n) + + + false + true + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 4882d2e2de114e7546c9b73add64c6bffbb0125d + bd580d568c1b2cf2a726ed789d8a755c1ed2ebdf + + + + + character(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + + + + + + + +
+ + 7f024bd90eec8d89290f4db163b3ea077d6ce26d + 1348 + 405 + Segoe UI + 9 + 564 + 45 + + 128 + 128 + 192 + + + + 8b10442357d1561bb946b77f486c97d2673bde4b + 02c2487dc0cf00bec5bb12635a6b2eaca8dce45b + 7f024bd90eec8d89290f4db163b3ea077d6ce26d + -1 + -1 + -1 + -1 + + 0 + 0 + 0 + + 1..n + 1 + true + + RESTRICT + RESTRICT + null + null + + + js_cms_category + 栏目表 + + + + + + + 162641e8c144235ea0f2fb55ed4b88c7e1c006bf + 0d993b7470d7bde3d20e9c7f24d1811518cf44cc + + + + + varchar(n) + + + false + false + true + true + false + + + + + + + + + + + false + false + false + + + 0 + + + a535b6c506004a7fdf4d48984c9ff2cfa59c157a + + b0280df85be5321ac35dd7904bd04fe457b7d09f + 3b97e52e25c24c77e03a9b78fad4426535a6aafd + + + + + nvarchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + f86eb0e3c56d958c2d1ee2c0ea77353b01b89973 + f51ed54a54f6cd6b1d74072be62c808f6848470c + 8b10442357d1561bb946b77f486c97d2673bde4b + + + + + varchar(n) + + + false + true + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + a478faefac3b31fe451d144c115eab04e02533d1 + 79b3fbe699e303c21335c291836b3f5593aa206c + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 38677895fbddee2a778976096fc554af0dbe3ede + 21bf89f56281674a78a844f355bcb369fba985e7 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 7df5a5ec366af21eeab7cf932b6c36a908570001 + f58a6d67f5350333488a9469d442fec790b4c9d6 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + dc3463864d84a4527e93c3d687067776de971558 + 229683cbe3d486c25f4b46624c787ec842d14f2a + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 146b4ca3cafb932a0474b6885799a84179426683 + 5d68d3e666fc97755fedc3ef791f438fedda5581 + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 4f08e0e3e3e8b8c34be9e05d95118c5add3d0b13 + 84cd10b6db6d10aac1e605b88e51b22ec06b63ea + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + a01a65e5fb2a04c46595d7d11cadd36673b441ad + d53d3c8a1026f5bde2747c545e1b78f294da7f56 + + + + + character(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 43fdb5b94b461a22605d5cd4488a59655fa00dc5 + f66206c046be58bb2c575069be681ef2a135551c + + + + + character(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + e9bcb01788ca210c5282fe9df263880768a8a421 + 8648e63a9b97fe54ef553105d7b5b8eef2c1b71f + + + + + character(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 76d25011f19ac67544dc8af547b2715c85df01cd + 7187ff36f855a4e82c0e1a0d6de0e605757014d2 + + + + + character(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + f780d22bd4bf8e279c5016565e37f1b2cace44d7 + 107135f4d6737d38cfd4ec44dd086240b11393db + + + + + character(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 549ced1875f9f9d6e9cdf6ba3a51eb75781a886e + b4bd194b30b49fbedf203ddffdd19a2aaedc0138 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 98dd48bc416b1ce6872885df8cec3e40044b1ea3 + c65d68fef1799df61f34daf6620be5cebfde3ebb + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 3dadc495eadb3f2e14472ff7f2869ab7b20d4cb5 + 0e766a93c3bec26b54b0c71ca3fc1c0f7d0ab838 + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + 35ae805d1da92afdb99b2fe8c536d1649356fccd + 118dab95fc1f792cd468b9f66af2d4fabd98c39b + + + + false + true + idx_cms_category_pc + + + + + 394369b90c0a5b6efeed3cf823c642605d7a1653 + false + + + + + false + true + idx_cms_category_ts + + + + + 23f973124aedd0244533f4e7b3b103c548b966be + false + + + + + false + true + idx_cms_category_status + + + + + f0036584bd8711715579d21994a0105935605a7e + false + + + + + false + true + idx_cms_category_tss + + + + + 984d5eac2b3221118a61655e4a5a49c78e0f0151 + false + + + + + + + + + +
+ + 388faee80ae30bf2d261c383395ea538ac65d139 + 750 + 405 + Segoe UI + 9 + 1092 + 48 + + 128 + 128 + 192 + + + + 102c612ebec0dcaf6a4a4270ed4683aea7346293 + 7f024bd90eec8d89290f4db163b3ea077d6ce26d + 388faee80ae30bf2d261c383395ea538ac65d139 + -1 + -1 + -1 + -1 + + 0 + 0 + 0 + + 1..n + 1 + true + + RESTRICT + RESTRICT + null + null + + + js_cms_article + 文章表 + + + + + + + 869fc70cf3a4e92e8056b40814df8e03f9f9efde + eb5d114785c793115e222f88cbce9d6cda0f1543 + + + + + varchar(n) + + + false + false + true + true + false + + + + + + + + + + + false + false + false + + + 0 + + + + dde1496bcd5d55330967cc24f53513e102a163c0 + 0d993b7470d7bde3d20e9c7f24d1811518cf44cc + 102c612ebec0dcaf6a4a4270ed4683aea7346293 + + + + + varchar(n) + + + false + true + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + a478faefac3b31fe451d144c115eab04e02533d1 + bd1a5ed3ac07f4338055d8a12c8146cae37c164c + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 2ade064238f63bf942781dc39267fe7f54e4692f + 37e50d5a25f2367cc57c056ee45ad5cb48810968 + + + + + nvarchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + f46eac64abba3044db1451ea94dbc46f4d888e9a + 7567aa8fbfa2799eb9807ae765a45afa51eae992 + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 45d160c563e186ec25cd93a0f7f56f0f9707d452 + 61c2101a6c97f7c9abceaba4a45d63d40eeafdc8 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + cdfdb56f0ba0532d4e4c01bb054ce75cbf07e959 + b07468735f2575b6de202a14eabc7ceba4a1c5df + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 146b4ca3cafb932a0474b6885799a84179426683 + f08dc2008900b7fbcdc7eb960b3c7e9c133031a4 + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 4f08e0e3e3e8b8c34be9e05d95118c5add3d0b13 + 2a7ae7d128a83d1adafdff9af86aa469aed2f338 + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 1a97c7c45f8e29ecae15b06520e90702bf5cdc85 + 382d9135460cf8d24c5c7f645b27f24b1fb766d1 + + + + + decimal(p) + + 0 + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 45cc4afa6cf6ab40e9af2ce5755dfb3c7a9e1db4 + e91726c8306698a6343c46de78c595fdc7e37d72 + + + + + datetime + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 80153420ce49ce7c3dde6b7bd1e0dce4efa88311 + 746a9c320ffec37eda33d7ad30a93ee64923f28b + + + + + character(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 4fd30a9613db6a1f261f57904adc7b0534734276 + 07eeddae2d3773cf417d15e8ed0c2265bb171874 + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 64d3c520e91a13dcd9f63fae7b177bb06e05be7a + 96483eea696711f59326da945873daf5fbdd3aa0 + + + + + decimal(p) + + 0 + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + b8d8a57b107565584ffde420f188c8c0d444487b + 641d9b4a2dea1fc445bb1290fb3ef0cc377b20d7 + + + + + numeric(p) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 47c3a25657ac2f136e12188e0134fe30928477f9 + 16343f2b171b860692297df77d27308e987b3471 + + + + + numeric(p) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 98afbf96d353f87ce0478e168869e56dfd4af462 + 3697e6e1dabca0cce7e3f2abb680b98f3dc14b96 + + + + + numeric(p) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 98dd48bc416b1ce6872885df8cec3e40044b1ea3 + a34855a3562f1820ebd2a1537f07a9fdacaab286 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 3dadc495eadb3f2e14472ff7f2869ab7b20d4cb5 + dcd2ddd1ebdabd4774839be4423c1fc9fd89d0ac + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + 35ae805d1da92afdb99b2fe8c536d1649356fccd + ea920cba2fe0eaee64a2310ece7cda4b198b37ec + + + + false + true + idx_cms_article_cb + + + + + c391a15752a8eb58bc558a39d1b431f7ee125e0e + false + + + + + false + true + idx_cms_article_cc + + + + + dde1496bcd5d55330967cc24f53513e102a163c0 + false + + + + + false + true + idx_cms_article_corp_code + + + + + b8ea4b73d6d32a222e5abfd453287575ae518480 + false + + + + + false + true + idx_cms_article_status + + + + + f0036584bd8711715579d21994a0105935605a7e + false + + + + + false + true + idx_cms_article_ud + + + + + f8ea4fc4a778a0b94398a661a1ed8608f0e8d28d + false + + + + + false + true + idx_cms_article_weight + + + + + 382d9135460cf8d24c5c7f645b27f24b1fb766d1 + false + + + + + + + + + +
+ + 18893974755ff1a6dc89f298885d6b0d571a8c7b + 516 + 383 + Segoe UI + 9 + 1056 + 996 + + 128 + 128 + 192 + + + + a2ee7f1aaf861f1faa23ba7763027fca76d6f48d + 388faee80ae30bf2d261c383395ea538ac65d139 + 18893974755ff1a6dc89f298885d6b0d571a8c7b + -1 + -1 + -1 + -1 + + 0 + 0 + 0 + + 1..n + 1 + true + + RESTRICT + RESTRICT + null + null + + + 52c8c967a2f0edf6dd988a9bb4cb00d6da008195 + 7f024bd90eec8d89290f4db163b3ea077d6ce26d + 18893974755ff1a6dc89f298885d6b0d571a8c7b + -1 + -1 + -1 + -1 + + 0 + 0 + 0 + + 1..n + 1 + true + + RESTRICT + RESTRICT + null + null + + + js_cms_comment + 文章评论表 + + + + + + + 869fc70cf3a4e92e8056b40814df8e03f9f9efde + 54f3bf02f4a2786c4d79239effed0560d06a2506 + + + + + varchar(n) + + + false + false + true + true + false + + + + + + + + + + + false + false + false + + + 0 + + + + 835faef487ae6874a525a8cb8ba19825f93091aa + 0d993b7470d7bde3d20e9c7f24d1811518cf44cc + 52c8c967a2f0edf6dd988a9bb4cb00d6da008195 + + + + + varchar(n) + + + false + true + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 41bd3c792a5a382accd971c4235c30842d0c051c + eb5d114785c793115e222f88cbce9d6cda0f1543 + a2ee7f1aaf861f1faa23ba7763027fca76d6f48d + + + 内容编号 + article_id + varchar(n) + + + false + true + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 6ba94d61743eaf1154092edf58fa87fcba5aaf3c + 12af69d900b4f137e87c95ac882720cb01912b7e + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 18423fee68730dc1c22be45168acf153e015b39b + 39078af05c1a3ab1323e0859582e0bfc8f2f7605 + + + + + nvarchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 71e860010ee137570b1fe15d54f8fc3ee5ccf7e5 + d3f60cc1222cb3bbc7d84b47028c677cf52a50e5 + + + + + nvarchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + ac4749308c644019a83c0a1932603bce674e8997 + a57b864623f2df4e556c1d367721949689f11545 + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 9264d171a6799492e2556fcd2ef63de54f817bb7 + a4c9fa6fedd5812cea2c8dee58cd514f37939e3a + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 1a3b3f8bccfce8894d117d6bdb0a6b104bfb80ef + 42ad3ccac5e8dfe17c5721e21e63cb9189473977 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + dba1aec0c72d79ea73ed4ebde07696cf4df174b7 + 623a8b5b174a3bc9fdbdb5c65ecd561a4bf65a40 + + + + + datetime + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 15c9658569b24151180e771838432db066fe41f1 + 0387a23bf7ea8e2f5857c4ae536700d9f6dc03f2 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 7a327bcd0e95fbbf6b724d05c14f085950fa0928 + ed3a282e11c83f8ebe01ed3f85e772e410e4c454 + + + + + datetime + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 276f29162989f309d85806ece156f0a9c37484f1 + fbcb204fc3da5e62abe9f90524f27b483acdeee3 + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + b8d8a57b107565584ffde420f188c8c0d444487b + 18b968329827c79290b0db10b00131e30f97047f + + + + + numeric(p) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 47c3a25657ac2f136e12188e0134fe30928477f9 + 84ea11032fe1a36de5fe346aa16142ad3d35a497 + + + + + numeric(p) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + da70970cf1f73a8092ba0abd5d7da6c2dfec55ce + 97a2c22c48e2b4049d84dd0a637491c0674512ea + + + + + character(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + ea920cba2fe0eaee64a2310ece7cda4b198b37ec + + + + false + true + idx_cms_comment_catc + + + + + 835faef487ae6874a525a8cb8ba19825f93091aa + false + + + + + false + true + idx_cms_comment_ai + + + + + 41bd3c792a5a382accd971c4235c30842d0c051c + false + + + + + false + true + idx_cms_comment_cc + + + + + b8ea4b73d6d32a222e5abfd453287575ae518480 + false + + + + + false + true + idx_cms_comment_status + + + + + 97a2c22c48e2b4049d84dd0a637491c0674512ea + false + + + + + + + + + +
+ + 02c2487dc0cf00bec5bb12635a6b2eaca8dce45b + 464 + 423 + Segoe UI + 9 + 52 + 48 + + 128 + 128 + 192 + + + + js_cms_site + 站点表 + + + + + + + f240879d6a1a961e639649e02beabfd37ef5319b + f51ed54a54f6cd6b1d74072be62c808f6848470c + + + + + varchar(n) + + + false + false + true + true + false + + + + + + + + + + + false + false + false + + + 0 + + + + 74dad2ed7366e74f74b96590df8b6bd758748b52 + 09eda0fb75fb20fff9ecefb569a44e9cd5f47491 + + + + + nvarchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + a602c1eeebe58e1a0a6d735ad1c32431059001fb + c1641887e5caa2d44efdf192693d34e644d3160d + + + + + decimal(p) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 189344c9d7084fbc3e0cb35296704bbdf757d5dd + a605e8a7ac657c636b1451487ff405c8a615e73c + + + + + nvarchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + be34a39fc2bdae09f8bc815c9994b6fff2eaaac5 + d2499d3351df9579fcbcc4c1f45286adb24fcf81 + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 7f40f312d59375e237ed0de76e696040d9550c13 + 5a0f8db9d1e706d8248f5c2fbfb9edcfb373618a + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 146b4ca3cafb932a0474b6885799a84179426683 + 7b44460b25fbdc4f63b3cd5e3edc3bac96924388 + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 4f08e0e3e3e8b8c34be9e05d95118c5add3d0b13 + 311d2d8a882c36968e57f78baa154d50c5c7a99b + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 61c82eaa83caf2d162e87179e8beb2f76d1af8ec + 667d7d9fad9b270d314690c04abfe9a75633d8da + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + cd22c62ad8eff35c93dc3f7753fc82fa8a63e34d + 3cba027f7b250b59a87215af752671980326b3e5 + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 79a00041672d16ea35bc08c824f8b9200a4acf9a + 15d8f8152057ebe557394121c7534643fd12ccb2 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + 35ae805d1da92afdb99b2fe8c536d1649356fccd + + + + false + true + idx_cms_site_status + + + + + f0036584bd8711715579d21994a0105935605a7e + false + + + + + + + + + +
+
+ + + 845c82ebd869d5620b1ef2c2b6f438b11a045082 + BaseEntity + + + 869fc70cf3a4e92e8056b40814df8e03f9f9efde + 02ecedc0de5850cba25bc91919ed39d414b74111 + + + + + varchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + ba0fb53af3ccc8b0e5d73baa58ec27fbb7973097 + 2fe6a36385238c1b21c76deae00a7afa00ff5538 + + + + + character(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + + + ea920cba2fe0eaee64a2310ece7cda4b198b37ec + BaseEntityCorp + + + 136ca02f1b3a96a8f2e242d5dd64d48f566143ef + b8ea4b73d6d32a222e5abfd453287575ae518480 + + + + + varchar(n) + + 0 + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + f116706ac00cd3a3ee88b2a88debf7ebc3eeb12d + b94f5fe344185c40739cf93d1090686001bb11e0 + + + + + nvarchar(n) + + JeeSite + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + + + 35ae805d1da92afdb99b2fe8c536d1649356fccd + DataEntity + + + 17718c2364a2368c2072da279c927d7ad3bfcf08 + f0036584bd8711715579d21994a0105935605a7e + + + + + character(n) + + 0 + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 1a3b3f8bccfce8894d117d6bdb0a6b104bfb80ef + c391a15752a8eb58bc558a39d1b431f7ee125e0e + + + + + varchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + dba1aec0c72d79ea73ed4ebde07696cf4df174b7 + e2e82ba86e15fd67397355e711255b1625078ae1 + + + + + datetime + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 2c6b290f30c6f9e100f6c77eab0cba7bb3386768 + fd0546fc2d4e01c35dcbc23913add68a99fabd73 + + + + + varchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + f0bdbc4002f4a1b7fb7c5026bc21a7689c549728 + f8ea4fc4a778a0b94398a661a1ed8608f0e8d28d + + + + + datetime + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 8f7d3761c17a1b8632d186a3c67cb08dca18c498 + 69e01b6d4f42df40a09540ef4ba10ed8e006abaa + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + + + 85024a2953cf3e3c9c1cce49b2351853ab0d125b + DataEntityNoStatus + + + 1a3b3f8bccfce8894d117d6bdb0a6b104bfb80ef + e5355faba5ec3c9128507dd4c48ea9230631cf83 + + + + + varchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + dba1aec0c72d79ea73ed4ebde07696cf4df174b7 + 6bed374c39d181003a4f92d76d79a4119176ba0c + + + + + datetime + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 2c6b290f30c6f9e100f6c77eab0cba7bb3386768 + f9db19bb567760bbdd554d75bbfdc891c89f9da9 + + + + + varchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + f0bdbc4002f4a1b7fb7c5026bc21a7689c549728 + ee78b079f7d319bf8119fd01439cd97424ff49fa + + + + + datetime + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 8f7d3761c17a1b8632d186a3c67cb08dca18c498 + f7b88ecec0ef386bb384c228842a7587432112fb + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + + + 118dab95fc1f792cd468b9f66af2d4fabd98c39b + ExtendEntity + + + ad6f9eff50476669df62b7601cbc3a2e0c905d36 + 6ccadddab6ce48441ca7abd798cda6f3debf4a0c + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 3a24133d2be4831e99d1319983e5393bcf964ff9 + 93ab0ba3b47b01934614dbd3e572358c9f99e6ea + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 40e1afbbad28d28e371dd1ab77fb56640b1cb66b + a78c7961910a5e697027d1a3530b1afaa8ea8c94 + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + a2d6b5a494fc1a3d29360d922296521c6640856b + 40085364ec7a58653e96f8659aadd258d7556bc7 + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 29f701cc6a308fbfc5b12b80fee621ceeb231dcc + 9787d7fe93ee31c5b4979fd620ff6e4b2777eccf + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + c9a37a7b6a5451930ca63e36814767f742cd1393 + 95c55b81b7e9e1a9bb01aa3d88fb90c648641c4e + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 8c26203d310a4e602cf0c0fc8a7b2c818219c1dc + 16f44dfc7964796f109293bc49afd58dcb4eec1f + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 54448f19b0f5d1630bf29f9f99787802c36ebddb + 39b1dffa083f74afc30df621845cf7f0ed71394f + + + + + nvarchar(n) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + a1d747cd40768ac9f85176518ee48cb513bae110 + 7584cc6360ae7edc99e1f619042eba5865b2c4c7 + + + + + decimal(p) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + a9f0e14d6691c397990abe4ef1ff21674dccf401 + f0b5383e05c6b3f6e5f65b33b33009826c83d014 + + + + + decimal(p) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 2ce06c5cf87d93bb1e3f47268dbc679be4b6dd8d + 260d5f31009fff18000d1e64f4f877926e621306 + + + + + decimal(p) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 53d8c730fcec69d341f44089817ae06eb4844278 + a83144f40e7ae64e46a4b4ed651379774a953b17 + + + + + decimal(p) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 4c0cc4ae32f8774cc319f516784430204aef0bdb + 2a5203a275171a250870cf6cb224a910aa9354ec + + + + + decimal(p,s) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 2e958c528620621985af4394590198feed57cdf9 + 3ef5bd65a7dcd74b9a9d8a292ec395f66b7de32b + + + + + decimal(p,s) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 7c25ad75662553c7d4a58fa66eb50ca7c0ffee59 + 01d0849bdda56a8d8f24befdadc3fc9b007ae92b + + + + + decimal(p,s) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 1f81990c9694963f032c302d1834b972a6f2eb74 + 1c8ed63d72f40f0fe2f05815675771bdf3f824f8 + + + + + decimal(p,s) + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + f01926071736b56b898949cc0720149c71504324 + 2b49e875138bfb329aaa352629650b7881435123 + + + + + datetime + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 942700093ab61c3be0bdf6b23bcba210bcc30281 + 5c6ec16226d85b0411b7077cb9a6e0c7aa8d74d1 + + + + + datetime + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + f221902bf89fe94dece8ccf309f59cc2c479d63f + d92b8f7fa7a2be49c7f00c447a603b136e84261d + + + + + datetime + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + c8d21e24bc69aac295703b0bae56269035b729f0 + 095a76f07a3cd2bdc6cc442757c11012e1974f4a + + + + + datetime + + + false + false + false + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + + + a535b6c506004a7fdf4d48984c9ff2cfa59c157a + TreeEntity + + + b18ce64a2a72d00b26515583d8bbfea282f30ea8 + 394369b90c0a5b6efeed3cf823c642605d7a1653 + + + + + varchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 63772c051414452204e91e8d0dabd1dbfd640326 + e8d877396943acfec73023dba2c1c6e3d7802d62 + + + + + varchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + be17e27c1f73fe128f00468cc83953077b7e00a9 + 23f973124aedd0244533f4e7b3b103c548b966be + + + + + decimal(p) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + b0bd388c14e5b2bbab9590f5247961a7edd9eb3b + 984d5eac2b3221118a61655e4a5a49c78e0f0151 + + + + + varchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 40b63ab3e485fd55370d6d04b063c4397483ebc1 + b2f246a3f0ade317eaa9915e2fd539abae5a5ec8 + + + + + character(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 3b9c3307b7140f27edeb47ffe307a662b2856627 + f5a9968479420f08da2e98d21136b3ed4b6e396f + + + + + decimal(p) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + 8f1564e5646071de508d4325f3cc7f62bdeede16 + 618194ebfc8c6c42efcef3a4af0b8054f6af209b + + + + + nvarchar(n) + + + false + false + true + false + false + + + + + + + + + + + false + false + false + + + 0 + + + + + + + + + + + + + +
diff --git a/modules/cms/db/db2/cms.sql b/modules/cms/db/db2/cms.sql new file mode 100644 index 00000000..9f9f0b71 --- /dev/null +++ b/modules/cms/db/db2/cms.sql @@ -0,0 +1,320 @@ + + +/* Create Tables */ + +-- 文章表 +CREATE TABLE js_cms_article +( + id varchar(64) NOT NULL, + category_code varchar(64) NOT NULL, + module_type varchar(50), + title vargraphic(255) NOT NULL, + href vargraphic(1000), + color varchar(50), + image vargraphic(1000), + keywords vargraphic(500), + description vargraphic(500), + weight decimal(10) DEFAULT 0, + weight_date timestamp, + source char(1), + copyfrom vargraphic(255), + hits decimal(20) DEFAULT 0, + hits_plus numeric(10), + hits_minus numeric(10), + word_count numeric(10), + custom_content_view varchar(255), + view_config vargraphic(1000), + status char(1) DEFAULT '0' NOT NULL, + create_by varchar(64) NOT NULL, + create_date timestamp NOT NULL, + update_by varchar(64) NOT NULL, + update_date timestamp NOT NULL, + remarks vargraphic(500), + corp_code varchar(64) DEFAULT '0' NOT NULL, + corp_name vargraphic(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +); + + +-- 文章详情表 +CREATE TABLE js_cms_article_data +( + id varchar(64) NOT NULL, + content clob, + relation varchar(1000), + is_can_comment char(1), + extend_s1 vargraphic(500), + extend_s2 vargraphic(500), + extend_s3 vargraphic(500), + extend_s4 vargraphic(500), + extend_s5 vargraphic(500), + extend_s6 vargraphic(500), + extend_s7 vargraphic(500), + extend_s8 vargraphic(500), + extend_i1 decimal(19), + extend_i2 decimal(19), + extend_i3 decimal(19), + extend_i4 decimal(19), + extend_f1 decimal(19,4), + extend_f2 decimal(19,4), + extend_f3 decimal(19,4), + extend_f4 decimal(19,4), + extend_d1 timestamp, + extend_d2 timestamp, + extend_d3 timestamp, + extend_d4 timestamp, + PRIMARY KEY (id) +); + + +-- 文章推荐位 +CREATE TABLE js_cms_article_posid +( + article_id varchar(64) NOT NULL, + postid char(1) NOT NULL +); + + +-- 文章与标签关系 +CREATE TABLE js_cms_article_tag +( + article_id varchar(64) NOT NULL, + tag_name vargraphic(200) NOT NULL +); + + +-- 栏目表 +CREATE TABLE js_cms_category +( + category_code varchar(64) NOT NULL, + parent_code varchar(64) NOT NULL, + parent_codes varchar(1000) NOT NULL, + tree_sort decimal(10) NOT NULL, + tree_sorts varchar(1000) NOT NULL, + tree_leaf char(1) NOT NULL, + tree_level decimal(4) NOT NULL, + tree_names vargraphic(1000) NOT NULL, + category_name vargraphic(100) NOT NULL, + site_code varchar(64) NOT NULL, + module_type varchar(50), + image varchar(255), + href varchar(255), + target varchar(20), + keywords vargraphic(500), + description vargraphic(500), + in_menu char(1), + in_list char(1), + show_modes char(1), + is_need_audit char(1), + is_can_comment char(1), + custom_list_view varchar(255), + custom_content_view varchar(255), + view_config vargraphic(1000), + status char(1) DEFAULT '0' NOT NULL, + create_by varchar(64) NOT NULL, + create_date timestamp NOT NULL, + update_by varchar(64) NOT NULL, + update_date timestamp NOT NULL, + remarks vargraphic(500), + extend_s1 vargraphic(500), + extend_s2 vargraphic(500), + extend_s3 vargraphic(500), + extend_s4 vargraphic(500), + extend_s5 vargraphic(500), + extend_s6 vargraphic(500), + extend_s7 vargraphic(500), + extend_s8 vargraphic(500), + extend_i1 decimal(19), + extend_i2 decimal(19), + extend_i3 decimal(19), + extend_i4 decimal(19), + extend_f1 decimal(19,4), + extend_f2 decimal(19,4), + extend_f3 decimal(19,4), + extend_f4 decimal(19,4), + extend_d1 timestamp, + extend_d2 timestamp, + extend_d3 timestamp, + extend_d4 timestamp, + PRIMARY KEY (category_code) +); + + +-- 栏目与角色关联表 +CREATE TABLE js_cms_category_role +( + category_code varchar(64) NOT NULL, + role_code varchar(64) NOT NULL, + ctrl_type varchar(32), + PRIMARY KEY (category_code, role_code) +); + + +-- 文章评论表 +CREATE TABLE js_cms_comment +( + id varchar(64) NOT NULL, + category_code varchar(64) NOT NULL, + article_id varchar(64) NOT NULL, + parent_id varchar(64), + article_title vargraphic(255) NOT NULL, + content vargraphic(255) NOT NULL, + name vargraphic(50), + ip varchar(100), + create_by varchar(64), + create_date timestamp NOT NULL, + audit_user_code varchar(64), + audit_date timestamp, + audit_comment vargraphic(200), + hits_plus numeric(10), + hits_minus numeric(10), + status char(1) NOT NULL, + corp_code varchar(64) DEFAULT '0' NOT NULL, + corp_name vargraphic(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +); + + +-- 留言板表 +CREATE TABLE js_cms_guestbook +( + id varchar(64) NOT NULL, + type char(1) NOT NULL, + content varchar(255) NOT NULL, + name varchar(100) NOT NULL, + email varchar(100) NOT NULL, + phone varchar(100) NOT NULL, + workunit varchar(100) NOT NULL, + ip varchar(100) NOT NULL, + create_by varchar(64), + create_date timestamp, + re_user_code varchar(64), + re_date timestamp, + re_content varchar(100), + status char(1) NOT NULL, + corp_code varchar(64) DEFAULT '0' NOT NULL, + corp_name vargraphic(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +); + + +-- 内容举报表 +CREATE TABLE js_cms_report +( + id varchar(64) NOT NULL, + report_source char(1), + report_content vargraphic(500), + report_url vargraphic(1000), + report_type char(1), + report_cause vargraphic(500), + PRIMARY KEY (id) +); + + +-- 站点表 +CREATE TABLE js_cms_site +( + site_code varchar(64) NOT NULL, + site_name vargraphic(100) NOT NULL, + site_sort decimal(10), + title vargraphic(100) NOT NULL, + logo vargraphic(1000), + domain vargraphic(500), + keywords vargraphic(500), + description vargraphic(500), + theme vargraphic(500), + copyright vargraphic(1000), + custom_index_view varchar(500), + status char(1) DEFAULT '0' NOT NULL, + create_by varchar(64) NOT NULL, + create_date timestamp NOT NULL, + update_by varchar(64) NOT NULL, + update_date timestamp NOT NULL, + remarks vargraphic(500), + PRIMARY KEY (site_code) +); + + +-- 内容标签 +CREATE TABLE js_cms_tag +( + tag_name vargraphic(200) NOT NULL, + clicknum numeric(10) NOT NULL, + PRIMARY KEY (tag_name) +); + + +-- 访问日志表 +CREATE TABLE js_cms_visit_log +( + id varchar(64) NOT NULL, + request_url vargraphic(1000), + request_url_host varchar(128), + source_referer vargraphic(1000), + source_referer_host varchar(128), + source_type char(1), + search_engine varchar(200), + search_word vargraphic(200), + remote_addr varchar(50), + user_agent vargraphic(500), + user_language varchar(32), + user_screen_size varchar(32), + user_device varchar(32), + user_os_name varchar(32), + user_browser varchar(32), + user_browser_version varchar(16), + unique_visit_id varchar(64), + visit_date char(8), + visit_time timestamp, + is_new_visit char(1), + first_visit_time decimal(20), + prev_remain_time decimal(20), + total_remain_time decimal(20), + site_code varchar(64), + site_name vargraphic(100), + category_code varchar(64), + category_name vargraphic(100), + content_id varchar(64), + content_title vargraphic(255), + visit_user_code varchar(100), + visit_user_name varchar(100), + corp_code varchar(64) DEFAULT '0' NOT NULL, + corp_name vargraphic(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +); + + + +/* Create Indexes */ + +CREATE INDEX idx_cms_article_cb ON js_cms_article (create_by); +CREATE INDEX idx_cms_article_cc ON js_cms_article (category_code); +CREATE INDEX idx_cms_article_corp_code ON js_cms_article (corp_code); +CREATE INDEX idx_cms_article_status ON js_cms_article (status); +CREATE INDEX idx_cms_article_ud ON js_cms_article (update_date); +CREATE INDEX idx_cms_article_weight ON js_cms_article (weight); +CREATE INDEX idx_cms_category_pc ON js_cms_category (parent_code); +CREATE INDEX idx_cms_category_ts ON js_cms_category (tree_sort); +CREATE INDEX idx_cms_category_status ON js_cms_category (status); +CREATE INDEX idx_cms_category_tss ON js_cms_category (tree_sorts); +CREATE INDEX idx_cms_comment_catc ON js_cms_comment (category_code); +CREATE INDEX idx_cms_comment_ai ON js_cms_comment (article_id); +CREATE INDEX idx_cms_comment_cc ON js_cms_comment (corp_code); +CREATE INDEX idx_cms_comment_status ON js_cms_comment (status); +CREATE INDEX idx_cms_guestbook_cc ON js_cms_guestbook (corp_code); +CREATE INDEX idx_cms_guestbook_status ON js_cms_guestbook (status); +CREATE INDEX idx_cms_guestbook_type ON js_cms_guestbook (type); +CREATE INDEX idx_cms_site_status ON js_cms_site (status); +CREATE INDEX cms_visit_log_cc ON js_cms_visit_log (category_code); +CREATE INDEX cms_visit_log_ci ON js_cms_visit_log (content_id); +CREATE INDEX cms_visit_log_fvt ON js_cms_visit_log (first_visit_time); +CREATE INDEX cms_visit_log_inv ON js_cms_visit_log (is_new_visit); +CREATE INDEX cms_visit_log_ra ON js_cms_visit_log (remote_addr); +CREATE INDEX cms_visit_log_sc ON js_cms_visit_log (site_code); +CREATE INDEX cms_visit_log_uvid ON js_cms_visit_log (unique_visit_id); +CREATE INDEX cms_visit_log_vd ON js_cms_visit_log (visit_date); +CREATE INDEX cms_visit_log_vt ON js_cms_visit_log (visit_time); +CREATE INDEX idx_cms_visit_log_corpc ON js_cms_visit_log (corp_code); + + + diff --git a/modules/cms/db/h2/cms.sql b/modules/cms/db/h2/cms.sql new file mode 100644 index 00000000..03bc1a56 --- /dev/null +++ b/modules/cms/db/h2/cms.sql @@ -0,0 +1,320 @@ + + +/* Create Tables */ + +-- 文章表 +CREATE TABLE js_cms_article +( + id varchar(64) NOT NULL, + category_code varchar(64) NOT NULL, + module_type varchar(50), + title varchar(255) NOT NULL, + href varchar(1000), + color varchar(50), + image varchar(1000), + keywords varchar(500), + description varchar(500), + weight decimal(10) DEFAULT 0, + weight_date datetime, + source char(1), + copyfrom varchar(255), + hits decimal(20) DEFAULT 0, + hits_plus numeric(10), + hits_minus numeric(10), + word_count numeric(10), + custom_content_view varchar(255), + view_config varchar(1000), + status char(1) DEFAULT '0' NOT NULL, + create_by varchar(64) NOT NULL, + create_date datetime NOT NULL, + update_by varchar(64) NOT NULL, + update_date datetime NOT NULL, + remarks varchar(500), + corp_code varchar(64) DEFAULT '0' NOT NULL, + corp_name varchar(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +); + + +-- 文章详情表 +CREATE TABLE js_cms_article_data +( + id varchar(64) NOT NULL, + content clob, + relation varchar(1000), + is_can_comment char(1), + extend_s1 varchar(500), + extend_s2 varchar(500), + extend_s3 varchar(500), + extend_s4 varchar(500), + extend_s5 varchar(500), + extend_s6 varchar(500), + extend_s7 varchar(500), + extend_s8 varchar(500), + extend_i1 decimal(19), + extend_i2 decimal(19), + extend_i3 decimal(19), + extend_i4 decimal(19), + extend_f1 decimal(19,4), + extend_f2 decimal(19,4), + extend_f3 decimal(19,4), + extend_f4 decimal(19,4), + extend_d1 datetime, + extend_d2 datetime, + extend_d3 datetime, + extend_d4 datetime, + PRIMARY KEY (id) +); + + +-- 文章推荐位 +CREATE TABLE js_cms_article_posid +( + article_id varchar(64) NOT NULL, + postid char(1) NOT NULL +); + + +-- 文章与标签关系 +CREATE TABLE js_cms_article_tag +( + article_id varchar(64) NOT NULL, + tag_name varchar(200) NOT NULL +); + + +-- 栏目表 +CREATE TABLE js_cms_category +( + category_code varchar(64) NOT NULL, + parent_code varchar(64) NOT NULL, + parent_codes varchar(1000) NOT NULL, + tree_sort decimal(10) NOT NULL, + tree_sorts varchar(1000) NOT NULL, + tree_leaf char(1) NOT NULL, + tree_level decimal(4) NOT NULL, + tree_names varchar(1000) NOT NULL, + category_name varchar(100) NOT NULL, + site_code varchar(64) NOT NULL, + module_type varchar(50), + image varchar(255), + href varchar(255), + target varchar(20), + keywords varchar(500), + description varchar(500), + in_menu char(1), + in_list char(1), + show_modes char(1), + is_need_audit char(1), + is_can_comment char(1), + custom_list_view varchar(255), + custom_content_view varchar(255), + view_config varchar(1000), + status char(1) DEFAULT '0' NOT NULL, + create_by varchar(64) NOT NULL, + create_date datetime NOT NULL, + update_by varchar(64) NOT NULL, + update_date datetime NOT NULL, + remarks varchar(500), + extend_s1 varchar(500), + extend_s2 varchar(500), + extend_s3 varchar(500), + extend_s4 varchar(500), + extend_s5 varchar(500), + extend_s6 varchar(500), + extend_s7 varchar(500), + extend_s8 varchar(500), + extend_i1 decimal(19), + extend_i2 decimal(19), + extend_i3 decimal(19), + extend_i4 decimal(19), + extend_f1 decimal(19,4), + extend_f2 decimal(19,4), + extend_f3 decimal(19,4), + extend_f4 decimal(19,4), + extend_d1 datetime, + extend_d2 datetime, + extend_d3 datetime, + extend_d4 datetime, + PRIMARY KEY (category_code) +); + + +-- 栏目与角色关联表 +CREATE TABLE js_cms_category_role +( + category_code varchar(64) NOT NULL, + role_code varchar(64) NOT NULL, + ctrl_type varchar(32), + PRIMARY KEY (category_code, role_code) +); + + +-- 文章评论表 +CREATE TABLE js_cms_comment +( + id varchar(64) NOT NULL, + category_code varchar(64) NOT NULL, + article_id varchar(64) NOT NULL, + parent_id varchar(64), + article_title varchar(255) NOT NULL, + content varchar(255) NOT NULL, + name varchar(50), + ip varchar(100), + create_by varchar(64), + create_date datetime NOT NULL, + audit_user_code varchar(64), + audit_date datetime, + audit_comment varchar(200), + hits_plus numeric(10), + hits_minus numeric(10), + status char(1) NOT NULL, + corp_code varchar(64) DEFAULT '0' NOT NULL, + corp_name varchar(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +); + + +-- 留言板表 +CREATE TABLE js_cms_guestbook +( + id varchar(64) NOT NULL, + type char(1) NOT NULL, + content varchar(255) NOT NULL, + name varchar(100) NOT NULL, + email varchar(100) NOT NULL, + phone varchar(100) NOT NULL, + workunit varchar(100) NOT NULL, + ip varchar(100) NOT NULL, + create_by varchar(64), + create_date datetime, + re_user_code varchar(64), + re_date datetime, + re_content varchar(100), + status char(1) NOT NULL, + corp_code varchar(64) DEFAULT '0' NOT NULL, + corp_name varchar(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +); + + +-- 内容举报表 +CREATE TABLE js_cms_report +( + id varchar(64) NOT NULL, + report_source char(1), + report_content varchar(500), + report_url varchar(1000), + report_type char(1), + report_cause varchar(500), + PRIMARY KEY (id) +); + + +-- 站点表 +CREATE TABLE js_cms_site +( + site_code varchar(64) NOT NULL, + site_name varchar(100) NOT NULL, + site_sort decimal(10), + title varchar(100) NOT NULL, + logo varchar(1000), + domain varchar(500), + keywords varchar(500), + description varchar(500), + theme varchar(500), + copyright varchar(1000), + custom_index_view varchar(500), + status char(1) DEFAULT '0' NOT NULL, + create_by varchar(64) NOT NULL, + create_date datetime NOT NULL, + update_by varchar(64) NOT NULL, + update_date datetime NOT NULL, + remarks varchar(500), + PRIMARY KEY (site_code) +); + + +-- 内容标签 +CREATE TABLE js_cms_tag +( + tag_name varchar(200) NOT NULL, + clicknum numeric(10) NOT NULL, + PRIMARY KEY (tag_name) +); + + +-- 访问日志表 +CREATE TABLE js_cms_visit_log +( + id varchar(64) NOT NULL, + request_url varchar(1000), + request_url_host varchar(128), + source_referer varchar(1000), + source_referer_host varchar(128), + source_type char(1), + search_engine varchar(200), + search_word varchar(200), + remote_addr varchar(50), + user_agent varchar(500), + user_language varchar(32), + user_screen_size varchar(32), + user_device varchar(32), + user_os_name varchar(32), + user_browser varchar(32), + user_browser_version varchar(16), + unique_visit_id varchar(64), + visit_date char(8), + visit_time datetime, + is_new_visit char(1), + first_visit_time decimal(20), + prev_remain_time decimal(20), + total_remain_time decimal(20), + site_code varchar(64), + site_name varchar(100), + category_code varchar(64), + category_name varchar(100), + content_id varchar(64), + content_title varchar(255), + visit_user_code varchar(100), + visit_user_name varchar(100), + corp_code varchar(64) DEFAULT '0' NOT NULL, + corp_name varchar(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +); + + + +/* Create Indexes */ + +CREATE INDEX idx_cms_article_cb ON js_cms_article (create_by); +CREATE INDEX idx_cms_article_cc ON js_cms_article (category_code); +CREATE INDEX idx_cms_article_corp_code ON js_cms_article (corp_code); +CREATE INDEX idx_cms_article_status ON js_cms_article (status); +CREATE INDEX idx_cms_article_ud ON js_cms_article (update_date); +CREATE INDEX idx_cms_article_weight ON js_cms_article (weight); +CREATE INDEX idx_cms_category_pc ON js_cms_category (parent_code); +CREATE INDEX idx_cms_category_ts ON js_cms_category (tree_sort); +CREATE INDEX idx_cms_category_status ON js_cms_category (status); +CREATE INDEX idx_cms_category_tss ON js_cms_category (tree_sorts); +CREATE INDEX idx_cms_comment_catc ON js_cms_comment (category_code); +CREATE INDEX idx_cms_comment_ai ON js_cms_comment (article_id); +CREATE INDEX idx_cms_comment_cc ON js_cms_comment (corp_code); +CREATE INDEX idx_cms_comment_status ON js_cms_comment (status); +CREATE INDEX idx_cms_guestbook_cc ON js_cms_guestbook (corp_code); +CREATE INDEX idx_cms_guestbook_status ON js_cms_guestbook (status); +CREATE INDEX idx_cms_guestbook_type ON js_cms_guestbook (type); +CREATE INDEX idx_cms_site_status ON js_cms_site (status); +CREATE INDEX cms_visit_log_cc ON js_cms_visit_log (category_code); +CREATE INDEX cms_visit_log_ci ON js_cms_visit_log (content_id); +CREATE INDEX cms_visit_log_fvt ON js_cms_visit_log (first_visit_time); +CREATE INDEX cms_visit_log_inv ON js_cms_visit_log (is_new_visit); +CREATE INDEX cms_visit_log_ra ON js_cms_visit_log (remote_addr); +CREATE INDEX cms_visit_log_sc ON js_cms_visit_log (site_code); +CREATE INDEX cms_visit_log_uvid ON js_cms_visit_log (unique_visit_id); +CREATE INDEX cms_visit_log_vd ON js_cms_visit_log (visit_date); +CREATE INDEX cms_visit_log_vt ON js_cms_visit_log (visit_time); +CREATE INDEX idx_cms_visit_log_corpc ON js_cms_visit_log (corp_code); + + + diff --git a/modules/cms/db/mssql/cms.sql b/modules/cms/db/mssql/cms.sql new file mode 100644 index 00000000..ec373e68 --- /dev/null +++ b/modules/cms/db/mssql/cms.sql @@ -0,0 +1,320 @@ + + +/* Create Tables */ + +-- 文章表 +CREATE TABLE [js_cms_article] +( + [id] varchar(64) NOT NULL, + [category_code] varchar(64) NOT NULL, + [module_type] varchar(50), + [title] nvarchar(255) NOT NULL, + [href] nvarchar(1000), + [color] varchar(50), + [image] nvarchar(1000), + [keywords] nvarchar(500), + [description] nvarchar(500), + [weight] decimal(10) DEFAULT 0, + [weight_date] datetime, + [source] char(1), + [copyfrom] nvarchar(255), + [hits] decimal(20) DEFAULT 0, + [hits_plus] numeric(10), + [hits_minus] numeric(10), + [word_count] numeric(10), + [custom_content_view] varchar(255), + [view_config] nvarchar(1000), + [status] char(1) DEFAULT '0' NOT NULL, + [create_by] varchar(64) NOT NULL, + [create_date] datetime NOT NULL, + [update_by] varchar(64) NOT NULL, + [update_date] datetime NOT NULL, + [remarks] nvarchar(500), + [corp_code] varchar(64) DEFAULT '0' NOT NULL, + [corp_name] nvarchar(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY ([id]) +); + + +-- 文章详情表 +CREATE TABLE [js_cms_article_data] +( + [id] varchar(64) NOT NULL, + [content] text, + [relation] varchar(1000), + [is_can_comment] char(1), + [extend_s1] nvarchar(500), + [extend_s2] nvarchar(500), + [extend_s3] nvarchar(500), + [extend_s4] nvarchar(500), + [extend_s5] nvarchar(500), + [extend_s6] nvarchar(500), + [extend_s7] nvarchar(500), + [extend_s8] nvarchar(500), + [extend_i1] decimal(19), + [extend_i2] decimal(19), + [extend_i3] decimal(19), + [extend_i4] decimal(19), + [extend_f1] decimal(19,4), + [extend_f2] decimal(19,4), + [extend_f3] decimal(19,4), + [extend_f4] decimal(19,4), + [extend_d1] datetime, + [extend_d2] datetime, + [extend_d3] datetime, + [extend_d4] datetime, + PRIMARY KEY ([id]) +); + + +-- 文章推荐位 +CREATE TABLE [js_cms_article_posid] +( + [article_id] varchar(64) NOT NULL, + [postid] char(1) NOT NULL +); + + +-- 文章与标签关系 +CREATE TABLE [js_cms_article_tag] +( + [article_id] varchar(64) NOT NULL, + [tag_name] nvarchar(200) NOT NULL +); + + +-- 栏目表 +CREATE TABLE [js_cms_category] +( + [category_code] varchar(64) NOT NULL, + [parent_code] varchar(64) NOT NULL, + [parent_codes] varchar(1000) NOT NULL, + [tree_sort] decimal(10) NOT NULL, + [tree_sorts] varchar(1000) NOT NULL, + [tree_leaf] char(1) NOT NULL, + [tree_level] decimal(4) NOT NULL, + [tree_names] nvarchar(1000) NOT NULL, + [category_name] nvarchar(100) NOT NULL, + [site_code] varchar(64) NOT NULL, + [module_type] varchar(50), + [image] varchar(255), + [href] varchar(255), + [target] varchar(20), + [keywords] nvarchar(500), + [description] nvarchar(500), + [in_menu] char(1), + [in_list] char(1), + [show_modes] char(1), + [is_need_audit] char(1), + [is_can_comment] char(1), + [custom_list_view] varchar(255), + [custom_content_view] varchar(255), + [view_config] nvarchar(1000), + [status] char(1) DEFAULT '0' NOT NULL, + [create_by] varchar(64) NOT NULL, + [create_date] datetime NOT NULL, + [update_by] varchar(64) NOT NULL, + [update_date] datetime NOT NULL, + [remarks] nvarchar(500), + [extend_s1] nvarchar(500), + [extend_s2] nvarchar(500), + [extend_s3] nvarchar(500), + [extend_s4] nvarchar(500), + [extend_s5] nvarchar(500), + [extend_s6] nvarchar(500), + [extend_s7] nvarchar(500), + [extend_s8] nvarchar(500), + [extend_i1] decimal(19), + [extend_i2] decimal(19), + [extend_i3] decimal(19), + [extend_i4] decimal(19), + [extend_f1] decimal(19,4), + [extend_f2] decimal(19,4), + [extend_f3] decimal(19,4), + [extend_f4] decimal(19,4), + [extend_d1] datetime, + [extend_d2] datetime, + [extend_d3] datetime, + [extend_d4] datetime, + PRIMARY KEY ([category_code]) +); + + +-- 栏目与角色关联表 +CREATE TABLE [js_cms_category_role] +( + [category_code] varchar(64) NOT NULL, + [role_code] varchar(64) NOT NULL, + [ctrl_type] varchar(32), + PRIMARY KEY ([category_code], [role_code]) +); + + +-- 文章评论表 +CREATE TABLE [js_cms_comment] +( + [id] varchar(64) NOT NULL, + [category_code] varchar(64) NOT NULL, + [article_id] varchar(64) NOT NULL, + [parent_id] varchar(64), + [article_title] nvarchar(255) NOT NULL, + [content] nvarchar(255) NOT NULL, + [name] nvarchar(50), + [ip] varchar(100), + [create_by] varchar(64), + [create_date] datetime NOT NULL, + [audit_user_code] varchar(64), + [audit_date] datetime, + [audit_comment] nvarchar(200), + [hits_plus] numeric(10), + [hits_minus] numeric(10), + [status] char(1) NOT NULL, + [corp_code] varchar(64) DEFAULT '0' NOT NULL, + [corp_name] nvarchar(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY ([id]) +); + + +-- 留言板表 +CREATE TABLE [js_cms_guestbook] +( + [id] varchar(64) NOT NULL, + [type] char(1) NOT NULL, + [content] varchar(255) NOT NULL, + [name] varchar(100) NOT NULL, + [email] varchar(100) NOT NULL, + [phone] varchar(100) NOT NULL, + [workunit] varchar(100) NOT NULL, + [ip] varchar(100) NOT NULL, + [create_by] varchar(64), + [create_date] datetime, + [re_user_code] varchar(64), + [re_date] datetime, + [re_content] varchar(100), + [status] char(1) NOT NULL, + [corp_code] varchar(64) DEFAULT '0' NOT NULL, + [corp_name] nvarchar(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY ([id]) +); + + +-- 内容举报表 +CREATE TABLE [js_cms_report] +( + [id] varchar(64) NOT NULL, + [report_source] char(1), + [report_content] nvarchar(500), + [report_url] nvarchar(1000), + [report_type] char(1), + [report_cause] nvarchar(500), + PRIMARY KEY ([id]) +); + + +-- 站点表 +CREATE TABLE [js_cms_site] +( + [site_code] varchar(64) NOT NULL, + [site_name] nvarchar(100) NOT NULL, + [site_sort] decimal(10), + [title] nvarchar(100) NOT NULL, + [logo] nvarchar(1000), + [domain] nvarchar(500), + [keywords] nvarchar(500), + [description] nvarchar(500), + [theme] nvarchar(500), + [copyright] nvarchar(1000), + [custom_index_view] varchar(500), + [status] char(1) DEFAULT '0' NOT NULL, + [create_by] varchar(64) NOT NULL, + [create_date] datetime NOT NULL, + [update_by] varchar(64) NOT NULL, + [update_date] datetime NOT NULL, + [remarks] nvarchar(500), + PRIMARY KEY ([site_code]) +); + + +-- 内容标签 +CREATE TABLE [js_cms_tag] +( + [tag_name] nvarchar(200) NOT NULL, + [clicknum] numeric(10) NOT NULL, + PRIMARY KEY ([tag_name]) +); + + +-- 访问日志表 +CREATE TABLE [js_cms_visit_log] +( + [id] varchar(64) NOT NULL, + [request_url] nvarchar(1000), + [request_url_host] varchar(128), + [source_referer] nvarchar(1000), + [source_referer_host] varchar(128), + [source_type] char(1), + [search_engine] varchar(200), + [search_word] nvarchar(200), + [remote_addr] varchar(50), + [user_agent] nvarchar(500), + [user_language] varchar(32), + [user_screen_size] varchar(32), + [user_device] varchar(32), + [user_os_name] varchar(32), + [user_browser] varchar(32), + [user_browser_version] varchar(16), + [unique_visit_id] varchar(64), + [visit_date] char(8), + [visit_time] datetime, + [is_new_visit] char(1), + [first_visit_time] decimal(20), + [prev_remain_time] decimal(20), + [total_remain_time] decimal(20), + [site_code] varchar(64), + [site_name] nvarchar(100), + [category_code] varchar(64), + [category_name] nvarchar(100), + [content_id] varchar(64), + [content_title] nvarchar(255), + [visit_user_code] varchar(100), + [visit_user_name] varchar(100), + [corp_code] varchar(64) DEFAULT '0' NOT NULL, + [corp_name] nvarchar(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY ([id]) +); + + + +/* Create Indexes */ + +CREATE INDEX [idx_cms_article_cb] ON [js_cms_article] ([create_by]); +CREATE INDEX [idx_cms_article_cc] ON [js_cms_article] ([category_code]); +CREATE INDEX [idx_cms_article_corp_code] ON [js_cms_article] ([corp_code]); +CREATE INDEX [idx_cms_article_status] ON [js_cms_article] ([status]); +CREATE INDEX [idx_cms_article_ud] ON [js_cms_article] ([update_date]); +CREATE INDEX [idx_cms_article_weight] ON [js_cms_article] ([weight]); +CREATE INDEX [idx_cms_category_pc] ON [js_cms_category] ([parent_code]); +CREATE INDEX [idx_cms_category_ts] ON [js_cms_category] ([tree_sort]); +CREATE INDEX [idx_cms_category_status] ON [js_cms_category] ([status]); +CREATE INDEX [idx_cms_category_tss] ON [js_cms_category] ([tree_sorts]); +CREATE INDEX [idx_cms_comment_catc] ON [js_cms_comment] ([category_code]); +CREATE INDEX [idx_cms_comment_ai] ON [js_cms_comment] ([article_id]); +CREATE INDEX [idx_cms_comment_cc] ON [js_cms_comment] ([corp_code]); +CREATE INDEX [idx_cms_comment_status] ON [js_cms_comment] ([status]); +CREATE INDEX [idx_cms_guestbook_cc] ON [js_cms_guestbook] ([corp_code]); +CREATE INDEX [idx_cms_guestbook_status] ON [js_cms_guestbook] ([status]); +CREATE INDEX [idx_cms_guestbook_type] ON [js_cms_guestbook] ([type]); +CREATE INDEX [idx_cms_site_status] ON [js_cms_site] ([status]); +CREATE INDEX [cms_visit_log_cc] ON [js_cms_visit_log] ([category_code]); +CREATE INDEX [cms_visit_log_ci] ON [js_cms_visit_log] ([content_id]); +CREATE INDEX [cms_visit_log_fvt] ON [js_cms_visit_log] ([first_visit_time]); +CREATE INDEX [cms_visit_log_inv] ON [js_cms_visit_log] ([is_new_visit]); +CREATE INDEX [cms_visit_log_ra] ON [js_cms_visit_log] ([remote_addr]); +CREATE INDEX [cms_visit_log_sc] ON [js_cms_visit_log] ([site_code]); +CREATE INDEX [cms_visit_log_uvid] ON [js_cms_visit_log] ([unique_visit_id]); +CREATE INDEX [cms_visit_log_vd] ON [js_cms_visit_log] ([visit_date]); +CREATE INDEX [cms_visit_log_vt] ON [js_cms_visit_log] ([visit_time]); +CREATE INDEX [idx_cms_visit_log_corpc] ON [js_cms_visit_log] ([corp_code]); + + + diff --git a/modules/cms/db/mysql/cms.sql b/modules/cms/db/mysql/cms.sql new file mode 100644 index 00000000..b9db4d32 --- /dev/null +++ b/modules/cms/db/mysql/cms.sql @@ -0,0 +1,321 @@ +SET SESSION FOREIGN_KEY_CHECKS=0; + + +/* Create Tables */ + +-- 文章表 +CREATE TABLE js_cms_article +( + id varchar(64) NOT NULL COMMENT '编号', + category_code varchar(64) NOT NULL COMMENT '栏目编码', + module_type varchar(50) COMMENT '模块类型', + title varchar(255) NOT NULL COMMENT '内容标题', + href varchar(1000) COMMENT '外部链接', + color varchar(50) COMMENT '标题颜色', + image varchar(1000) COMMENT '内容图片', + keywords varchar(500) COMMENT '关键字', + description varchar(500) COMMENT '描述', + weight decimal(10) DEFAULT 0 COMMENT '权重,越大越靠前', + weight_date datetime COMMENT '权重期限', + source char(1) COMMENT '来源(转载/原创)', + copyfrom varchar(255) COMMENT '文章来源出处', + hits decimal(20) DEFAULT 0 COMMENT '点击数', + hits_plus numeric(10) COMMENT '支持数', + hits_minus numeric(10) COMMENT '反对数', + word_count numeric(10) COMMENT '字数(不包含html)', + custom_content_view varchar(255) COMMENT '自定义内容视图', + view_config varchar(1000) COMMENT '视图配置', + status char(1) DEFAULT '0' NOT NULL COMMENT '状态(0正常 1删除 2停用)', + create_by varchar(64) NOT NULL COMMENT '创建者', + create_date datetime NOT NULL COMMENT '创建时间', + update_by varchar(64) NOT NULL COMMENT '更新者', + update_date datetime NOT NULL COMMENT '更新时间', + remarks varchar(500) COMMENT '备注信息', + corp_code varchar(64) DEFAULT '0' NOT NULL COMMENT '租户代码', + corp_name varchar(100) DEFAULT 'JeeSite' NOT NULL COMMENT '租户名称', + PRIMARY KEY (id) +) COMMENT = '文章表'; + + +-- 文章详情表 +CREATE TABLE js_cms_article_data +( + id varchar(64) NOT NULL COMMENT '编号', + content longtext COMMENT '文章内容', + relation varchar(1000) COMMENT '相关文章', + is_can_comment char(1) COMMENT '是否允许评论', + extend_s1 varchar(500) COMMENT '扩展 String 1', + extend_s2 varchar(500) COMMENT '扩展 String 2', + extend_s3 varchar(500) COMMENT '扩展 String 3', + extend_s4 varchar(500) COMMENT '扩展 String 4', + extend_s5 varchar(500) COMMENT '扩展 String 5', + extend_s6 varchar(500) COMMENT '扩展 String 6', + extend_s7 varchar(500) COMMENT '扩展 String 7', + extend_s8 varchar(500) COMMENT '扩展 String 8', + extend_i1 decimal(19) COMMENT '扩展 Integer 1', + extend_i2 decimal(19) COMMENT '扩展 Integer 2', + extend_i3 decimal(19) COMMENT '扩展 Integer 3', + extend_i4 decimal(19) COMMENT '扩展 Integer 4', + extend_f1 decimal(19,4) COMMENT '扩展 Float 1', + extend_f2 decimal(19,4) COMMENT '扩展 Float 2', + extend_f3 decimal(19,4) COMMENT '扩展 Float 3', + extend_f4 decimal(19,4) COMMENT '扩展 Float 4', + extend_d1 datetime COMMENT '扩展 Date 1', + extend_d2 datetime COMMENT '扩展 Date 2', + extend_d3 datetime COMMENT '扩展 Date 3', + extend_d4 datetime COMMENT '扩展 Date 4', + PRIMARY KEY (id) +) COMMENT = '文章详情表'; + + +-- 文章推荐位 +CREATE TABLE js_cms_article_posid +( + article_id varchar(64) NOT NULL COMMENT '内容编号', + postid char(1) NOT NULL COMMENT '推荐位置(1轮播图 2首页推荐 3栏目页面)' +) COMMENT = '文章推荐位'; + + +-- 文章与标签关系 +CREATE TABLE js_cms_article_tag +( + article_id varchar(64) NOT NULL COMMENT '内容编号', + tag_name varchar(200) NOT NULL COMMENT '标签名称' +) COMMENT = '文章与标签关系'; + + +-- 栏目表 +CREATE TABLE js_cms_category +( + category_code varchar(64) NOT NULL COMMENT '栏目编码', + parent_code varchar(64) NOT NULL COMMENT '父级编号', + parent_codes varchar(1000) NOT NULL COMMENT '所有父级编号', + tree_sort decimal(10) NOT NULL COMMENT '本级排序号(升序)', + tree_sorts varchar(1000) NOT NULL COMMENT '所有级别排序号', + tree_leaf char(1) NOT NULL COMMENT '是否最末级', + tree_level decimal(4) NOT NULL COMMENT '层次级别', + tree_names varchar(1000) NOT NULL COMMENT '全节点名', + category_name varchar(100) NOT NULL COMMENT '栏目名称', + site_code varchar(64) NOT NULL COMMENT '站点编码', + module_type varchar(50) COMMENT '模块类型', + image varchar(255) COMMENT '栏目图片', + href varchar(255) COMMENT '链接', + target varchar(20) COMMENT '目标', + keywords varchar(500) COMMENT '关键字', + description varchar(500) COMMENT '描述', + in_menu char(1) COMMENT '是否在导航中显示', + in_list char(1) COMMENT '是否在分类页中显示列表', + show_modes char(1) COMMENT '展现模式', + is_need_audit char(1) COMMENT '是否需要审核', + is_can_comment char(1) COMMENT '是否允许评论', + custom_list_view varchar(255) COMMENT '自定义列表视图', + custom_content_view varchar(255) COMMENT '自定义内容视图', + view_config varchar(1000) COMMENT '视图配置', + status char(1) DEFAULT '0' NOT NULL COMMENT '状态(0正常 1删除 2停用)', + create_by varchar(64) NOT NULL COMMENT '创建者', + create_date datetime NOT NULL COMMENT '创建时间', + update_by varchar(64) NOT NULL COMMENT '更新者', + update_date datetime NOT NULL COMMENT '更新时间', + remarks varchar(500) COMMENT '备注信息', + extend_s1 varchar(500) COMMENT '扩展 String 1', + extend_s2 varchar(500) COMMENT '扩展 String 2', + extend_s3 varchar(500) COMMENT '扩展 String 3', + extend_s4 varchar(500) COMMENT '扩展 String 4', + extend_s5 varchar(500) COMMENT '扩展 String 5', + extend_s6 varchar(500) COMMENT '扩展 String 6', + extend_s7 varchar(500) COMMENT '扩展 String 7', + extend_s8 varchar(500) COMMENT '扩展 String 8', + extend_i1 decimal(19) COMMENT '扩展 Integer 1', + extend_i2 decimal(19) COMMENT '扩展 Integer 2', + extend_i3 decimal(19) COMMENT '扩展 Integer 3', + extend_i4 decimal(19) COMMENT '扩展 Integer 4', + extend_f1 decimal(19,4) COMMENT '扩展 Float 1', + extend_f2 decimal(19,4) COMMENT '扩展 Float 2', + extend_f3 decimal(19,4) COMMENT '扩展 Float 3', + extend_f4 decimal(19,4) COMMENT '扩展 Float 4', + extend_d1 datetime COMMENT '扩展 Date 1', + extend_d2 datetime COMMENT '扩展 Date 2', + extend_d3 datetime COMMENT '扩展 Date 3', + extend_d4 datetime COMMENT '扩展 Date 4', + PRIMARY KEY (category_code) +) COMMENT = '栏目表'; + + +-- 栏目与角色关联表 +CREATE TABLE js_cms_category_role +( + category_code varchar(64) NOT NULL COMMENT '栏目编码', + role_code varchar(64) NOT NULL COMMENT '角色编码', + ctrl_type varchar(32) COMMENT '控制类型(view查看、edit编辑)', + PRIMARY KEY (category_code, role_code) +) COMMENT = '栏目与角色关联表'; + + +-- 文章评论表 +CREATE TABLE js_cms_comment +( + id varchar(64) NOT NULL COMMENT '编号', + category_code varchar(64) NOT NULL COMMENT '栏目编码', + article_id varchar(64) NOT NULL COMMENT '内容编号', + parent_id varchar(64) COMMENT '父级评论', + article_title varchar(255) NOT NULL COMMENT '内容标题', + content varchar(255) NOT NULL COMMENT '评论内容', + name varchar(50) COMMENT '评论姓名', + ip varchar(100) COMMENT '评论IP', + create_by varchar(64) COMMENT '创建者', + create_date datetime NOT NULL COMMENT '创建时间', + audit_user_code varchar(64) COMMENT '审核人', + audit_date datetime COMMENT '审核时间', + audit_comment varchar(200) COMMENT '审核意见', + hits_plus numeric(10) COMMENT '支持数', + hits_minus numeric(10) COMMENT '反对数', + status char(1) NOT NULL COMMENT '状态(0正常 1删除 2停用)', + corp_code varchar(64) DEFAULT '0' NOT NULL COMMENT '租户代码', + corp_name varchar(100) DEFAULT 'JeeSite' NOT NULL COMMENT '租户名称', + PRIMARY KEY (id) +) COMMENT = '文章评论表'; + + +-- 留言板表 +CREATE TABLE js_cms_guestbook +( + id varchar(64) NOT NULL COMMENT '编号', + type char(1) NOT NULL COMMENT '留言分类', + content varchar(255) NOT NULL COMMENT '留言内容', + name varchar(100) NOT NULL COMMENT '姓名', + email varchar(100) NOT NULL COMMENT '邮箱', + phone varchar(100) NOT NULL COMMENT '电话', + workunit varchar(100) NOT NULL COMMENT '单位', + ip varchar(100) NOT NULL COMMENT 'IP', + create_by varchar(64) COMMENT '创建者', + create_date datetime COMMENT '创建时间', + re_user_code varchar(64) COMMENT '回复人', + re_date datetime COMMENT '回复时间', + re_content varchar(100) COMMENT '回复内容', + status char(1) NOT NULL COMMENT '状态(0正常 1删除 2停用)', + corp_code varchar(64) DEFAULT '0' NOT NULL COMMENT '租户代码', + corp_name varchar(100) DEFAULT 'JeeSite' NOT NULL COMMENT '租户名称', + PRIMARY KEY (id) +) COMMENT = '留言板表'; + + +-- 内容举报表 +CREATE TABLE js_cms_report +( + id varchar(64) NOT NULL COMMENT '编号', + report_source char(1) COMMENT '举报来源(1文章、2评论)', + report_content varchar(500) COMMENT '举报内容(文章标题 评论内容)', + report_url varchar(1000) COMMENT '举报的URL', + report_type char(1) COMMENT '举报类型(色情 政治...)', + report_cause varchar(500) COMMENT '举报原因', + PRIMARY KEY (id) +) COMMENT = '内容举报表'; + + +-- 站点表 +CREATE TABLE js_cms_site +( + site_code varchar(64) NOT NULL COMMENT '站点编码', + site_name varchar(100) NOT NULL COMMENT '站点名称', + site_sort decimal(10) COMMENT '站点排序号', + title varchar(100) NOT NULL COMMENT '站点标题', + logo varchar(1000) COMMENT '站点Logo', + domain varchar(500) COMMENT '站点域名', + keywords varchar(500) COMMENT '关键字', + description varchar(500) COMMENT '描述', + theme varchar(500) COMMENT '主题', + copyright varchar(1000) COMMENT '版权信息', + custom_index_view varchar(500) COMMENT '自定义站点首页视图', + status char(1) DEFAULT '0' NOT NULL COMMENT '状态(0正常 1删除 2停用)', + create_by varchar(64) NOT NULL COMMENT '创建者', + create_date datetime NOT NULL COMMENT '创建时间', + update_by varchar(64) NOT NULL COMMENT '更新者', + update_date datetime NOT NULL COMMENT '更新时间', + remarks varchar(500) COMMENT '备注信息', + PRIMARY KEY (site_code) +) COMMENT = '站点表'; + + +-- 内容标签 +CREATE TABLE js_cms_tag +( + tag_name varchar(200) NOT NULL COMMENT '标签名称', + clicknum numeric(10) NOT NULL COMMENT '点击次数', + PRIMARY KEY (tag_name) +) COMMENT = '内容标签'; + + +-- 访问日志表 +CREATE TABLE js_cms_visit_log +( + id varchar(64) NOT NULL COMMENT '编号', + request_url varchar(1000) COMMENT '请求的URL地址', + request_url_host varchar(128) COMMENT '受访域名', + source_referer varchar(1000) COMMENT '来源页面/上一个页面', + source_referer_host varchar(128) COMMENT '来源域名', + source_type char(1) COMMENT '访问来源类型(1直接访问 2搜索引擎 3外部链接 4内部访问)', + search_engine varchar(200) COMMENT '使用的搜索引擎', + search_word varchar(200) COMMENT '搜索的关键词', + remote_addr varchar(50) COMMENT '客户IP地址', + user_agent varchar(500) COMMENT '用户代理字符串', + user_language varchar(32) COMMENT '客户机语言', + user_screen_size varchar(32) COMMENT '客户机屏幕大小0x0', + user_device varchar(32) COMMENT '客户机设备类型(电脑、平板、手机、未知)', + user_os_name varchar(32) COMMENT '客户机操作系统', + user_browser varchar(32) COMMENT '客户机浏览器', + user_browser_version varchar(16) COMMENT '浏览器版本', + unique_visit_id varchar(64) COMMENT '唯一访问标识', + visit_date char(8) COMMENT '本次访问日期(年月日)', + visit_time datetime COMMENT '本次访问时间', + is_new_visit char(1) COMMENT '是否新访问(30分内)', + first_visit_time decimal(20) COMMENT '首次访问时间戳(30分钟内)', + prev_remain_time decimal(20) COMMENT '上页面停留时间(秒)', + total_remain_time decimal(20) COMMENT '本次访问总停留时间(秒)', + site_code varchar(64) COMMENT '站点编码', + site_name varchar(100) COMMENT '站点名称', + category_code varchar(64) COMMENT '栏目编码', + category_name varchar(100) COMMENT '栏目名称', + content_id varchar(64) COMMENT '栏目内容编号', + content_title varchar(255) COMMENT '访问页面标题', + visit_user_code varchar(100) COMMENT '访问用户编码', + visit_user_name varchar(100) COMMENT '访问用户姓名', + corp_code varchar(64) DEFAULT '0' NOT NULL COMMENT '租户代码', + corp_name varchar(100) DEFAULT 'JeeSite' NOT NULL COMMENT '租户名称', + PRIMARY KEY (id) +) COMMENT = '访问日志表'; + + + +/* Create Indexes */ + +CREATE INDEX idx_cms_article_cb ON js_cms_article (create_by ASC); +CREATE INDEX idx_cms_article_cc ON js_cms_article (category_code ASC); +CREATE INDEX idx_cms_article_corp_code ON js_cms_article (corp_code ASC); +CREATE INDEX idx_cms_article_status ON js_cms_article (status ASC); +CREATE INDEX idx_cms_article_ud ON js_cms_article (update_date ASC); +CREATE INDEX idx_cms_article_weight ON js_cms_article (weight ASC); +CREATE INDEX idx_cms_category_pc ON js_cms_category (parent_code ASC); +CREATE INDEX idx_cms_category_ts ON js_cms_category (tree_sort ASC); +CREATE INDEX idx_cms_category_status ON js_cms_category (status ASC); +CREATE INDEX idx_cms_category_tss ON js_cms_category (tree_sorts ASC); +CREATE INDEX idx_cms_comment_catc ON js_cms_comment (category_code ASC); +CREATE INDEX idx_cms_comment_ai ON js_cms_comment (article_id ASC); +CREATE INDEX idx_cms_comment_cc ON js_cms_comment (corp_code ASC); +CREATE INDEX idx_cms_comment_status ON js_cms_comment (status ASC); +CREATE INDEX idx_cms_guestbook_cc ON js_cms_guestbook (corp_code ASC); +CREATE INDEX idx_cms_guestbook_status ON js_cms_guestbook (status ASC); +CREATE INDEX idx_cms_guestbook_type ON js_cms_guestbook (type ASC); +CREATE INDEX idx_cms_site_status ON js_cms_site (status ASC); +CREATE INDEX cms_visit_log_cc ON js_cms_visit_log (category_code ASC); +CREATE INDEX cms_visit_log_ci ON js_cms_visit_log (content_id ASC); +CREATE INDEX cms_visit_log_fvt ON js_cms_visit_log (first_visit_time ASC); +CREATE INDEX cms_visit_log_inv ON js_cms_visit_log (is_new_visit ASC); +CREATE INDEX cms_visit_log_ra ON js_cms_visit_log (remote_addr ASC); +CREATE INDEX cms_visit_log_sc ON js_cms_visit_log (site_code ASC); +CREATE INDEX cms_visit_log_uvid ON js_cms_visit_log (unique_visit_id ASC); +CREATE INDEX cms_visit_log_vd ON js_cms_visit_log (visit_date ASC); +CREATE INDEX cms_visit_log_vt ON js_cms_visit_log (visit_time ASC); +CREATE INDEX idx_cms_visit_log_corpc ON js_cms_visit_log (corp_code ASC); + + + diff --git a/modules/cms/db/oracle/cms.sql b/modules/cms/db/oracle/cms.sql new file mode 100644 index 00000000..f76502ee --- /dev/null +++ b/modules/cms/db/oracle/cms.sql @@ -0,0 +1,537 @@ + + +/* Create Tables */ + +-- 文章表 +CREATE TABLE js_cms_article +( + id varchar2(64) NOT NULL, + category_code varchar2(64) NOT NULL, + module_type varchar2(50), + title nvarchar2(255) NOT NULL, + href nvarchar2(1000), + color varchar2(50), + image nvarchar2(1000), + keywords nvarchar2(500), + description nvarchar2(500), + weight number(10) DEFAULT 0, + weight_date timestamp, + source char(1), + copyfrom nvarchar2(255), + hits number(20) DEFAULT 0, + hits_plus number(10), + hits_minus number(10), + word_count number(10), + custom_content_view varchar2(255), + view_config nvarchar2(1000), + status char(1) DEFAULT '0' NOT NULL, + create_by varchar2(64) NOT NULL, + create_date timestamp NOT NULL, + update_by varchar2(64) NOT NULL, + update_date timestamp NOT NULL, + remarks nvarchar2(500), + corp_code varchar2(64) DEFAULT '0' NOT NULL, + corp_name nvarchar2(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +); + + +-- 文章详情表 +CREATE TABLE js_cms_article_data +( + id varchar2(64) NOT NULL, + content clob, + relation varchar2(1000), + is_can_comment char(1), + extend_s1 nvarchar2(500), + extend_s2 nvarchar2(500), + extend_s3 nvarchar2(500), + extend_s4 nvarchar2(500), + extend_s5 nvarchar2(500), + extend_s6 nvarchar2(500), + extend_s7 nvarchar2(500), + extend_s8 nvarchar2(500), + extend_i1 number(19), + extend_i2 number(19), + extend_i3 number(19), + extend_i4 number(19), + extend_f1 number(19,4), + extend_f2 number(19,4), + extend_f3 number(19,4), + extend_f4 number(19,4), + extend_d1 timestamp, + extend_d2 timestamp, + extend_d3 timestamp, + extend_d4 timestamp, + PRIMARY KEY (id) +); + + +-- 文章推荐位 +CREATE TABLE js_cms_article_posid +( + article_id varchar2(64) NOT NULL, + postid char(1) NOT NULL +); + + +-- 文章与标签关系 +CREATE TABLE js_cms_article_tag +( + article_id varchar2(64) NOT NULL, + tag_name nvarchar2(200) NOT NULL +); + + +-- 栏目表 +CREATE TABLE js_cms_category +( + category_code varchar2(64) NOT NULL, + parent_code varchar2(64) NOT NULL, + parent_codes varchar2(1000) NOT NULL, + tree_sort number(10) NOT NULL, + tree_sorts varchar2(1000) NOT NULL, + tree_leaf char(1) NOT NULL, + tree_level number(4) NOT NULL, + tree_names nvarchar2(1000) NOT NULL, + category_name nvarchar2(100) NOT NULL, + site_code varchar2(64) NOT NULL, + module_type varchar2(50), + image varchar2(255), + href varchar2(255), + target varchar2(20), + keywords nvarchar2(500), + description nvarchar2(500), + in_menu char(1), + in_list char(1), + show_modes char(1), + is_need_audit char(1), + is_can_comment char(1), + custom_list_view varchar2(255), + custom_content_view varchar2(255), + view_config nvarchar2(1000), + status char(1) DEFAULT '0' NOT NULL, + create_by varchar2(64) NOT NULL, + create_date timestamp NOT NULL, + update_by varchar2(64) NOT NULL, + update_date timestamp NOT NULL, + remarks nvarchar2(500), + extend_s1 nvarchar2(500), + extend_s2 nvarchar2(500), + extend_s3 nvarchar2(500), + extend_s4 nvarchar2(500), + extend_s5 nvarchar2(500), + extend_s6 nvarchar2(500), + extend_s7 nvarchar2(500), + extend_s8 nvarchar2(500), + extend_i1 number(19), + extend_i2 number(19), + extend_i3 number(19), + extend_i4 number(19), + extend_f1 number(19,4), + extend_f2 number(19,4), + extend_f3 number(19,4), + extend_f4 number(19,4), + extend_d1 timestamp, + extend_d2 timestamp, + extend_d3 timestamp, + extend_d4 timestamp, + PRIMARY KEY (category_code) +); + + +-- 栏目与角色关联表 +CREATE TABLE js_cms_category_role +( + category_code varchar2(64) NOT NULL, + role_code varchar2(64) NOT NULL, + ctrl_type varchar2(32), + PRIMARY KEY (category_code, role_code) +); + + +-- 文章评论表 +CREATE TABLE js_cms_comment +( + id varchar2(64) NOT NULL, + category_code varchar2(64) NOT NULL, + article_id varchar2(64) NOT NULL, + parent_id varchar2(64), + article_title nvarchar2(255) NOT NULL, + content nvarchar2(255) NOT NULL, + name nvarchar2(50), + ip varchar2(100), + create_by varchar2(64), + create_date timestamp NOT NULL, + audit_user_code varchar2(64), + audit_date timestamp, + audit_comment nvarchar2(200), + hits_plus number(10), + hits_minus number(10), + status char(1) NOT NULL, + corp_code varchar2(64) DEFAULT '0' NOT NULL, + corp_name nvarchar2(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +); + + +-- 留言板表 +CREATE TABLE js_cms_guestbook +( + id varchar2(64) NOT NULL, + type char(1) NOT NULL, + content varchar2(255) NOT NULL, + name varchar2(100) NOT NULL, + email varchar2(100) NOT NULL, + phone varchar2(100) NOT NULL, + workunit varchar2(100) NOT NULL, + ip varchar2(100) NOT NULL, + create_by varchar2(64), + create_date timestamp, + re_user_code varchar2(64), + re_date timestamp, + re_content varchar2(100), + status char(1) NOT NULL, + corp_code varchar2(64) DEFAULT '0' NOT NULL, + corp_name nvarchar2(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +); + + +-- 内容举报表 +CREATE TABLE js_cms_report +( + id varchar2(64) NOT NULL, + report_source char(1), + report_content nvarchar2(500), + report_url nvarchar2(1000), + report_type char(1), + report_cause nvarchar2(500), + PRIMARY KEY (id) +); + + +-- 站点表 +CREATE TABLE js_cms_site +( + site_code varchar2(64) NOT NULL, + site_name nvarchar2(100) NOT NULL, + site_sort number(10), + title nvarchar2(100) NOT NULL, + logo nvarchar2(1000), + domain nvarchar2(500), + keywords nvarchar2(500), + description nvarchar2(500), + theme nvarchar2(500), + copyright nvarchar2(1000), + custom_index_view varchar2(500), + status char(1) DEFAULT '0' NOT NULL, + create_by varchar2(64) NOT NULL, + create_date timestamp NOT NULL, + update_by varchar2(64) NOT NULL, + update_date timestamp NOT NULL, + remarks nvarchar2(500), + PRIMARY KEY (site_code) +); + + +-- 内容标签 +CREATE TABLE js_cms_tag +( + tag_name nvarchar2(200) NOT NULL, + clicknum number(10) NOT NULL, + PRIMARY KEY (tag_name) +); + + +-- 访问日志表 +CREATE TABLE js_cms_visit_log +( + id varchar2(64) NOT NULL, + request_url nvarchar2(1000), + request_url_host varchar2(128), + source_referer nvarchar2(1000), + source_referer_host varchar2(128), + source_type char(1), + search_engine varchar2(200), + search_word nvarchar2(200), + remote_addr varchar2(50), + user_agent nvarchar2(500), + user_language varchar2(32), + user_screen_size varchar2(32), + user_device varchar2(32), + user_os_name varchar2(32), + user_browser varchar2(32), + user_browser_version varchar2(16), + unique_visit_id varchar2(64), + visit_date char(8), + visit_time timestamp, + is_new_visit char(1), + first_visit_time number(20), + prev_remain_time number(20), + total_remain_time number(20), + site_code varchar2(64), + site_name nvarchar2(100), + category_code varchar2(64), + category_name nvarchar2(100), + content_id varchar2(64), + content_title nvarchar2(255), + visit_user_code varchar2(100), + visit_user_name varchar2(100), + corp_code varchar2(64) DEFAULT '0' NOT NULL, + corp_name nvarchar2(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +); + + + +/* Create Indexes */ + +CREATE INDEX idx_cms_article_cb ON js_cms_article (create_by); +CREATE INDEX idx_cms_article_cc ON js_cms_article (category_code); +CREATE INDEX idx_cms_article_corp_code ON js_cms_article (corp_code); +CREATE INDEX idx_cms_article_status ON js_cms_article (status); +CREATE INDEX idx_cms_article_ud ON js_cms_article (update_date); +CREATE INDEX idx_cms_article_weight ON js_cms_article (weight); +CREATE INDEX idx_cms_category_pc ON js_cms_category (parent_code); +CREATE INDEX idx_cms_category_ts ON js_cms_category (tree_sort); +CREATE INDEX idx_cms_category_status ON js_cms_category (status); +CREATE INDEX idx_cms_category_tss ON js_cms_category (tree_sorts); +CREATE INDEX idx_cms_comment_catc ON js_cms_comment (category_code); +CREATE INDEX idx_cms_comment_ai ON js_cms_comment (article_id); +CREATE INDEX idx_cms_comment_cc ON js_cms_comment (corp_code); +CREATE INDEX idx_cms_comment_status ON js_cms_comment (status); +CREATE INDEX idx_cms_guestbook_cc ON js_cms_guestbook (corp_code); +CREATE INDEX idx_cms_guestbook_status ON js_cms_guestbook (status); +CREATE INDEX idx_cms_guestbook_type ON js_cms_guestbook (type); +CREATE INDEX idx_cms_site_status ON js_cms_site (status); +CREATE INDEX cms_visit_log_cc ON js_cms_visit_log (category_code); +CREATE INDEX cms_visit_log_ci ON js_cms_visit_log (content_id); +CREATE INDEX cms_visit_log_fvt ON js_cms_visit_log (first_visit_time); +CREATE INDEX cms_visit_log_inv ON js_cms_visit_log (is_new_visit); +CREATE INDEX cms_visit_log_ra ON js_cms_visit_log (remote_addr); +CREATE INDEX cms_visit_log_sc ON js_cms_visit_log (site_code); +CREATE INDEX cms_visit_log_uvid ON js_cms_visit_log (unique_visit_id); +CREATE INDEX cms_visit_log_vd ON js_cms_visit_log (visit_date); +CREATE INDEX cms_visit_log_vt ON js_cms_visit_log (visit_time); +CREATE INDEX idx_cms_visit_log_corpc ON js_cms_visit_log (corp_code); + + + +/* Comments */ + +COMMENT ON TABLE js_cms_article IS '文章表'; +COMMENT ON COLUMN js_cms_article.id IS '编号'; +COMMENT ON COLUMN js_cms_article.category_code IS '栏目编码'; +COMMENT ON COLUMN js_cms_article.module_type IS '模块类型'; +COMMENT ON COLUMN js_cms_article.title IS '内容标题'; +COMMENT ON COLUMN js_cms_article.href IS '外部链接'; +COMMENT ON COLUMN js_cms_article.color IS '标题颜色'; +COMMENT ON COLUMN js_cms_article.image IS '内容图片'; +COMMENT ON COLUMN js_cms_article.keywords IS '关键字'; +COMMENT ON COLUMN js_cms_article.description IS '描述'; +COMMENT ON COLUMN js_cms_article.weight IS '权重,越大越靠前'; +COMMENT ON COLUMN js_cms_article.weight_date IS '权重期限'; +COMMENT ON COLUMN js_cms_article.source IS '来源(转载/原创)'; +COMMENT ON COLUMN js_cms_article.copyfrom IS '文章来源出处'; +COMMENT ON COLUMN js_cms_article.hits IS '点击数'; +COMMENT ON COLUMN js_cms_article.hits_plus IS '支持数'; +COMMENT ON COLUMN js_cms_article.hits_minus IS '反对数'; +COMMENT ON COLUMN js_cms_article.word_count IS '字数(不包含html)'; +COMMENT ON COLUMN js_cms_article.custom_content_view IS '自定义内容视图'; +COMMENT ON COLUMN js_cms_article.view_config IS '视图配置'; +COMMENT ON COLUMN js_cms_article.status IS '状态(0正常 1删除 2停用)'; +COMMENT ON COLUMN js_cms_article.create_by IS '创建者'; +COMMENT ON COLUMN js_cms_article.create_date IS '创建时间'; +COMMENT ON COLUMN js_cms_article.update_by IS '更新者'; +COMMENT ON COLUMN js_cms_article.update_date IS '更新时间'; +COMMENT ON COLUMN js_cms_article.remarks IS '备注信息'; +COMMENT ON COLUMN js_cms_article.corp_code IS '租户代码'; +COMMENT ON COLUMN js_cms_article.corp_name IS '租户名称'; +COMMENT ON TABLE js_cms_article_data IS '文章详情表'; +COMMENT ON COLUMN js_cms_article_data.id IS '编号'; +COMMENT ON COLUMN js_cms_article_data.content IS '文章内容'; +COMMENT ON COLUMN js_cms_article_data.relation IS '相关文章'; +COMMENT ON COLUMN js_cms_article_data.is_can_comment IS '是否允许评论'; +COMMENT ON COLUMN js_cms_article_data.extend_s1 IS '扩展 String 1'; +COMMENT ON COLUMN js_cms_article_data.extend_s2 IS '扩展 String 2'; +COMMENT ON COLUMN js_cms_article_data.extend_s3 IS '扩展 String 3'; +COMMENT ON COLUMN js_cms_article_data.extend_s4 IS '扩展 String 4'; +COMMENT ON COLUMN js_cms_article_data.extend_s5 IS '扩展 String 5'; +COMMENT ON COLUMN js_cms_article_data.extend_s6 IS '扩展 String 6'; +COMMENT ON COLUMN js_cms_article_data.extend_s7 IS '扩展 String 7'; +COMMENT ON COLUMN js_cms_article_data.extend_s8 IS '扩展 String 8'; +COMMENT ON COLUMN js_cms_article_data.extend_i1 IS '扩展 Integer 1'; +COMMENT ON COLUMN js_cms_article_data.extend_i2 IS '扩展 Integer 2'; +COMMENT ON COLUMN js_cms_article_data.extend_i3 IS '扩展 Integer 3'; +COMMENT ON COLUMN js_cms_article_data.extend_i4 IS '扩展 Integer 4'; +COMMENT ON COLUMN js_cms_article_data.extend_f1 IS '扩展 Float 1'; +COMMENT ON COLUMN js_cms_article_data.extend_f2 IS '扩展 Float 2'; +COMMENT ON COLUMN js_cms_article_data.extend_f3 IS '扩展 Float 3'; +COMMENT ON COLUMN js_cms_article_data.extend_f4 IS '扩展 Float 4'; +COMMENT ON COLUMN js_cms_article_data.extend_d1 IS '扩展 Date 1'; +COMMENT ON COLUMN js_cms_article_data.extend_d2 IS '扩展 Date 2'; +COMMENT ON COLUMN js_cms_article_data.extend_d3 IS '扩展 Date 3'; +COMMENT ON COLUMN js_cms_article_data.extend_d4 IS '扩展 Date 4'; +COMMENT ON TABLE js_cms_article_posid IS '文章推荐位'; +COMMENT ON COLUMN js_cms_article_posid.article_id IS '内容编号'; +COMMENT ON COLUMN js_cms_article_posid.postid IS '推荐位置(1轮播图 2首页推荐 3栏目页面)'; +COMMENT ON TABLE js_cms_article_tag IS '文章与标签关系'; +COMMENT ON COLUMN js_cms_article_tag.article_id IS '内容编号'; +COMMENT ON COLUMN js_cms_article_tag.tag_name IS '标签名称'; +COMMENT ON TABLE js_cms_category IS '栏目表'; +COMMENT ON COLUMN js_cms_category.category_code IS '栏目编码'; +COMMENT ON COLUMN js_cms_category.parent_code IS '父级编号'; +COMMENT ON COLUMN js_cms_category.parent_codes IS '所有父级编号'; +COMMENT ON COLUMN js_cms_category.tree_sort IS '本级排序号(升序)'; +COMMENT ON COLUMN js_cms_category.tree_sorts IS '所有级别排序号'; +COMMENT ON COLUMN js_cms_category.tree_leaf IS '是否最末级'; +COMMENT ON COLUMN js_cms_category.tree_level IS '层次级别'; +COMMENT ON COLUMN js_cms_category.tree_names IS '全节点名'; +COMMENT ON COLUMN js_cms_category.category_name IS '栏目名称'; +COMMENT ON COLUMN js_cms_category.site_code IS '站点编码'; +COMMENT ON COLUMN js_cms_category.module_type IS '模块类型'; +COMMENT ON COLUMN js_cms_category.image IS '栏目图片'; +COMMENT ON COLUMN js_cms_category.href IS '链接'; +COMMENT ON COLUMN js_cms_category.target IS '目标'; +COMMENT ON COLUMN js_cms_category.keywords IS '关键字'; +COMMENT ON COLUMN js_cms_category.description IS '描述'; +COMMENT ON COLUMN js_cms_category.in_menu IS '是否在导航中显示'; +COMMENT ON COLUMN js_cms_category.in_list IS '是否在分类页中显示列表'; +COMMENT ON COLUMN js_cms_category.show_modes IS '展现模式'; +COMMENT ON COLUMN js_cms_category.is_need_audit IS '是否需要审核'; +COMMENT ON COLUMN js_cms_category.is_can_comment IS '是否允许评论'; +COMMENT ON COLUMN js_cms_category.custom_list_view IS '自定义列表视图'; +COMMENT ON COLUMN js_cms_category.custom_content_view IS '自定义内容视图'; +COMMENT ON COLUMN js_cms_category.view_config IS '视图配置'; +COMMENT ON COLUMN js_cms_category.status IS '状态(0正常 1删除 2停用)'; +COMMENT ON COLUMN js_cms_category.create_by IS '创建者'; +COMMENT ON COLUMN js_cms_category.create_date IS '创建时间'; +COMMENT ON COLUMN js_cms_category.update_by IS '更新者'; +COMMENT ON COLUMN js_cms_category.update_date IS '更新时间'; +COMMENT ON COLUMN js_cms_category.remarks IS '备注信息'; +COMMENT ON COLUMN js_cms_category.extend_s1 IS '扩展 String 1'; +COMMENT ON COLUMN js_cms_category.extend_s2 IS '扩展 String 2'; +COMMENT ON COLUMN js_cms_category.extend_s3 IS '扩展 String 3'; +COMMENT ON COLUMN js_cms_category.extend_s4 IS '扩展 String 4'; +COMMENT ON COLUMN js_cms_category.extend_s5 IS '扩展 String 5'; +COMMENT ON COLUMN js_cms_category.extend_s6 IS '扩展 String 6'; +COMMENT ON COLUMN js_cms_category.extend_s7 IS '扩展 String 7'; +COMMENT ON COLUMN js_cms_category.extend_s8 IS '扩展 String 8'; +COMMENT ON COLUMN js_cms_category.extend_i1 IS '扩展 Integer 1'; +COMMENT ON COLUMN js_cms_category.extend_i2 IS '扩展 Integer 2'; +COMMENT ON COLUMN js_cms_category.extend_i3 IS '扩展 Integer 3'; +COMMENT ON COLUMN js_cms_category.extend_i4 IS '扩展 Integer 4'; +COMMENT ON COLUMN js_cms_category.extend_f1 IS '扩展 Float 1'; +COMMENT ON COLUMN js_cms_category.extend_f2 IS '扩展 Float 2'; +COMMENT ON COLUMN js_cms_category.extend_f3 IS '扩展 Float 3'; +COMMENT ON COLUMN js_cms_category.extend_f4 IS '扩展 Float 4'; +COMMENT ON COLUMN js_cms_category.extend_d1 IS '扩展 Date 1'; +COMMENT ON COLUMN js_cms_category.extend_d2 IS '扩展 Date 2'; +COMMENT ON COLUMN js_cms_category.extend_d3 IS '扩展 Date 3'; +COMMENT ON COLUMN js_cms_category.extend_d4 IS '扩展 Date 4'; +COMMENT ON TABLE js_cms_category_role IS '栏目与角色关联表'; +COMMENT ON COLUMN js_cms_category_role.category_code IS '栏目编码'; +COMMENT ON COLUMN js_cms_category_role.role_code IS '角色编码'; +COMMENT ON COLUMN js_cms_category_role.ctrl_type IS '控制类型(view查看、edit编辑)'; +COMMENT ON TABLE js_cms_comment IS '文章评论表'; +COMMENT ON COLUMN js_cms_comment.id IS '编号'; +COMMENT ON COLUMN js_cms_comment.category_code IS '栏目编码'; +COMMENT ON COLUMN js_cms_comment.article_id IS '内容编号'; +COMMENT ON COLUMN js_cms_comment.parent_id IS '父级评论'; +COMMENT ON COLUMN js_cms_comment.article_title IS '内容标题'; +COMMENT ON COLUMN js_cms_comment.content IS '评论内容'; +COMMENT ON COLUMN js_cms_comment.name IS '评论姓名'; +COMMENT ON COLUMN js_cms_comment.ip IS '评论IP'; +COMMENT ON COLUMN js_cms_comment.create_by IS '创建者'; +COMMENT ON COLUMN js_cms_comment.create_date IS '创建时间'; +COMMENT ON COLUMN js_cms_comment.audit_user_code IS '审核人'; +COMMENT ON COLUMN js_cms_comment.audit_date IS '审核时间'; +COMMENT ON COLUMN js_cms_comment.audit_comment IS '审核意见'; +COMMENT ON COLUMN js_cms_comment.hits_plus IS '支持数'; +COMMENT ON COLUMN js_cms_comment.hits_minus IS '反对数'; +COMMENT ON COLUMN js_cms_comment.status IS '状态(0正常 1删除 2停用)'; +COMMENT ON COLUMN js_cms_comment.corp_code IS '租户代码'; +COMMENT ON COLUMN js_cms_comment.corp_name IS '租户名称'; +COMMENT ON TABLE js_cms_guestbook IS '留言板表'; +COMMENT ON COLUMN js_cms_guestbook.id IS '编号'; +COMMENT ON COLUMN js_cms_guestbook.type IS '留言分类'; +COMMENT ON COLUMN js_cms_guestbook.content IS '留言内容'; +COMMENT ON COLUMN js_cms_guestbook.name IS '姓名'; +COMMENT ON COLUMN js_cms_guestbook.email IS '邮箱'; +COMMENT ON COLUMN js_cms_guestbook.phone IS '电话'; +COMMENT ON COLUMN js_cms_guestbook.workunit IS '单位'; +COMMENT ON COLUMN js_cms_guestbook.ip IS 'IP'; +COMMENT ON COLUMN js_cms_guestbook.create_by IS '创建者'; +COMMENT ON COLUMN js_cms_guestbook.create_date IS '创建时间'; +COMMENT ON COLUMN js_cms_guestbook.re_user_code IS '回复人'; +COMMENT ON COLUMN js_cms_guestbook.re_date IS '回复时间'; +COMMENT ON COLUMN js_cms_guestbook.re_content IS '回复内容'; +COMMENT ON COLUMN js_cms_guestbook.status IS '状态(0正常 1删除 2停用)'; +COMMENT ON COLUMN js_cms_guestbook.corp_code IS '租户代码'; +COMMENT ON COLUMN js_cms_guestbook.corp_name IS '租户名称'; +COMMENT ON TABLE js_cms_report IS '内容举报表'; +COMMENT ON COLUMN js_cms_report.id IS '编号'; +COMMENT ON COLUMN js_cms_report.report_source IS '举报来源(1文章、2评论)'; +COMMENT ON COLUMN js_cms_report.report_content IS '举报内容(文章标题 评论内容)'; +COMMENT ON COLUMN js_cms_report.report_url IS '举报的URL'; +COMMENT ON COLUMN js_cms_report.report_type IS '举报类型(色情 政治...)'; +COMMENT ON COLUMN js_cms_report.report_cause IS '举报原因'; +COMMENT ON TABLE js_cms_site IS '站点表'; +COMMENT ON COLUMN js_cms_site.site_code IS '站点编码'; +COMMENT ON COLUMN js_cms_site.site_name IS '站点名称'; +COMMENT ON COLUMN js_cms_site.site_sort IS '站点排序号'; +COMMENT ON COLUMN js_cms_site.title IS '站点标题'; +COMMENT ON COLUMN js_cms_site.logo IS '站点Logo'; +COMMENT ON COLUMN js_cms_site.domain IS '站点域名'; +COMMENT ON COLUMN js_cms_site.keywords IS '关键字'; +COMMENT ON COLUMN js_cms_site.description IS '描述'; +COMMENT ON COLUMN js_cms_site.theme IS '主题'; +COMMENT ON COLUMN js_cms_site.copyright IS '版权信息'; +COMMENT ON COLUMN js_cms_site.custom_index_view IS '自定义站点首页视图'; +COMMENT ON COLUMN js_cms_site.status IS '状态(0正常 1删除 2停用)'; +COMMENT ON COLUMN js_cms_site.create_by IS '创建者'; +COMMENT ON COLUMN js_cms_site.create_date IS '创建时间'; +COMMENT ON COLUMN js_cms_site.update_by IS '更新者'; +COMMENT ON COLUMN js_cms_site.update_date IS '更新时间'; +COMMENT ON COLUMN js_cms_site.remarks IS '备注信息'; +COMMENT ON TABLE js_cms_tag IS '内容标签'; +COMMENT ON COLUMN js_cms_tag.tag_name IS '标签名称'; +COMMENT ON COLUMN js_cms_tag.clicknum IS '点击次数'; +COMMENT ON TABLE js_cms_visit_log IS '访问日志表'; +COMMENT ON COLUMN js_cms_visit_log.id IS '编号'; +COMMENT ON COLUMN js_cms_visit_log.request_url IS '请求的URL地址'; +COMMENT ON COLUMN js_cms_visit_log.request_url_host IS '受访域名'; +COMMENT ON COLUMN js_cms_visit_log.source_referer IS '来源页面/上一个页面'; +COMMENT ON COLUMN js_cms_visit_log.source_referer_host IS '来源域名'; +COMMENT ON COLUMN js_cms_visit_log.source_type IS '访问来源类型(1直接访问 2搜索引擎 3外部链接 4内部访问)'; +COMMENT ON COLUMN js_cms_visit_log.search_engine IS '使用的搜索引擎'; +COMMENT ON COLUMN js_cms_visit_log.search_word IS '搜索的关键词'; +COMMENT ON COLUMN js_cms_visit_log.remote_addr IS '客户IP地址'; +COMMENT ON COLUMN js_cms_visit_log.user_agent IS '用户代理字符串'; +COMMENT ON COLUMN js_cms_visit_log.user_language IS '客户机语言'; +COMMENT ON COLUMN js_cms_visit_log.user_screen_size IS '客户机屏幕大小0x0'; +COMMENT ON COLUMN js_cms_visit_log.user_device IS '客户机设备类型(电脑、平板、手机、未知)'; +COMMENT ON COLUMN js_cms_visit_log.user_os_name IS '客户机操作系统'; +COMMENT ON COLUMN js_cms_visit_log.user_browser IS '客户机浏览器'; +COMMENT ON COLUMN js_cms_visit_log.user_browser_version IS '浏览器版本'; +COMMENT ON COLUMN js_cms_visit_log.unique_visit_id IS '唯一访问标识'; +COMMENT ON COLUMN js_cms_visit_log.visit_date IS '本次访问日期(年月日)'; +COMMENT ON COLUMN js_cms_visit_log.visit_time IS '本次访问时间'; +COMMENT ON COLUMN js_cms_visit_log.is_new_visit IS '是否新访问(30分内)'; +COMMENT ON COLUMN js_cms_visit_log.first_visit_time IS '首次访问时间戳(30分钟内)'; +COMMENT ON COLUMN js_cms_visit_log.prev_remain_time IS '上页面停留时间(秒)'; +COMMENT ON COLUMN js_cms_visit_log.total_remain_time IS '本次访问总停留时间(秒)'; +COMMENT ON COLUMN js_cms_visit_log.site_code IS '站点编码'; +COMMENT ON COLUMN js_cms_visit_log.site_name IS '站点名称'; +COMMENT ON COLUMN js_cms_visit_log.category_code IS '栏目编码'; +COMMENT ON COLUMN js_cms_visit_log.category_name IS '栏目名称'; +COMMENT ON COLUMN js_cms_visit_log.content_id IS '栏目内容编号'; +COMMENT ON COLUMN js_cms_visit_log.content_title IS '访问页面标题'; +COMMENT ON COLUMN js_cms_visit_log.visit_user_code IS '访问用户编码'; +COMMENT ON COLUMN js_cms_visit_log.visit_user_name IS '访问用户姓名'; +COMMENT ON COLUMN js_cms_visit_log.corp_code IS '租户代码'; +COMMENT ON COLUMN js_cms_visit_log.corp_name IS '租户名称'; + + + diff --git a/modules/cms/db/postgresql/cms.sql b/modules/cms/db/postgresql/cms.sql new file mode 100644 index 00000000..f5b69988 --- /dev/null +++ b/modules/cms/db/postgresql/cms.sql @@ -0,0 +1,537 @@ + + +/* Create Tables */ + +-- 文章表 +CREATE TABLE js_cms_article +( + id varchar(64) NOT NULL, + category_code varchar(64) NOT NULL, + module_type varchar(50), + title varchar(255) NOT NULL, + href varchar(1000), + color varchar(50), + image varchar(1000), + keywords varchar(500), + description varchar(500), + weight decimal(10) DEFAULT 0, + weight_date timestamp, + source char(1), + copyfrom varchar(255), + hits decimal(20) DEFAULT 0, + hits_plus numeric(10), + hits_minus numeric(10), + word_count numeric(10), + custom_content_view varchar(255), + view_config varchar(1000), + status char(1) DEFAULT '0' NOT NULL, + create_by varchar(64) NOT NULL, + create_date timestamp NOT NULL, + update_by varchar(64) NOT NULL, + update_date timestamp NOT NULL, + remarks varchar(500), + corp_code varchar(64) DEFAULT '0' NOT NULL, + corp_name varchar(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +) WITHOUT OIDS; + + +-- 文章详情表 +CREATE TABLE js_cms_article_data +( + id varchar(64) NOT NULL, + content text, + relation varchar(1000), + is_can_comment char(1), + extend_s1 varchar(500), + extend_s2 varchar(500), + extend_s3 varchar(500), + extend_s4 varchar(500), + extend_s5 varchar(500), + extend_s6 varchar(500), + extend_s7 varchar(500), + extend_s8 varchar(500), + extend_i1 decimal(19), + extend_i2 decimal(19), + extend_i3 decimal(19), + extend_i4 decimal(19), + extend_f1 decimal(19,4), + extend_f2 decimal(19,4), + extend_f3 decimal(19,4), + extend_f4 decimal(19,4), + extend_d1 timestamp, + extend_d2 timestamp, + extend_d3 timestamp, + extend_d4 timestamp, + PRIMARY KEY (id) +) WITHOUT OIDS; + + +-- 文章推荐位 +CREATE TABLE js_cms_article_posid +( + article_id varchar(64) NOT NULL, + postid char(1) NOT NULL +) WITHOUT OIDS; + + +-- 文章与标签关系 +CREATE TABLE js_cms_article_tag +( + article_id varchar(64) NOT NULL, + tag_name varchar(200) NOT NULL +) WITHOUT OIDS; + + +-- 栏目表 +CREATE TABLE js_cms_category +( + category_code varchar(64) NOT NULL, + parent_code varchar(64) NOT NULL, + parent_codes varchar(1000) NOT NULL, + tree_sort decimal(10) NOT NULL, + tree_sorts varchar(1000) NOT NULL, + tree_leaf char(1) NOT NULL, + tree_level decimal(4) NOT NULL, + tree_names varchar(1000) NOT NULL, + category_name varchar(100) NOT NULL, + site_code varchar(64) NOT NULL, + module_type varchar(50), + image varchar(255), + href varchar(255), + target varchar(20), + keywords varchar(500), + description varchar(500), + in_menu char(1), + in_list char(1), + show_modes char(1), + is_need_audit char(1), + is_can_comment char(1), + custom_list_view varchar(255), + custom_content_view varchar(255), + view_config varchar(1000), + status char(1) DEFAULT '0' NOT NULL, + create_by varchar(64) NOT NULL, + create_date timestamp NOT NULL, + update_by varchar(64) NOT NULL, + update_date timestamp NOT NULL, + remarks varchar(500), + extend_s1 varchar(500), + extend_s2 varchar(500), + extend_s3 varchar(500), + extend_s4 varchar(500), + extend_s5 varchar(500), + extend_s6 varchar(500), + extend_s7 varchar(500), + extend_s8 varchar(500), + extend_i1 decimal(19), + extend_i2 decimal(19), + extend_i3 decimal(19), + extend_i4 decimal(19), + extend_f1 decimal(19,4), + extend_f2 decimal(19,4), + extend_f3 decimal(19,4), + extend_f4 decimal(19,4), + extend_d1 timestamp, + extend_d2 timestamp, + extend_d3 timestamp, + extend_d4 timestamp, + PRIMARY KEY (category_code) +) WITHOUT OIDS; + + +-- 栏目与角色关联表 +CREATE TABLE js_cms_category_role +( + category_code varchar(64) NOT NULL, + role_code varchar(64) NOT NULL, + ctrl_type varchar(32), + PRIMARY KEY (category_code, role_code) +) WITHOUT OIDS; + + +-- 文章评论表 +CREATE TABLE js_cms_comment +( + id varchar(64) NOT NULL, + category_code varchar(64) NOT NULL, + article_id varchar(64) NOT NULL, + parent_id varchar(64), + article_title varchar(255) NOT NULL, + content varchar(255) NOT NULL, + name varchar(50), + ip varchar(100), + create_by varchar(64), + create_date timestamp NOT NULL, + audit_user_code varchar(64), + audit_date timestamp, + audit_comment varchar(200), + hits_plus numeric(10), + hits_minus numeric(10), + status char(1) NOT NULL, + corp_code varchar(64) DEFAULT '0' NOT NULL, + corp_name varchar(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +) WITHOUT OIDS; + + +-- 留言板表 +CREATE TABLE js_cms_guestbook +( + id varchar(64) NOT NULL, + type char(1) NOT NULL, + content varchar(255) NOT NULL, + name varchar(100) NOT NULL, + email varchar(100) NOT NULL, + phone varchar(100) NOT NULL, + workunit varchar(100) NOT NULL, + ip varchar(100) NOT NULL, + create_by varchar(64), + create_date timestamp, + re_user_code varchar(64), + re_date timestamp, + re_content varchar(100), + status char(1) NOT NULL, + corp_code varchar(64) DEFAULT '0' NOT NULL, + corp_name varchar(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +) WITHOUT OIDS; + + +-- 内容举报表 +CREATE TABLE js_cms_report +( + id varchar(64) NOT NULL, + report_source char(1), + report_content varchar(500), + report_url varchar(1000), + report_type char(1), + report_cause varchar(500), + PRIMARY KEY (id) +) WITHOUT OIDS; + + +-- 站点表 +CREATE TABLE js_cms_site +( + site_code varchar(64) NOT NULL, + site_name varchar(100) NOT NULL, + site_sort decimal(10), + title varchar(100) NOT NULL, + logo varchar(1000), + domain varchar(500), + keywords varchar(500), + description varchar(500), + theme varchar(500), + copyright varchar(1000), + custom_index_view varchar(500), + status char(1) DEFAULT '0' NOT NULL, + create_by varchar(64) NOT NULL, + create_date timestamp NOT NULL, + update_by varchar(64) NOT NULL, + update_date timestamp NOT NULL, + remarks varchar(500), + PRIMARY KEY (site_code) +) WITHOUT OIDS; + + +-- 内容标签 +CREATE TABLE js_cms_tag +( + tag_name varchar(200) NOT NULL, + clicknum numeric(10) NOT NULL, + PRIMARY KEY (tag_name) +) WITHOUT OIDS; + + +-- 访问日志表 +CREATE TABLE js_cms_visit_log +( + id varchar(64) NOT NULL, + request_url varchar(1000), + request_url_host varchar(128), + source_referer varchar(1000), + source_referer_host varchar(128), + source_type char(1), + search_engine varchar(200), + search_word varchar(200), + remote_addr varchar(50), + user_agent varchar(500), + user_language varchar(32), + user_screen_size varchar(32), + user_device varchar(32), + user_os_name varchar(32), + user_browser varchar(32), + user_browser_version varchar(16), + unique_visit_id varchar(64), + visit_date char(8), + visit_time timestamp, + is_new_visit char(1), + first_visit_time decimal(20), + prev_remain_time decimal(20), + total_remain_time decimal(20), + site_code varchar(64), + site_name varchar(100), + category_code varchar(64), + category_name varchar(100), + content_id varchar(64), + content_title varchar(255), + visit_user_code varchar(100), + visit_user_name varchar(100), + corp_code varchar(64) DEFAULT '0' NOT NULL, + corp_name varchar(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +) WITHOUT OIDS; + + + +/* Create Indexes */ + +CREATE INDEX idx_cms_article_cb ON js_cms_article (create_by); +CREATE INDEX idx_cms_article_cc ON js_cms_article (category_code); +CREATE INDEX idx_cms_article_corp_code ON js_cms_article (corp_code); +CREATE INDEX idx_cms_article_status ON js_cms_article (status); +CREATE INDEX idx_cms_article_ud ON js_cms_article (update_date); +CREATE INDEX idx_cms_article_weight ON js_cms_article (weight); +CREATE INDEX idx_cms_category_pc ON js_cms_category (parent_code); +CREATE INDEX idx_cms_category_ts ON js_cms_category (tree_sort); +CREATE INDEX idx_cms_category_status ON js_cms_category (status); +CREATE INDEX idx_cms_category_tss ON js_cms_category (tree_sorts); +CREATE INDEX idx_cms_comment_catc ON js_cms_comment (category_code); +CREATE INDEX idx_cms_comment_ai ON js_cms_comment (article_id); +CREATE INDEX idx_cms_comment_cc ON js_cms_comment (corp_code); +CREATE INDEX idx_cms_comment_status ON js_cms_comment (status); +CREATE INDEX idx_cms_guestbook_cc ON js_cms_guestbook (corp_code); +CREATE INDEX idx_cms_guestbook_status ON js_cms_guestbook (status); +CREATE INDEX idx_cms_guestbook_type ON js_cms_guestbook (type); +CREATE INDEX idx_cms_site_status ON js_cms_site (status); +CREATE INDEX cms_visit_log_cc ON js_cms_visit_log (category_code); +CREATE INDEX cms_visit_log_ci ON js_cms_visit_log (content_id); +CREATE INDEX cms_visit_log_fvt ON js_cms_visit_log (first_visit_time); +CREATE INDEX cms_visit_log_inv ON js_cms_visit_log (is_new_visit); +CREATE INDEX cms_visit_log_ra ON js_cms_visit_log (remote_addr); +CREATE INDEX cms_visit_log_sc ON js_cms_visit_log (site_code); +CREATE INDEX cms_visit_log_uvid ON js_cms_visit_log (unique_visit_id); +CREATE INDEX cms_visit_log_vd ON js_cms_visit_log (visit_date); +CREATE INDEX cms_visit_log_vt ON js_cms_visit_log (visit_time); +CREATE INDEX idx_cms_visit_log_corpc ON js_cms_visit_log (corp_code); + + + +/* Comments */ + +COMMENT ON TABLE js_cms_article IS '文章表'; +COMMENT ON COLUMN js_cms_article.id IS '编号'; +COMMENT ON COLUMN js_cms_article.category_code IS '栏目编码'; +COMMENT ON COLUMN js_cms_article.module_type IS '模块类型'; +COMMENT ON COLUMN js_cms_article.title IS '内容标题'; +COMMENT ON COLUMN js_cms_article.href IS '外部链接'; +COMMENT ON COLUMN js_cms_article.color IS '标题颜色'; +COMMENT ON COLUMN js_cms_article.image IS '内容图片'; +COMMENT ON COLUMN js_cms_article.keywords IS '关键字'; +COMMENT ON COLUMN js_cms_article.description IS '描述'; +COMMENT ON COLUMN js_cms_article.weight IS '权重,越大越靠前'; +COMMENT ON COLUMN js_cms_article.weight_date IS '权重期限'; +COMMENT ON COLUMN js_cms_article.source IS '来源(转载/原创)'; +COMMENT ON COLUMN js_cms_article.copyfrom IS '文章来源出处'; +COMMENT ON COLUMN js_cms_article.hits IS '点击数'; +COMMENT ON COLUMN js_cms_article.hits_plus IS '支持数'; +COMMENT ON COLUMN js_cms_article.hits_minus IS '反对数'; +COMMENT ON COLUMN js_cms_article.word_count IS '字数(不包含html)'; +COMMENT ON COLUMN js_cms_article.custom_content_view IS '自定义内容视图'; +COMMENT ON COLUMN js_cms_article.view_config IS '视图配置'; +COMMENT ON COLUMN js_cms_article.status IS '状态(0正常 1删除 2停用)'; +COMMENT ON COLUMN js_cms_article.create_by IS '创建者'; +COMMENT ON COLUMN js_cms_article.create_date IS '创建时间'; +COMMENT ON COLUMN js_cms_article.update_by IS '更新者'; +COMMENT ON COLUMN js_cms_article.update_date IS '更新时间'; +COMMENT ON COLUMN js_cms_article.remarks IS '备注信息'; +COMMENT ON COLUMN js_cms_article.corp_code IS '租户代码'; +COMMENT ON COLUMN js_cms_article.corp_name IS '租户名称'; +COMMENT ON TABLE js_cms_article_data IS '文章详情表'; +COMMENT ON COLUMN js_cms_article_data.id IS '编号'; +COMMENT ON COLUMN js_cms_article_data.content IS '文章内容'; +COMMENT ON COLUMN js_cms_article_data.relation IS '相关文章'; +COMMENT ON COLUMN js_cms_article_data.is_can_comment IS '是否允许评论'; +COMMENT ON COLUMN js_cms_article_data.extend_s1 IS '扩展 String 1'; +COMMENT ON COLUMN js_cms_article_data.extend_s2 IS '扩展 String 2'; +COMMENT ON COLUMN js_cms_article_data.extend_s3 IS '扩展 String 3'; +COMMENT ON COLUMN js_cms_article_data.extend_s4 IS '扩展 String 4'; +COMMENT ON COLUMN js_cms_article_data.extend_s5 IS '扩展 String 5'; +COMMENT ON COLUMN js_cms_article_data.extend_s6 IS '扩展 String 6'; +COMMENT ON COLUMN js_cms_article_data.extend_s7 IS '扩展 String 7'; +COMMENT ON COLUMN js_cms_article_data.extend_s8 IS '扩展 String 8'; +COMMENT ON COLUMN js_cms_article_data.extend_i1 IS '扩展 Integer 1'; +COMMENT ON COLUMN js_cms_article_data.extend_i2 IS '扩展 Integer 2'; +COMMENT ON COLUMN js_cms_article_data.extend_i3 IS '扩展 Integer 3'; +COMMENT ON COLUMN js_cms_article_data.extend_i4 IS '扩展 Integer 4'; +COMMENT ON COLUMN js_cms_article_data.extend_f1 IS '扩展 Float 1'; +COMMENT ON COLUMN js_cms_article_data.extend_f2 IS '扩展 Float 2'; +COMMENT ON COLUMN js_cms_article_data.extend_f3 IS '扩展 Float 3'; +COMMENT ON COLUMN js_cms_article_data.extend_f4 IS '扩展 Float 4'; +COMMENT ON COLUMN js_cms_article_data.extend_d1 IS '扩展 Date 1'; +COMMENT ON COLUMN js_cms_article_data.extend_d2 IS '扩展 Date 2'; +COMMENT ON COLUMN js_cms_article_data.extend_d3 IS '扩展 Date 3'; +COMMENT ON COLUMN js_cms_article_data.extend_d4 IS '扩展 Date 4'; +COMMENT ON TABLE js_cms_article_posid IS '文章推荐位'; +COMMENT ON COLUMN js_cms_article_posid.article_id IS '内容编号'; +COMMENT ON COLUMN js_cms_article_posid.postid IS '推荐位置(1轮播图 2首页推荐 3栏目页面)'; +COMMENT ON TABLE js_cms_article_tag IS '文章与标签关系'; +COMMENT ON COLUMN js_cms_article_tag.article_id IS '内容编号'; +COMMENT ON COLUMN js_cms_article_tag.tag_name IS '标签名称'; +COMMENT ON TABLE js_cms_category IS '栏目表'; +COMMENT ON COLUMN js_cms_category.category_code IS '栏目编码'; +COMMENT ON COLUMN js_cms_category.parent_code IS '父级编号'; +COMMENT ON COLUMN js_cms_category.parent_codes IS '所有父级编号'; +COMMENT ON COLUMN js_cms_category.tree_sort IS '本级排序号(升序)'; +COMMENT ON COLUMN js_cms_category.tree_sorts IS '所有级别排序号'; +COMMENT ON COLUMN js_cms_category.tree_leaf IS '是否最末级'; +COMMENT ON COLUMN js_cms_category.tree_level IS '层次级别'; +COMMENT ON COLUMN js_cms_category.tree_names IS '全节点名'; +COMMENT ON COLUMN js_cms_category.category_name IS '栏目名称'; +COMMENT ON COLUMN js_cms_category.site_code IS '站点编码'; +COMMENT ON COLUMN js_cms_category.module_type IS '模块类型'; +COMMENT ON COLUMN js_cms_category.image IS '栏目图片'; +COMMENT ON COLUMN js_cms_category.href IS '链接'; +COMMENT ON COLUMN js_cms_category.target IS '目标'; +COMMENT ON COLUMN js_cms_category.keywords IS '关键字'; +COMMENT ON COLUMN js_cms_category.description IS '描述'; +COMMENT ON COLUMN js_cms_category.in_menu IS '是否在导航中显示'; +COMMENT ON COLUMN js_cms_category.in_list IS '是否在分类页中显示列表'; +COMMENT ON COLUMN js_cms_category.show_modes IS '展现模式'; +COMMENT ON COLUMN js_cms_category.is_need_audit IS '是否需要审核'; +COMMENT ON COLUMN js_cms_category.is_can_comment IS '是否允许评论'; +COMMENT ON COLUMN js_cms_category.custom_list_view IS '自定义列表视图'; +COMMENT ON COLUMN js_cms_category.custom_content_view IS '自定义内容视图'; +COMMENT ON COLUMN js_cms_category.view_config IS '视图配置'; +COMMENT ON COLUMN js_cms_category.status IS '状态(0正常 1删除 2停用)'; +COMMENT ON COLUMN js_cms_category.create_by IS '创建者'; +COMMENT ON COLUMN js_cms_category.create_date IS '创建时间'; +COMMENT ON COLUMN js_cms_category.update_by IS '更新者'; +COMMENT ON COLUMN js_cms_category.update_date IS '更新时间'; +COMMENT ON COLUMN js_cms_category.remarks IS '备注信息'; +COMMENT ON COLUMN js_cms_category.extend_s1 IS '扩展 String 1'; +COMMENT ON COLUMN js_cms_category.extend_s2 IS '扩展 String 2'; +COMMENT ON COLUMN js_cms_category.extend_s3 IS '扩展 String 3'; +COMMENT ON COLUMN js_cms_category.extend_s4 IS '扩展 String 4'; +COMMENT ON COLUMN js_cms_category.extend_s5 IS '扩展 String 5'; +COMMENT ON COLUMN js_cms_category.extend_s6 IS '扩展 String 6'; +COMMENT ON COLUMN js_cms_category.extend_s7 IS '扩展 String 7'; +COMMENT ON COLUMN js_cms_category.extend_s8 IS '扩展 String 8'; +COMMENT ON COLUMN js_cms_category.extend_i1 IS '扩展 Integer 1'; +COMMENT ON COLUMN js_cms_category.extend_i2 IS '扩展 Integer 2'; +COMMENT ON COLUMN js_cms_category.extend_i3 IS '扩展 Integer 3'; +COMMENT ON COLUMN js_cms_category.extend_i4 IS '扩展 Integer 4'; +COMMENT ON COLUMN js_cms_category.extend_f1 IS '扩展 Float 1'; +COMMENT ON COLUMN js_cms_category.extend_f2 IS '扩展 Float 2'; +COMMENT ON COLUMN js_cms_category.extend_f3 IS '扩展 Float 3'; +COMMENT ON COLUMN js_cms_category.extend_f4 IS '扩展 Float 4'; +COMMENT ON COLUMN js_cms_category.extend_d1 IS '扩展 Date 1'; +COMMENT ON COLUMN js_cms_category.extend_d2 IS '扩展 Date 2'; +COMMENT ON COLUMN js_cms_category.extend_d3 IS '扩展 Date 3'; +COMMENT ON COLUMN js_cms_category.extend_d4 IS '扩展 Date 4'; +COMMENT ON TABLE js_cms_category_role IS '栏目与角色关联表'; +COMMENT ON COLUMN js_cms_category_role.category_code IS '栏目编码'; +COMMENT ON COLUMN js_cms_category_role.role_code IS '角色编码'; +COMMENT ON COLUMN js_cms_category_role.ctrl_type IS '控制类型(view查看、edit编辑)'; +COMMENT ON TABLE js_cms_comment IS '文章评论表'; +COMMENT ON COLUMN js_cms_comment.id IS '编号'; +COMMENT ON COLUMN js_cms_comment.category_code IS '栏目编码'; +COMMENT ON COLUMN js_cms_comment.article_id IS '内容编号'; +COMMENT ON COLUMN js_cms_comment.parent_id IS '父级评论'; +COMMENT ON COLUMN js_cms_comment.article_title IS '内容标题'; +COMMENT ON COLUMN js_cms_comment.content IS '评论内容'; +COMMENT ON COLUMN js_cms_comment.name IS '评论姓名'; +COMMENT ON COLUMN js_cms_comment.ip IS '评论IP'; +COMMENT ON COLUMN js_cms_comment.create_by IS '创建者'; +COMMENT ON COLUMN js_cms_comment.create_date IS '创建时间'; +COMMENT ON COLUMN js_cms_comment.audit_user_code IS '审核人'; +COMMENT ON COLUMN js_cms_comment.audit_date IS '审核时间'; +COMMENT ON COLUMN js_cms_comment.audit_comment IS '审核意见'; +COMMENT ON COLUMN js_cms_comment.hits_plus IS '支持数'; +COMMENT ON COLUMN js_cms_comment.hits_minus IS '反对数'; +COMMENT ON COLUMN js_cms_comment.status IS '状态(0正常 1删除 2停用)'; +COMMENT ON COLUMN js_cms_comment.corp_code IS '租户代码'; +COMMENT ON COLUMN js_cms_comment.corp_name IS '租户名称'; +COMMENT ON TABLE js_cms_guestbook IS '留言板表'; +COMMENT ON COLUMN js_cms_guestbook.id IS '编号'; +COMMENT ON COLUMN js_cms_guestbook.type IS '留言分类'; +COMMENT ON COLUMN js_cms_guestbook.content IS '留言内容'; +COMMENT ON COLUMN js_cms_guestbook.name IS '姓名'; +COMMENT ON COLUMN js_cms_guestbook.email IS '邮箱'; +COMMENT ON COLUMN js_cms_guestbook.phone IS '电话'; +COMMENT ON COLUMN js_cms_guestbook.workunit IS '单位'; +COMMENT ON COLUMN js_cms_guestbook.ip IS 'IP'; +COMMENT ON COLUMN js_cms_guestbook.create_by IS '创建者'; +COMMENT ON COLUMN js_cms_guestbook.create_date IS '创建时间'; +COMMENT ON COLUMN js_cms_guestbook.re_user_code IS '回复人'; +COMMENT ON COLUMN js_cms_guestbook.re_date IS '回复时间'; +COMMENT ON COLUMN js_cms_guestbook.re_content IS '回复内容'; +COMMENT ON COLUMN js_cms_guestbook.status IS '状态(0正常 1删除 2停用)'; +COMMENT ON COLUMN js_cms_guestbook.corp_code IS '租户代码'; +COMMENT ON COLUMN js_cms_guestbook.corp_name IS '租户名称'; +COMMENT ON TABLE js_cms_report IS '内容举报表'; +COMMENT ON COLUMN js_cms_report.id IS '编号'; +COMMENT ON COLUMN js_cms_report.report_source IS '举报来源(1文章、2评论)'; +COMMENT ON COLUMN js_cms_report.report_content IS '举报内容(文章标题 评论内容)'; +COMMENT ON COLUMN js_cms_report.report_url IS '举报的URL'; +COMMENT ON COLUMN js_cms_report.report_type IS '举报类型(色情 政治...)'; +COMMENT ON COLUMN js_cms_report.report_cause IS '举报原因'; +COMMENT ON TABLE js_cms_site IS '站点表'; +COMMENT ON COLUMN js_cms_site.site_code IS '站点编码'; +COMMENT ON COLUMN js_cms_site.site_name IS '站点名称'; +COMMENT ON COLUMN js_cms_site.site_sort IS '站点排序号'; +COMMENT ON COLUMN js_cms_site.title IS '站点标题'; +COMMENT ON COLUMN js_cms_site.logo IS '站点Logo'; +COMMENT ON COLUMN js_cms_site.domain IS '站点域名'; +COMMENT ON COLUMN js_cms_site.keywords IS '关键字'; +COMMENT ON COLUMN js_cms_site.description IS '描述'; +COMMENT ON COLUMN js_cms_site.theme IS '主题'; +COMMENT ON COLUMN js_cms_site.copyright IS '版权信息'; +COMMENT ON COLUMN js_cms_site.custom_index_view IS '自定义站点首页视图'; +COMMENT ON COLUMN js_cms_site.status IS '状态(0正常 1删除 2停用)'; +COMMENT ON COLUMN js_cms_site.create_by IS '创建者'; +COMMENT ON COLUMN js_cms_site.create_date IS '创建时间'; +COMMENT ON COLUMN js_cms_site.update_by IS '更新者'; +COMMENT ON COLUMN js_cms_site.update_date IS '更新时间'; +COMMENT ON COLUMN js_cms_site.remarks IS '备注信息'; +COMMENT ON TABLE js_cms_tag IS '内容标签'; +COMMENT ON COLUMN js_cms_tag.tag_name IS '标签名称'; +COMMENT ON COLUMN js_cms_tag.clicknum IS '点击次数'; +COMMENT ON TABLE js_cms_visit_log IS '访问日志表'; +COMMENT ON COLUMN js_cms_visit_log.id IS '编号'; +COMMENT ON COLUMN js_cms_visit_log.request_url IS '请求的URL地址'; +COMMENT ON COLUMN js_cms_visit_log.request_url_host IS '受访域名'; +COMMENT ON COLUMN js_cms_visit_log.source_referer IS '来源页面/上一个页面'; +COMMENT ON COLUMN js_cms_visit_log.source_referer_host IS '来源域名'; +COMMENT ON COLUMN js_cms_visit_log.source_type IS '访问来源类型(1直接访问 2搜索引擎 3外部链接 4内部访问)'; +COMMENT ON COLUMN js_cms_visit_log.search_engine IS '使用的搜索引擎'; +COMMENT ON COLUMN js_cms_visit_log.search_word IS '搜索的关键词'; +COMMENT ON COLUMN js_cms_visit_log.remote_addr IS '客户IP地址'; +COMMENT ON COLUMN js_cms_visit_log.user_agent IS '用户代理字符串'; +COMMENT ON COLUMN js_cms_visit_log.user_language IS '客户机语言'; +COMMENT ON COLUMN js_cms_visit_log.user_screen_size IS '客户机屏幕大小0x0'; +COMMENT ON COLUMN js_cms_visit_log.user_device IS '客户机设备类型(电脑、平板、手机、未知)'; +COMMENT ON COLUMN js_cms_visit_log.user_os_name IS '客户机操作系统'; +COMMENT ON COLUMN js_cms_visit_log.user_browser IS '客户机浏览器'; +COMMENT ON COLUMN js_cms_visit_log.user_browser_version IS '浏览器版本'; +COMMENT ON COLUMN js_cms_visit_log.unique_visit_id IS '唯一访问标识'; +COMMENT ON COLUMN js_cms_visit_log.visit_date IS '本次访问日期(年月日)'; +COMMENT ON COLUMN js_cms_visit_log.visit_time IS '本次访问时间'; +COMMENT ON COLUMN js_cms_visit_log.is_new_visit IS '是否新访问(30分内)'; +COMMENT ON COLUMN js_cms_visit_log.first_visit_time IS '首次访问时间戳(30分钟内)'; +COMMENT ON COLUMN js_cms_visit_log.prev_remain_time IS '上页面停留时间(秒)'; +COMMENT ON COLUMN js_cms_visit_log.total_remain_time IS '本次访问总停留时间(秒)'; +COMMENT ON COLUMN js_cms_visit_log.site_code IS '站点编码'; +COMMENT ON COLUMN js_cms_visit_log.site_name IS '站点名称'; +COMMENT ON COLUMN js_cms_visit_log.category_code IS '栏目编码'; +COMMENT ON COLUMN js_cms_visit_log.category_name IS '栏目名称'; +COMMENT ON COLUMN js_cms_visit_log.content_id IS '栏目内容编号'; +COMMENT ON COLUMN js_cms_visit_log.content_title IS '访问页面标题'; +COMMENT ON COLUMN js_cms_visit_log.visit_user_code IS '访问用户编码'; +COMMENT ON COLUMN js_cms_visit_log.visit_user_name IS '访问用户姓名'; +COMMENT ON COLUMN js_cms_visit_log.corp_code IS '租户代码'; +COMMENT ON COLUMN js_cms_visit_log.corp_name IS '租户名称'; + + + diff --git a/modules/cms/pom.xml b/modules/cms/pom.xml new file mode 100644 index 00000000..f072d0d1 --- /dev/null +++ b/modules/cms/pom.xml @@ -0,0 +1,84 @@ + + + 4.0.0 + + + com.jeesite + jeesite-parent + 4.2.3-SNAPSHOT + ../../parent/pom.xml + + + jeesite-module-cms + + JeeSite Module CMS + http://jeesite.com + 2013-Now + + + + + + + + + com.jeesite + jeesite-module-core + ${project.parent.version} + + + + + + + + + + + + + + + + + + + + thinkgem + WangZhen + thinkgem at 163.com + + Project lead + + +8 + + + + + JeeSite + http://jeesite.com + + + + aliyun-repos + https://maven.aliyun.com/repository/public + + true + + + false + + + + + + + aliyun-repos + https://maven.aliyun.com/repository/public + + + + diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/dao/ArticleDao.java b/modules/cms/src/main/java/com/jeesite/modules/cms/dao/ArticleDao.java new file mode 100644 index 00000000..b51ad8c0 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/dao/ArticleDao.java @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.dao; + +import com.jeesite.common.dao.CrudDao; +import com.jeesite.common.mybatis.annotation.MyBatisDao; +import com.jeesite.modules.cms.entity.Article; + +/** + * 文章表DAO接口 + * @author 长春叭哥 + * @version 2018-10-15 + */ +@MyBatisDao +public interface ArticleDao extends CrudDao
{ + + public long updateExpiredWeight(Article article); + + public long updateHitsAddOne(String id); + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/dao/ArticleDataDao.java b/modules/cms/src/main/java/com/jeesite/modules/cms/dao/ArticleDataDao.java new file mode 100644 index 00000000..28bbac73 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/dao/ArticleDataDao.java @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.dao; + +import com.jeesite.common.dao.CrudDao; +import com.jeesite.common.mybatis.annotation.MyBatisDao; +import com.jeesite.modules.cms.entity.ArticleData; + +/** + * 文章详情表DAO接口 + * @author 长春叭哥 + * @version 2018-10-15 + */ +@MyBatisDao +public interface ArticleDataDao extends CrudDao { + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/dao/ArticlePosidDao.java b/modules/cms/src/main/java/com/jeesite/modules/cms/dao/ArticlePosidDao.java new file mode 100644 index 00000000..3482abbf --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/dao/ArticlePosidDao.java @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.dao; + +import com.jeesite.common.dao.CrudDao; +import com.jeesite.common.mybatis.annotation.MyBatisDao; +import com.jeesite.modules.cms.entity.ArticlePosid; + +/** + * 文章推荐位DAO接口 + * @author 长春叭哥 + * @version 2018-10-15 + */ +@MyBatisDao +public interface ArticlePosidDao extends CrudDao { + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/dao/ArticleTagDao.java b/modules/cms/src/main/java/com/jeesite/modules/cms/dao/ArticleTagDao.java new file mode 100644 index 00000000..f474d516 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/dao/ArticleTagDao.java @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.dao; + +import com.jeesite.common.dao.CrudDao; +import com.jeesite.common.mybatis.annotation.MyBatisDao; +import com.jeesite.modules.cms.entity.ArticleTag; + +/** + * 文章与标签关系DAO接口 + * @author 长春叭哥 + * @version 2018-10-15 + */ +@MyBatisDao +public interface ArticleTagDao extends CrudDao { + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/dao/CategoryDao.java b/modules/cms/src/main/java/com/jeesite/modules/cms/dao/CategoryDao.java new file mode 100644 index 00000000..eadba861 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/dao/CategoryDao.java @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.dao; + +import com.jeesite.common.dao.TreeDao; +import com.jeesite.common.mybatis.annotation.MyBatisDao; +import com.jeesite.modules.cms.entity.Category; + +/** + * 栏目表DAO接口 + * @author 长春叭哥 + * @version 2018-10-15 + */ +@MyBatisDao +public interface CategoryDao extends TreeDao { + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/dao/CategoryRoleDao.java b/modules/cms/src/main/java/com/jeesite/modules/cms/dao/CategoryRoleDao.java new file mode 100644 index 00000000..a19fcf4f --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/dao/CategoryRoleDao.java @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.dao; + +import com.jeesite.common.dao.CrudDao; +import com.jeesite.common.mybatis.annotation.MyBatisDao; +import com.jeesite.modules.cms.entity.CategoryRole; + +/** + * 栏目与角色关联表DAO接口 + * @author 长春叭哥 + * @version 2018-10-15 + */ +@MyBatisDao +public interface CategoryRoleDao extends CrudDao { + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/dao/CommentDao.java b/modules/cms/src/main/java/com/jeesite/modules/cms/dao/CommentDao.java new file mode 100644 index 00000000..d3760f2e --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/dao/CommentDao.java @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.dao; + +import com.jeesite.common.dao.CrudDao; +import com.jeesite.common.mybatis.annotation.MyBatisDao; +import com.jeesite.modules.cms.entity.Comment; + +/** + * 文章评论表DAO接口 + * @author 长春叭哥 + * @version 2018-10-15 + */ +@MyBatisDao +public interface CommentDao extends CrudDao { + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/dao/ReportDao.java b/modules/cms/src/main/java/com/jeesite/modules/cms/dao/ReportDao.java new file mode 100644 index 00000000..1f2778a4 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/dao/ReportDao.java @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.dao; + +import com.jeesite.common.dao.CrudDao; +import com.jeesite.common.mybatis.annotation.MyBatisDao; +import com.jeesite.modules.cms.entity.Report; + +/** + * 内容举报表DAO接口 + * @author 长春叭哥 + * @version 2018-10-15 + */ +@MyBatisDao +public interface ReportDao extends CrudDao { + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/dao/SiteDao.java b/modules/cms/src/main/java/com/jeesite/modules/cms/dao/SiteDao.java new file mode 100644 index 00000000..a1117715 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/dao/SiteDao.java @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.dao; + +import com.jeesite.common.dao.CrudDao; +import com.jeesite.common.mybatis.annotation.MyBatisDao; +import com.jeesite.modules.cms.entity.Site; + +/** + * 站点表DAO接口 + * @author 长春叭哥 + * @version 2018-10-15 + */ +@MyBatisDao +public interface SiteDao extends CrudDao { + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/dao/TagDao.java b/modules/cms/src/main/java/com/jeesite/modules/cms/dao/TagDao.java new file mode 100644 index 00000000..a24c4b65 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/dao/TagDao.java @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.dao; + +import com.jeesite.common.dao.CrudDao; +import com.jeesite.common.mybatis.annotation.MyBatisDao; +import com.jeesite.modules.cms.entity.Tag; + +/** + * 内容标签DAO接口 + * @author 长春叭哥 + * @version 2018-10-15 + */ +@MyBatisDao +public interface TagDao extends CrudDao { + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/dao/VisitLogDao.java b/modules/cms/src/main/java/com/jeesite/modules/cms/dao/VisitLogDao.java new file mode 100644 index 00000000..547c70bb --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/dao/VisitLogDao.java @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.dao; + +import com.jeesite.common.dao.CrudDao; +import com.jeesite.common.mybatis.annotation.MyBatisDao; +import com.jeesite.modules.cms.entity.VisitLog; + +/** + * 访问日志表DAO接口 + * @author 长春叭哥 + * @version 2018-10-15 + */ +@MyBatisDao +public interface VisitLogDao extends CrudDao { + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/db/InitCmsData.java b/modules/cms/src/main/java/com/jeesite/modules/cms/db/InitCmsData.java new file mode 100644 index 00000000..5451f777 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/db/InitCmsData.java @@ -0,0 +1,122 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.db; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Component; + +import com.jeesite.common.callback.MethodCallback; +import com.jeesite.common.config.Global; +import com.jeesite.common.tests.BaseInitDataTests; +import com.jeesite.modules.cms.dao.ArticleDao; +import com.jeesite.modules.cms.dao.ArticleDataDao; +import com.jeesite.modules.cms.entity.Article; +import com.jeesite.modules.cms.entity.ArticleData; +import com.jeesite.modules.cms.entity.Category; +import com.jeesite.modules.cms.entity.Site; +import com.jeesite.modules.cms.service.CategoryService; +import com.jeesite.modules.cms.service.SiteService; +import com.jeesite.modules.gen.utils.GenUtils; + +/** + * 初始化CMS表及数据 + * @author ThinkGem + * @version 2020-5-26 + */ +@Component +@ConditionalOnProperty(name="jeesite.initdata", havingValue="true", matchIfMissing=false) +public class InitCmsData extends BaseInitDataTests { + + @Override + public boolean initData() throws Exception { + if (GenUtils.isTableExists(Global.getTablePrefix() + "cms_article")) { + return true; // 如果表已存在,则无需初始化 + } + + this.runCreateScript("cms.sql"); + this.initModuleInfo("cms"); + this.initModuleMenu("/cms/index"); + this.initModuleDict("cms_theme"); + this.initSite(); + this.initCategory(); + this.initArticle(); + this.initArticleData(); + + return true; + } + + @Autowired + private SiteService siteService; + public void initSite() throws Exception{ + initExcelData(Site.class, new MethodCallback() { + @Override + public Object execute(Object... params) { + String action = (String)params[0]; + if("save".equals(action)){ + Site entity = (Site)params[1]; + entity.setIsNewRecord(true); + siteService.save(entity); + return null; + } + return null; + } + }); + } + + @Autowired + private CategoryService categoryService; + public void initCategory() throws Exception{ + initExcelData(Category.class, new MethodCallback() { + @Override + public Object execute(Object... params) { + String action = (String)params[0]; + if("save".equals(action)){ + Category entity = (Category)params[1]; + entity.setIsNewRecord(true); + categoryService.save(entity); + return null; + } + return null; + } + }); + } + + @Autowired + private ArticleDao articleDao; + public void initArticle() throws Exception{ + initExcelData(Article.class, new MethodCallback() { + @Override + public Object execute(Object... params) { + String action = (String)params[0]; + if("save".equals(action)){ + Article entity = (Article)params[1]; + entity.setIsNewRecord(true); + articleDao.insert(entity); + return null; + } + return null; + } + }); + } + + @Autowired + private ArticleDataDao articleDataDao; + public void initArticleData() throws Exception{ + initExcelData(ArticleData.class, new MethodCallback() { + @Override + public Object execute(Object... params) { + String action = (String)params[0]; + if("save".equals(action)){ + ArticleData entity = (ArticleData)params[1]; + entity.setIsNewRecord(true); + articleDataDao.insert(entity); + return null; + } + return null; + } + }); + } + +} diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/db/InitCmsData.xlsx b/modules/cms/src/main/java/com/jeesite/modules/cms/db/InitCmsData.xlsx new file mode 100644 index 00000000..16bad179 Binary files /dev/null and b/modules/cms/src/main/java/com/jeesite/modules/cms/db/InitCmsData.xlsx differ diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/entity/Article.java b/modules/cms/src/main/java/com/jeesite/modules/cms/entity/Article.java new file mode 100644 index 00000000..c6cf4afa --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/entity/Article.java @@ -0,0 +1,311 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.entity; + +import java.util.Date; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import org.hibernate.validator.constraints.Length; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.jeesite.common.entity.BaseEntity; +import com.jeesite.common.entity.DataEntity; +import com.jeesite.common.mybatis.annotation.Column; +import com.jeesite.common.mybatis.annotation.JoinTable; +import com.jeesite.common.mybatis.annotation.Table; +import com.jeesite.common.mybatis.mapper.query.QueryType; +import com.jeesite.modules.cms.utils.CmsUtils; + +/** + * 文章表Entity + * @author 长春叭哥、ThinkGem + * @version 2018-10-15 + */ +@Table(name = "${_prefix}cms_article", alias = "a", columns = { + @Column(name = "id", attrName = "id", label = "编号", isPK = true), + @Column(name = "category_code", attrName = "category.categoryCode", label = "栏目编码"), + @Column(name = "module_type", attrName = "moduleType", label = "模块类型"), + @Column(name = "title", attrName = "title", label = "内容标题", queryType = QueryType.LIKE), + @Column(name = "href", attrName = "href", label = "外部链接"), + @Column(name = "color", attrName = "color", label = "标题颜色"), + @Column(name = "image", attrName = "image", label = "内容图片"), + @Column(name = "keywords", attrName = "keywords", label = "关键字", queryType = QueryType.LIKE), + @Column(name = "description", attrName = "description", label = "描述"), + @Column(name = "weight", attrName = "weight", label = "权重,越大越靠前", isQuery = false), + @Column(name = "weight_date", attrName = "weightDate", label = "权重期限", isQuery = false), + @Column(name = "source", attrName = "source", label = "来源", comment = "来源(转载/原创)"), + @Column(name = "copyfrom", attrName = "copyfrom", label = "文章来源出处"), + @Column(name = "hits", attrName = "hits", label = "点击数"), + @Column(name = "hits_plus", attrName = "hitsPlus", label = "支持数"), + @Column(name = "hits_minus", attrName = "hitsMinus", label = "反对数"), + @Column(name = "word_count", attrName = "wordCount", label = "字数", comment = "字数(不包含html)"), + @Column(name = "custom_content_view", attrName = "customContentView", label = "自定义内容视图"), + @Column(name = "view_config", attrName = "viewConfig", label = "视图配置"), + @Column(includeEntity = DataEntity.class), + @Column(includeEntity = BaseEntity.class), + }, joinTable = { + @JoinTable(entity = Category.class, alias = "c", + on = "c.category_code = a.category_code", columns = { + @Column(name = "category_name"), + }), + @JoinTable(entity = Site.class, attrName = "category.site", alias = "s", + on = "s.site_code = c.site_code", columns = { + @Column(name = "site_code"), + @Column(name = "site_name"), + }) + }, orderBy = "a.update_date DESC" +) +public class Article extends DataEntity
{ + + public static final String DEFAULT_TEMPLATE = "viewArticle"; // 默认文章内容模板 + private static final long serialVersionUID = 1L; + + private Category category; // 栏目编码 + private String moduleType; // 模块类型 + private String title; // 内容标题 + private String href; // 外部链接 + private String color; // 标题颜色 + private String image; // 内容图片 + private String keywords; // 关键字 + private String description; // 描述 + private Integer weight; // 权重,越大越靠前 + private Date weightDate; // 权重期限 + private String source; // 来源(转载/原创) + private String copyfrom; // 文章来源出处 + private Long hits; // 点击数 + + private Integer hitsPlus; // 支持数 + private Integer hitsMinus; // 反对数 + private Integer wordCount; // 字数(不包含html) + private String customContentView; // 自定义内容视图 + private String viewConfig; // 视图配置 + private ArticleData articleData; //文章副表 + private Date beginDate; // 开始时间 + private Date endDate; // 结束时间 + + private Boolean isQueryArticleData; // 是否查询文章内容 + + public Article() { + super(); + //this.weight = 0; + //this.hits = 0l; + } + + public Article(String id) { + super(id); + } + + public Article(Category category) { + this(); + this.category = category; + } + + @NotNull + public Category getCategory() { + if (category == null) { + category = new Category(); + } + return category; + } + + public void setCategory(Category category) { + this.category = category; + } + + @Length(min = 0, max = 50, message = "模块类型长度不能超过 50 个字符") + public String getModuleType() { + return moduleType; + } + + public void setModuleType(String moduleType) { + this.moduleType = moduleType; + } + + @NotBlank(message = "内容标题不能为空") + @Length(min = 0, max = 255, message = "内容标题长度不能超过 255 个字符") + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + @Length(min = 0, max = 1000, message = "外部链接长度不能超过 1000 个字符") + public String getHref() { + return href; + } + + public void setHref(String href) { + this.href = href; + } + + @Length(min = 0, max = 50, message = "标题颜色长度不能超过 50 个字符") + public String getColor() { + return color; + } + + public void setColor(String color) { + this.color = color; + } + + @Length(min = 0, max = 1000, message = "内容图片长度不能超过 1000 个字符") + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } + + @Length(min = 0, max = 500, message = "关键字长度不能超过 500 个字符") + public String getKeywords() { + return keywords; + } + + public void setKeywords(String keywords) { + this.keywords = keywords; + } + + @Length(min = 0, max = 500, message = "描述长度不能超过 500 个字符") + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Integer getWeight() { + return weight; + } + + public void setWeight(Integer weight) { + this.weight = weight; + } + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + public Date getWeightDate() { + return weightDate; + } + + public void setWeightDate(Date weightDate) { + this.weightDate = weightDate; + } + + @Length(min = 0, max = 1, message = "来源长度不能超过 1 个字符") + public String getSource() { + return source; + } + + public void setSource(String source) { + this.source = source; + } + + @Length(min = 0, max = 255, message = "文章来源出处长度不能超过 255 个字符") + public String getCopyfrom() { + return copyfrom; + } + + public void setCopyfrom(String copyfrom) { + this.copyfrom = copyfrom; + } + + public Long getHits() { + return hits; + } + + public void setHits(Long hits) { + this.hits = hits; + } + + + + public Integer getHitsPlus() { + return hitsPlus; + } + + public void setHitsPlus(Integer hitsPlus) { + this.hitsPlus = hitsPlus; + } + + public Integer getHitsMinus() { + return hitsMinus; + } + + public void setHitsMinus(Integer hitsMinus) { + this.hitsMinus = hitsMinus; + } + + public Integer getWordCount() { + return wordCount; + } + + public void setWordCount(Integer wordCount) { + this.wordCount = wordCount; + } + + @Length(min = 0, max = 255, message = "自定义内容视图长度不能超过 255 个字符") + public String getCustomContentView() { + return customContentView; + } + + public void setCustomContentView(String customContentView) { + this.customContentView = customContentView; + } + + @Length(min = 0, max = 1000, message = "视图配置长度不能超过 1000 个字符") + public String getViewConfig() { + return viewConfig; + } + + public void setViewConfig(String viewConfig) { + this.viewConfig = viewConfig; + } + + public ArticleData getArticleData() { + return articleData; + } + + public void setArticleData(ArticleData articleData) { + this.articleData = articleData; + } + + public Date getBeginDate() { + return beginDate; + } + + public void setBeginDate(Date beginDate) { + this.beginDate = beginDate; + } + + public Date getEndDate() { + return endDate; + } + + public void setEndDate(Date endDate) { + this.endDate = endDate; + } + + /** + * 是否查询文章内容 + * @return + */ + public Boolean getIsQueryArticleData() { + return isQueryArticleData; + } + + public void setIsQueryArticleData(Boolean isQueryArticleData) { + this.isQueryArticleData = isQueryArticleData; + } + + + + public String getUrl() { + return CmsUtils.getUrlDynamic(this); + } + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/entity/ArticleData.java b/modules/cms/src/main/java/com/jeesite/modules/cms/entity/ArticleData.java new file mode 100644 index 00000000..51d82019 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/entity/ArticleData.java @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.entity; + +import org.hibernate.validator.constraints.Length; + +import com.jeesite.common.entity.DataEntity; +import com.jeesite.common.entity.Extend; +import com.jeesite.common.mybatis.annotation.Column; +import com.jeesite.common.mybatis.annotation.Table; + +/** + * 文章详情表Entity + * @author 长春叭哥、ThinkGem + * @version 2018-10-15 + */ +@Table(name = "${_prefix}cms_article_data", alias = "a", columns = { + @Column(name = "id", attrName = "id", label = "编号", isPK = true), + @Column(name = "content", attrName = "content", label = "文章内容"), + @Column(name = "relation", attrName = "relation", label = "相关文章"), + @Column(name = "is_can_comment", attrName = "isCanComment", label = "是否允许评论"), + @Column(includeEntity = Extend.class, attrName = "extend"), + }, orderBy = "a.id DESC" +) +public class ArticleData extends DataEntity { + + private static final long serialVersionUID = 1L; + private String content; // 文章内容 + private String relation; // 相关文章 + private String isCanComment; // 是否允许评论 + private Extend extend; // 扩展字段 + + public ArticleData() { + this(null); + } + + public ArticleData(String id) { + super(id); + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + @Length(min = 0, max = 1000, message = "相关文章长度不能超过 1000 个字符") + public String getRelation() { + return relation; + } + + public void setRelation(String relation) { + this.relation = relation; + } + + @Length(min = 0, max = 1, message = "是否允许评论长度不能超过 1 个字符") + public String getIsCanComment() { + return isCanComment; + } + + public void setIsCanComment(String isCanComment) { + this.isCanComment = isCanComment; + } + + public Extend getExtend() { + return extend; + } + + public void setExtend(Extend extend) { + this.extend = extend; + } + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/entity/ArticlePosid.java b/modules/cms/src/main/java/com/jeesite/modules/cms/entity/ArticlePosid.java new file mode 100644 index 00000000..bcf5091c --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/entity/ArticlePosid.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.entity; + +import com.jeesite.common.entity.DataEntity; +import com.jeesite.common.mybatis.annotation.Column; +import com.jeesite.common.mybatis.annotation.Table; + +/** + * 文章推荐位Entity + * @author 长春叭哥、ThinkGem + * @version 2018-10-15 + */ +@Table(name = "${_prefix}cms_article_posid", alias = "a", columns = { + @Column(name = "article_id", attrName = "articleId", label = "内容编号", isPK = true), + @Column(name = "postid", attrName = "postid", label = "推荐位置", comment = "推荐位置(1轮播图 2首页推荐 3栏目页面)", isPK = true), + }, orderBy = "a.article_id DESC, a.postid DESC" +) +public class ArticlePosid extends DataEntity { + + private static final long serialVersionUID = 1L; + private String articleId; // 内容编号 + private String postid; // 推荐位置(1轮播图 2首页推荐 3栏目页面) + + public ArticlePosid() { + + } + + public ArticlePosid(String articleId, String postid) { + this.articleId = articleId; + this.postid = postid; + } + + public String getArticleId() { + return articleId; + } + + public void setArticleId(String articleId) { + this.articleId = articleId; + } + + public String getPostid() { + return postid; + } + + public void setPostid(String postid) { + this.postid = postid; + } + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/entity/ArticleTag.java b/modules/cms/src/main/java/com/jeesite/modules/cms/entity/ArticleTag.java new file mode 100644 index 00000000..8c5b2d83 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/entity/ArticleTag.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.entity; + +import com.jeesite.common.entity.DataEntity; +import com.jeesite.common.mybatis.annotation.Column; +import com.jeesite.common.mybatis.annotation.Table; + +/** + * 文章与标签关系Entity + * @author 长春叭哥、ThinkGem + * @version 2018-10-15 + */ +@Table(name = "${_prefix}cms_article_tag", alias = "a", columns = { + @Column(name = "article_id", attrName = "articleId", label = "内容编号", isPK = true), + @Column(name = "tag_name", attrName = "tagName", label = "标签名称", isPK = true), + }, orderBy = "a.article_id DESC, a.tag_name DESC" +) +public class ArticleTag extends DataEntity { + + private static final long serialVersionUID = 1L; + private String articleId; // 内容编号 + private String tagName; // 标签名称 + + public ArticleTag() { + + } + + public ArticleTag(String articleId, String tagName) { + this.articleId = articleId; + this.tagName = tagName; + } + + public String getArticleId() { + return articleId; + } + + public void setArticleId(String articleId) { + this.articleId = articleId; + } + + public String getTagName() { + return tagName; + } + + public void setTagName(String tagName) { + this.tagName = tagName; + } + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/entity/Category.java b/modules/cms/src/main/java/com/jeesite/modules/cms/entity/Category.java new file mode 100644 index 00000000..089e3c68 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/entity/Category.java @@ -0,0 +1,299 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.entity; + +import java.util.List; + +import javax.validation.constraints.NotBlank; + +import org.hibernate.validator.constraints.Length; + +import com.jeesite.common.collect.ListUtils; +import com.jeesite.common.entity.DataEntity; +import com.jeesite.common.entity.Extend; +import com.jeesite.common.entity.TreeEntity; +import com.jeesite.common.mybatis.annotation.Column; +import com.jeesite.common.mybatis.annotation.JoinTable; +import com.jeesite.common.mybatis.annotation.Table; +import com.jeesite.common.mybatis.mapper.query.QueryType; +import com.jeesite.modules.cms.utils.CmsUtils; + +/** + * 栏目表Entity + * @author 长春叭哥、ThinkGem + * @version 2018-10-15 + */ +@Table(name = "${_prefix}cms_category", alias = "a", columns = { + @Column(name = "category_code", attrName = "categoryCode", label = "栏目编码", isPK = true), @Column(includeEntity = TreeEntity.class), + @Column(name = "category_name", attrName = "categoryName", label = "栏目名称", queryType = QueryType.LIKE, isTreeName = true), + @Column(name = "site_code", attrName = "site.siteCode", label = "站点编码", queryType = QueryType.EQ), + @Column(name = "module_type", attrName = "moduleType", label = "模块类型"), @Column(name = "image", attrName = "image", label = "栏目图片"), + @Column(name = "href", attrName = "href", label = "链接"), @Column(name = "target", attrName = "target", label = "目标"), + @Column(name = "keywords", attrName = "keywords", label = "关键字"), @Column(name = "description", attrName = "description", label = "描述"), + @Column(name = "in_menu", attrName = "inMenu", label = "是否在导航中显示"), @Column(name = "in_list", attrName = "inList", label = "是否在分类页中显示列表"), + @Column(name = "show_modes", attrName = "showModes", label = "展现模式"), + @Column(name = "is_need_audit", attrName = "isNeedAudit", label = "是否需要审核"), + @Column(name = "is_can_comment", attrName = "isCanComment", label = "是否允许评论"), + @Column(name = "custom_list_view", attrName = "customListView", label = "自定义列表视图"), + @Column(name = "custom_content_view", attrName = "customContentView", label = "自定义内容视图"), + @Column(name = "view_config", attrName = "viewConfig", label = "视图配置"), @Column(includeEntity = DataEntity.class), + @Column(includeEntity = Extend.class, attrName = "extend"), + }, joinTable = { + @JoinTable(entity = Site.class, alias = "s", + on = "s.site_code = a.site_code", columns = { + @Column(name = "site_name"), + }) + }, orderBy = "a.tree_sorts, a.category_code" +) +public class Category extends TreeEntity { + + public static final String DEFAULT_TEMPLATE = "list"; // 默认文章列表模板 + + public static final String SHOW_MODES_AUTO = "1"; // 默认展现方式 + public static final String SHOW_MODES_CENTENT_LIST = "2"; // 首栏目内容列表 + public static final String SHOW_MODES_FIRST_CONTENT = "3"; // 简介类栏目,栏目第一条内容 + + private static final long serialVersionUID = 1L; + private String categoryCode; // 栏目编码 + private String categoryName; // 栏目名称 + private Site site; // 归属站点 + private String moduleType; // 模块类型 + private String image; // 栏目图片 + private String href; // 链接 + private String target; // 目标 + private String keywords; // 关键字 + private String description; // 描述 + private String inMenu; // 是否在导航中显示 + private String inList; // 是否在分类页中显示列表 + private String showModes; // 展现模式 + private String isNeedAudit; // 是否需要审核 + private String isCanComment; // 是否允许评论 + private String customListView; // 自定义列表视图 + private String customContentView; // 自定义内容视图 + private String viewConfig; // 视图配置 + private Extend extend; // 扩展字段 + + private List sortGradeList = ListUtils.newArrayList(); // 根据树的层级级别查询栏目列表 + private List categoryCodeList = ListUtils.newArrayList(); // 根据分类栏目编号查询栏目列表 + private List roleCodeList = ListUtils.newArrayList(); // 根据角色查询有权限的栏目列表 + + public Category() { + this(null); + } + + public Category(String id) { + super(id); + } + + public Category(String id, Site site) { + super(id); + this.setSite(site); + } + + @Override + public Category getParent() { + return parent; + } + + @Override + public void setParent(Category parent) { + this.parent = parent; + } + + public String getCategoryCode() { + return categoryCode; + } + + public void setCategoryCode(String categoryCode) { + this.categoryCode = categoryCode; + } + + @NotBlank(message = "栏目名称不能为空") + @Length(min = 0, max = 100, message = "栏目名称长度不能超过 100 个字符") + public String getCategoryName() { + return categoryName; + } + + public void setCategoryName(String categoryName) { + this.categoryName = categoryName; + } + + public Site getSite() { + if (site == null) { + site = new Site(); + } + return site; + } + + public void setSite(Site site) { + this.site = site; + } + + @Length(min = 0, max = 50, message = "模块类型长度不能超过 50 个字符") + public String getModuleType() { + return moduleType; + } + + public void setModuleType(String moduleType) { + this.moduleType = moduleType; + } + + @Length(min = 0, max = 255, message = "栏目图片长度不能超过 255 个字符") + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } + + @Length(min = 0, max = 255, message = "链接长度不能超过 255 个字符") + public String getHref() { + return href; + } + + public void setHref(String href) { + this.href = href; + } + + @Length(min = 0, max = 20, message = "目标长度不能超过 20 个字符") + public String getTarget() { + return target; + } + + public void setTarget(String target) { + this.target = target; + } + + @Length(min = 0, max = 500, message = "关键字长度不能超过 500 个字符") + public String getKeywords() { + return keywords; + } + + public void setKeywords(String keywords) { + this.keywords = keywords; + } + + @Length(min = 0, max = 500, message = "描述长度不能超过 500 个字符") + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + @Length(min = 0, max = 1, message = "是否在导航中显示长度不能超过 1 个字符") + public String getInMenu() { + return inMenu; + } + + public void setInMenu(String inMenu) { + this.inMenu = inMenu; + } + + @Length(min = 0, max = 1, message = "是否在分类页中显示列表长度不能超过 1 个字符") + public String getInList() { + return inList; + } + + public void setInList(String inList) { + this.inList = inList; + } + + @Length(min = 0, max = 1, message = "展现模式长度不能超过 1 个字符") + public String getShowModes() { + return showModes; + } + + public void setShowModes(String showModes) { + this.showModes = showModes; + } + + @Length(min = 0, max = 1, message = "是否需要审核长度不能超过 1 个字符") + public String getIsNeedAudit() { + return isNeedAudit; + } + + public void setIsNeedAudit(String isNeedAudit) { + this.isNeedAudit = isNeedAudit; + } + + @Length(min = 0, max = 1, message = "是否允许评论长度不能超过 1 个字符") + public String getIsCanComment() { + return isCanComment; + } + + public void setIsCanComment(String isCanComment) { + this.isCanComment = isCanComment; + } + + @Length(min = 0, max = 255, message = "自定义列表视图长度不能超过 255 个字符") + public String getCustomListView() { + return customListView; + } + + public void setCustomListView(String customListView) { + this.customListView = customListView; + } + + @Length(min = 0, max = 255, message = "自定义内容视图长度不能超过 255 个字符") + public String getCustomContentView() { + return customContentView; + } + + public void setCustomContentView(String customContentView) { + this.customContentView = customContentView; + } + + @Length(min = 0, max = 1000, message = "视图配置长度不能超过 1000 个字符") + public String getViewConfig() { + return viewConfig; + } + + public void setViewConfig(String viewConfig) { + this.viewConfig = viewConfig; + } + + public Extend getExtend() { + return extend; + } + + public void setExtend(Extend extend) { + this.extend = extend; + } + + public List getSortGradeList() { + return sortGradeList; + } + + public void setSortGradeList(List sortGradeList) { + this.sortGradeList = sortGradeList; + } + + public List getCategoryCodeList() { + return categoryCodeList; + } + + public void setCategoryCodeList(List categoryCodeList) { + this.categoryCodeList = categoryCodeList; + } + + public List getRoleCodeList() { + return roleCodeList; + } + + public void setRoleCodeList(List roleCodeList) { + this.roleCodeList = roleCodeList; + } + + public String getUrl() { + return CmsUtils.getUrlDynamic(this); + } + + public String getAdminUrl() { + return CmsUtils.getAdminUrlDynamic(this); + } + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/entity/CategoryRole.java b/modules/cms/src/main/java/com/jeesite/modules/cms/entity/CategoryRole.java new file mode 100644 index 00000000..ce6c744e --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/entity/CategoryRole.java @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.entity; + +import org.hibernate.validator.constraints.Length; + +import com.jeesite.common.entity.DataEntity; +import com.jeesite.common.mybatis.annotation.Column; +import com.jeesite.common.mybatis.annotation.Table; + +/** + * 栏目与角色关联表Entity + * @author 长春叭哥、ThinkGem + * @version 2018-10-15 + */ +@Table(name = "${_prefix}cms_category_role", alias = "a", columns = { + @Column(name = "category_code", attrName = "categoryCode", label = "栏目编码", isPK = true), + @Column(name = "role_code", attrName = "roleCode", label = "角色编码", isPK = true), + @Column(name = "ctrl_type", attrName = "ctrlType", label = "控制类型", comment = "控制类型(view查看、edit编辑)"), + }, orderBy = "a.category_code DESC, a.role_code DESC" +) +public class CategoryRole extends DataEntity { + + private static final long serialVersionUID = 1L; + private String categoryCode; // 栏目编码 + private String roleCode; // 角色编码 + private String ctrlType; // 控制类型(view查看、edit编辑) + + public CategoryRole() { + + } + + public CategoryRole(String categoryCode, String roleCode) { + this.categoryCode = categoryCode; + this.roleCode = roleCode; + } + + public String getCategoryCode() { + return categoryCode; + } + + public void setCategoryCode(String categoryCode) { + this.categoryCode = categoryCode; + } + + public String getRoleCode() { + return roleCode; + } + + public void setRoleCode(String roleCode) { + this.roleCode = roleCode; + } + + @Length(min = 0, max = 32, message = "控制类型长度不能超过 32 个字符") + public String getCtrlType() { + return ctrlType; + } + + public void setCtrlType(String ctrlType) { + this.ctrlType = ctrlType; + } + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/entity/Comment.java b/modules/cms/src/main/java/com/jeesite/modules/cms/entity/Comment.java new file mode 100644 index 00000000..79cc9001 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/entity/Comment.java @@ -0,0 +1,189 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.entity; + +import java.util.Date; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import org.hibernate.validator.constraints.Length; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.jeesite.common.entity.BaseEntity; +import com.jeesite.common.entity.DataEntity; +import com.jeesite.common.mybatis.annotation.Column; +import com.jeesite.common.mybatis.annotation.Table; +import com.jeesite.common.mybatis.mapper.query.QueryType; + +/** + * 文章评论表Entity + * @author 长春叭哥、ThinkGem + * @version 2018-10-15 + */ +@Table(name="${_prefix}cms_comment", alias="a", columns={ + @Column(name="id", attrName="id", label="编号", isPK=true), + @Column(name="category_code", attrName="categoryCode", label="栏目编码"), + @Column(name="article_id", attrName="articleId", label="内容编号"), + @Column(name="parent_id", attrName="parentId", label="父级评论"), + @Column(name="article_title", attrName="articleTitle", label="内容标题", queryType=QueryType.LIKE), + @Column(name="content", attrName="content", label="评论内容"), + @Column(name="name", attrName="name", label="评论姓名", queryType=QueryType.LIKE), + @Column(name="ip", attrName="ip", label="评论IP"), + @Column(includeEntity=DataEntity.class), + @Column(name="audit_user_code", attrName="auditUserCode", label="审核人"), + @Column(name="audit_date", attrName="auditDate", label="审核时间"), + @Column(name="audit_comment", attrName="auditComment", label="审核意见"), + @Column(name="hits_plus", attrName="hitsPlus", label="支持数"), + @Column(name="hits_minus", attrName="hitsMinus", label="反对数"), + @Column(includeEntity=BaseEntity.class), + }, orderBy="a.id DESC" +) +public class Comment extends DataEntity { + + private static final long serialVersionUID = 1L; + + private Category category;// 分类编号 + + private String categoryCode; // 栏目编码 + private String articleId; // 内容编号 (Article.id、Photo.id、Download.id) + private String parentId; // 父级评论 + private String articleTitle; // 内容标题(Article.title、Photo.title、Download.title) + private String content; // 评论内容 + private String name; // 评论姓名 + private String ip; // 评论IP + private String auditUserCode; // 审核人 + private Date auditDate; // 审核时间 + private String auditComment; // 审核意见 + private Integer hitsPlus; // 支持数 + private Integer hitsMinus; // 反对数 + + public Comment() { + this(null); + } + + public Comment(String id){ + super(id); + } + + @NotNull + public Category getCategory() { + return category; + } + + public void setCategory(Category category) { + this.category = category; + } + + @NotBlank(message="栏目编码不能为空") + @Length(min=0, max=64, message="栏目编码长度不能超过 64 个字符") + public String getCategoryCode() { + return categoryCode; + } + + public void setCategoryCode(String categoryCode) { + this.categoryCode = categoryCode; + } + + @NotBlank(message="内容编号不能为空") + @Length(min=0, max=64, message="内容编号长度不能超过 64 个字符") + public String getArticleId() { + return articleId; + } + + public void setArticleId(String articleId) { + this.articleId = articleId; + } + + @Length(min=0, max=64, message="父级评论长度不能超过 64 个字符") + public String getParentId() { + return parentId; + } + + public void setParentId(String parentId) { + this.parentId = parentId; + } + + @NotBlank(message="内容标题不能为空") + @Length(min=0, max=255, message="内容标题长度不能超过 255 个字符") + public String getArticleTitle() { + return articleTitle; + } + + public void setArticleTitle(String articleTitle) { + this.articleTitle = articleTitle; + } + + @NotBlank(message="评论内容不能为空") + @Length(min=0, max=255, message="评论内容长度不能超过 255 个字符") + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + @Length(min=0, max=50, message="评论姓名长度不能超过 50 个字符") + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Length(min=0, max=100, message="评论IP长度不能超过 100 个字符") + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + @Length(min=0, max=64, message="审核人长度不能超过 64 个字符") + public String getAuditUserCode() { + return auditUserCode; + } + + public void setAuditUserCode(String auditUserCode) { + this.auditUserCode = auditUserCode; + } + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + public Date getAuditDate() { + return auditDate; + } + + public void setAuditDate(Date auditDate) { + this.auditDate = auditDate; + } + + @Length(min=0, max=200, message="审核意见长度不能超过 200 个字符") + public String getAuditComment() { + return auditComment; + } + + public void setAuditComment(String auditComment) { + this.auditComment = auditComment; + } + + public Integer getHitsPlus() { + return hitsPlus; + } + + public void setHitsPlus(Integer hitsPlus) { + this.hitsPlus = hitsPlus; + } + + public Integer getHitsMinus() { + return hitsMinus; + } + + public void setHitsMinus(Integer hitsMinus) { + this.hitsMinus = hitsMinus; + } + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/entity/FileTemplete.java b/modules/cms/src/main/java/com/jeesite/modules/cms/entity/FileTemplete.java new file mode 100644 index 00000000..bc06175d --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/entity/FileTemplete.java @@ -0,0 +1,148 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.entity; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Serializable; +import java.util.Objects; + +import org.springframework.core.io.Resource; + +import com.jeesite.common.io.FileUtils; +import com.jeesite.common.io.IOUtils; +import com.jeesite.common.lang.ExceptionUtils; + +/** + * CMS模块-模版文件实体 + * @author 长春叭哥、ThinkGem + * @version 2020-7-7 + */ +public class FileTemplete implements Comparable, Serializable { + + private static final long serialVersionUID = 1L; + private Resource resource; + private String fileName; + private String fileExtension; + private String filePath; + private boolean isDirectory; + + public FileTemplete(Resource resource, String path) { + this.resource = resource; + this.fileName = resource.getFilename(); + this.fileExtension = FileUtils.getFileExtension(this.fileName); + try { + String filePath = resource.getURI().toString(); + int beginIndex = 0; + if (path != null) { + beginIndex = filePath.indexOf(path); + } + int endIndex = filePath.length(); + if (this.fileName.contains(".")){ + endIndex = filePath.lastIndexOf('/'); + }else if (filePath.endsWith("/")) { + endIndex -= 1; + } + this.filePath = filePath.substring(beginIndex, endIndex); +// System.out.println(this.filePath); + } catch (IOException e) { + throw ExceptionUtils.unchecked(e); + } + this.isDirectory = !this.fileName.contains("."); +// System.out.println(filePath); +// System.out.println(fileName); + } + + public FileTemplete(FileTemplete source) { + int index = source.filePath.lastIndexOf('/'); + this.fileName = source.filePath.substring(index+1); + this.filePath = source.filePath.substring(0, index); + this.fileExtension = null; + this.isDirectory = true; + this.resource = null; + } + + public Resource getResource() { + return resource; + } + + public void setResource(Resource resource) { + this.resource = resource; + } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public String getFileExtension() { + return fileExtension; + } + + public void setFileExtension(String fileExtension) { + this.fileExtension = fileExtension; + } + + public String getFilePath() { + return filePath; + } + + public void setFilePath(String filePath) { + this.filePath = filePath; + } + + public boolean isDirectory() { + return isDirectory; + } + + public void setDirectory(boolean isDirectory) { + this.isDirectory = isDirectory; + } + + /** + * 文件的内容 + */ + public String getFileContent() { + if (resource == null) { + return null; + } + try(InputStream is = resource.getInputStream()){ + return IOUtils.toString(is, "UTF-8"); + }catch (IOException e) { + throw ExceptionUtils.unchecked(e); + } + } + + @Override + public int compareTo(FileTemplete o) { + return this.getFileName().compareTo(o.getFileName()); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + FileTemplete e = (FileTemplete) o; + return Objects.equals(this.fileName, e.fileName) + && Objects.equals(this.fileExtension, e.fileExtension) + && Objects.equals(this.filePath, e.filePath) + && Objects.equals(this.isDirectory, e.isDirectory); + } + + @Override + public int hashCode() { + return Objects.hash(this.fileName, + this.fileExtension, + this.filePath, + this.isDirectory); + } + +} diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/entity/Report.java b/modules/cms/src/main/java/com/jeesite/modules/cms/entity/Report.java new file mode 100644 index 00000000..32a4129c --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/entity/Report.java @@ -0,0 +1,88 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.entity; + +import org.hibernate.validator.constraints.Length; + +import com.jeesite.common.entity.DataEntity; +import com.jeesite.common.mybatis.annotation.Column; +import com.jeesite.common.mybatis.annotation.Table; + +/** + * 内容举报表Entity + * @author 长春叭哥、ThinkGem + * @version 2018-10-15 + */ +@Table(name="${_prefix}cms_report", alias="a", columns={ + @Column(name="id", attrName="id", label="编号", isPK=true), + @Column(name="report_source", attrName="reportSource", label="举报来源", comment="举报来源(1文章、2评论)"), + @Column(name="report_content", attrName="reportContent", label="举报内容", comment="举报内容(文章标题 评论内容)"), + @Column(name="report_url", attrName="reportUrl", label="举报的URL"), + @Column(name="report_type", attrName="reportType", label="举报类型", comment="举报类型(色情 政治...)"), + @Column(name="report_cause", attrName="reportCause", label="举报原因"), + }, orderBy="a.id DESC" +) +public class Report extends DataEntity { + + private static final long serialVersionUID = 1L; + private String reportSource; // 举报来源(1文章、2评论) + private String reportContent; // 举报内容(文章标题 评论内容) + private String reportUrl; // 举报的URL + private String reportType; // 举报类型(色情 政治...) + private String reportCause; // 举报原因 + + public Report() { + this(null); + } + + public Report(String id){ + super(id); + } + + @Length(min=0, max=1, message="举报来源长度不能超过 1 个字符") + public String getReportSource() { + return reportSource; + } + + public void setReportSource(String reportSource) { + this.reportSource = reportSource; + } + + @Length(min=0, max=500, message="举报内容长度不能超过 500 个字符") + public String getReportContent() { + return reportContent; + } + + public void setReportContent(String reportContent) { + this.reportContent = reportContent; + } + + @Length(min=0, max=1000, message="举报的URL长度不能超过 1000 个字符") + public String getReportUrl() { + return reportUrl; + } + + public void setReportUrl(String reportUrl) { + this.reportUrl = reportUrl; + } + + @Length(min=0, max=1, message="举报类型长度不能超过 1 个字符") + public String getReportType() { + return reportType; + } + + public void setReportType(String reportType) { + this.reportType = reportType; + } + + @Length(min=0, max=500, message="举报原因长度不能超过 500 个字符") + public String getReportCause() { + return reportCause; + } + + public void setReportCause(String reportCause) { + this.reportCause = reportCause; + } + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/entity/Site.java b/modules/cms/src/main/java/com/jeesite/modules/cms/entity/Site.java new file mode 100644 index 00000000..fcf31ac5 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/entity/Site.java @@ -0,0 +1,247 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.entity; + +import java.util.List; + +import javax.validation.constraints.NotBlank; +import org.hibernate.validator.constraints.Length; + +import com.jeesite.common.config.Global; +import com.jeesite.common.entity.DataEntity; +import com.jeesite.common.lang.StringUtils; +import com.jeesite.common.mybatis.annotation.Column; +import com.jeesite.common.mybatis.annotation.Table; +import com.jeesite.common.mybatis.mapper.query.QueryType; +import com.jeesite.modules.sys.utils.CorpUtils; +import com.jeesite.modules.sys.utils.UserUtils; + +/** + * 站点表Entity + * @author 长春叭哥、ThinkGem + * @version 2018-10-15 + */ +@Table(name = "${_prefix}cms_site", alias = "a", columns = { + @Column(name = "site_code", attrName = "siteCode", label = "站点编码", isPK = true), + @Column(name = "site_name", attrName = "siteName", label = "站点名称", queryType = QueryType.LIKE), + @Column(name = "site_sort", attrName = "siteSort", label = "站点排序号"), + @Column(name = "title", attrName = "title", label = "站点标题", queryType = QueryType.LIKE), + @Column(name = "logo", attrName = "logo", label = "站点Logo"), + @Column(name = "domain", attrName = "domain", label = "站点域名"), + @Column(name = "keywords", attrName = "keywords", label = "关键字"), + @Column(name = "description", attrName = "description", label = "描述"), + @Column(name = "theme", attrName = "theme", label = "主题"), + @Column(name = "copyright", attrName = "copyright", label = "版权信息"), + @Column(name = "custom_index_view", attrName = "customIndexView", label = "自定义站点首页视图"), + @Column(includeEntity = DataEntity.class), + }, orderBy = "a.site_sort, a.update_date DESC" +) +public class Site extends DataEntity { + + /** + * 获取默认站点编码 + */ + public static final String MAIN_SITE_CODE = Global.getProperty("cms.mainSiteCode", "main"); + /** + * 模板路径 + */ + public static final String TEMPLETE_BASE_DIRECTION = "views/modules/cmsfront/themes"; + /** + * 默认模版 + */ + public static final String DEFAULT_TEMPLATE = "index"; + + private static final long serialVersionUID = 1L; + private String siteCode; // 站点编码 + private String siteName; // 站点名称 + private Integer siteSort; // 站点排序号 + private String title; // 站点标题 + private String logo; // 站点Logo + private String domain; // 站点域名 + private String keywords; // 关键字 + private String description; // 描述 + private String theme; // 主题 + private String copyright; // 版权信息 + private String customIndexView; // 自定义站点首页视图 + + private List categoryCodes; //某角色下某站点下授权的栏目id集合 + private List categoryList; //某站点下所有栏目集合 + + public Site() { + this(null); + } + + public Site(String id) { + super(id); + } + + public String getSiteCode() { + return siteCode; + } + + public void setSiteCode(String siteCode) { + this.siteCode = siteCode; + } + + @NotBlank(message = "站点名称不能为空") + @Length(min = 0, max = 100, message = "站点名称长度不能超过 100 个字符") + public String getSiteName() { + return siteName; + } + + public void setSiteName(String siteName) { + this.siteName = siteName; + } + + public Integer getSiteSort() { + return siteSort; + } + + public void setSiteSort(Integer siteSort) { + this.siteSort = siteSort; + } + + @NotBlank(message = "站点标题不能为空") + @Length(min = 0, max = 100, message = "站点标题长度不能超过 100 个字符") + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + @Length(min = 0, max = 1000, message = "站点Logo长度不能超过 1000 个字符") + public String getLogo() { + return logo; + } + + public void setLogo(String logo) { + this.logo = logo; + } + + @Length(min = 0, max = 500, message = "站点域名长度不能超过 500 个字符") + public String getDomain() { + return domain; + } + + public void setDomain(String domain) { + this.domain = domain; + } + + @Length(min = 0, max = 500, message = "关键字长度不能超过 500 个字符") + public String getKeywords() { + return keywords; + } + + public void setKeywords(String keywords) { + this.keywords = keywords; + } + + @Length(min = 0, max = 500, message = "描述长度不能超过 500 个字符") + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + @Length(min = 0, max = 500, message = "主题长度不能超过 500 个字符") + public String getTheme() { + return theme; + } + + public void setTheme(String theme) { + this.theme = theme; + } + + @Length(min = 0, max = 1000, message = "版权信息长度不能超过 1000 个字符") + public String getCopyright() { + return copyright; + } + + public void setCopyright(String copyright) { + this.copyright = copyright; + } + + @Length(min = 0, max = 500, message = "自定义站点首页视图长度不能超过 500 个字符") + public String getCustomIndexView() { + return customIndexView; + } + + public void setCustomIndexView(String customIndexView) { + this.customIndexView = customIndexView; + } + + /** + * 获取当前编辑的站点编号 + */ + public static String getCurrentSiteCode() { + String siteCode = (String) UserUtils.getCache("currentSiteCode"); + String defaultSiteCode = MAIN_SITE_CODE; + return StringUtils.isNotBlank(siteCode) ? siteCode : defaultSiteCode; + } + + /** + * 获得模板方案路径。如:/WEB-INF/views/modules/cmsfront/themes/jeesite + * @return + */ + public String getSolutionPath() { + return TEMPLETE_BASE_DIRECTION + "/" + getTheme(); + } + + public List getCategoryCodes() { + return categoryCodes; + } + + public void setCategoryCodes(List categoryCodes) { + this.categoryCodes = categoryCodes; + } + + public List getCategoryList() { + return categoryList; + } + + public void setCategoryList(List categoryList) { + this.categoryList = categoryList; + } + + + + + /** + * 判断是否为当前站点 + */ + public Boolean getIsCurrentSite(){ + return getCurrentSiteCode().equals(siteCode); + } + + /** + * 判断是否为默认(主站)站点 + */ + public static boolean isMainSite(String siteCode){ + if (siteCode != null){ + String code = siteCode; + if (Global.isUseCorpModel()){ + String corpCode = CorpUtils.getCurrentCorpCode(); + if (code.startsWith(corpCode + "_")){ + code = code.replaceFirst(corpCode + "_", ""); + } + } + return MAIN_SITE_CODE.equals(code); + } + return false; + } + + + + + + + + + + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/entity/Tag.java b/modules/cms/src/main/java/com/jeesite/modules/cms/entity/Tag.java new file mode 100644 index 00000000..faa0fd91 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/entity/Tag.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.entity; + +import javax.validation.constraints.NotNull; + +import com.jeesite.common.entity.DataEntity; +import com.jeesite.common.mybatis.annotation.Column; +import com.jeesite.common.mybatis.annotation.Table; + +/** + * 内容标签Entity + * @author 长春叭哥、ThinkGem + * @version 2018-10-15 + */ +@Table(name="${_prefix}cms_tag", alias="a", columns={ + @Column(name="tag_name", attrName="tagName", label="标签名称", isPK=true), + @Column(name="clicknum", attrName="clicknum", label="点击次数"), + }, orderBy="a.tag_name DESC" +) +public class Tag extends DataEntity { + + private static final long serialVersionUID = 1L; + private String tagName; // 标签名称 + private Integer clicknum; // 点击次数 + + public Tag() { + this(null); + } + + public Tag(String id){ + super(id); + } + + public String getTagName() { + return tagName; + } + + public void setTagName(String tagName) { + this.tagName = tagName; + } + + @NotNull(message="点击次数不能为空") + public Integer getClicknum() { + return clicknum; + } + + public void setClicknum(Integer clicknum) { + this.clicknum = clicknum; + } + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/entity/VisitLog.java b/modules/cms/src/main/java/com/jeesite/modules/cms/entity/VisitLog.java new file mode 100644 index 00000000..f215a8ff --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/entity/VisitLog.java @@ -0,0 +1,366 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.entity; + +import java.util.Date; + +import org.hibernate.validator.constraints.Length; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.jeesite.common.entity.BaseEntity; +import com.jeesite.common.entity.DataEntity; +import com.jeesite.common.mybatis.annotation.Column; +import com.jeesite.common.mybatis.annotation.Table; +import com.jeesite.common.mybatis.mapper.query.QueryType; + +/** + * 访问日志表Entity + * @author 长春叭哥、ThinkGem + * @version 2018-10-15 + */ +@Table(name="${_prefix}cms_visit_log", alias="a", columns={ + @Column(name="id", attrName="id", label="编号", isPK=true), + @Column(name="request_url", attrName="requestUrl", label="请求的URL地址"), + @Column(name="request_url_host", attrName="requestUrlHost", label="受访域名"), + @Column(name="source_referer", attrName="sourceReferer", label="来源页面/上一个页面"), + @Column(name="source_referer_host", attrName="sourceRefererHost", label="来源域名"), + @Column(name="source_type", attrName="sourceType", label="访问来源类型", comment="访问来源类型(1直接访问 2搜索引擎 3外部链接 4内部访问)"), + @Column(name="search_engine", attrName="searchEngine", label="使用的搜索引擎"), + @Column(name="search_word", attrName="searchWord", label="搜索的关键词"), + @Column(name="remote_addr", attrName="remoteAddr", label="客户IP地址"), + @Column(name="user_agent", attrName="userAgent", label="用户代理字符串"), + @Column(name="user_language", attrName="userLanguage", label="客户机语言"), + @Column(name="user_screen_size", attrName="userScreenSize", label="客户机屏幕大小0x0"), + @Column(name="user_device", attrName="userDevice", label="客户机设备类型", comment="客户机设备类型(电脑、平板、手机、未知)"), + @Column(name="user_os_name", attrName="userOsName", label="客户机操作系统", queryType=QueryType.LIKE), + @Column(name="user_browser", attrName="userBrowser", label="客户机浏览器"), + @Column(name="user_browser_version", attrName="userBrowserVersion", label="浏览器版本"), + @Column(name="unique_visit_id", attrName="uniqueVisitId", label="唯一访问标识"), + @Column(name="visit_date", attrName="visitDate", label="本次访问日期", comment="本次访问日期(年月日)"), + @Column(name="visit_time", attrName="visitTime", label="本次访问时间"), + @Column(name="is_new_visit", attrName="isNewVisit", label="是否新访问", comment="是否新访问(30分内)"), + @Column(name="first_visit_time", attrName="firstVisitTime", label="首次访问时间戳", comment="首次访问时间戳(30分钟内)"), + @Column(name="prev_remain_time", attrName="prevRemainTime", label="上页面停留时间", comment="上页面停留时间(秒)"), + @Column(name="total_remain_time", attrName="totalRemainTime", label="本次访问总停留时间", comment="本次访问总停留时间(秒)"), + @Column(name="site_code", attrName="siteCode", label="站点编码"), + @Column(name="site_name", attrName="siteName", label="站点名称", queryType=QueryType.LIKE), + @Column(name="category_code", attrName="categoryCode", label="栏目编码"), + @Column(name="category_name", attrName="categoryName", label="栏目名称", queryType=QueryType.LIKE), + @Column(name="content_id", attrName="contentId", label="栏目内容编号"), + @Column(name="content_title", attrName="contentTitle", label="访问页面标题", queryType=QueryType.LIKE), + @Column(name="visit_user_code", attrName="visitUserCode", label="访问用户编码"), + @Column(name="visit_user_name", attrName="visitUserName", label="访问用户姓名", queryType=QueryType.LIKE), + @Column(includeEntity=BaseEntity.class), + }, orderBy="a.id DESC" +) +public class VisitLog extends DataEntity { + + private static final long serialVersionUID = 1L; + private String requestUrl; // 请求的URL地址 + private String requestUrlHost; // 受访域名 + private String sourceReferer; // 来源页面/上一个页面 + private String sourceRefererHost; // 来源域名 + private String sourceType; // 访问来源类型(1直接访问 2搜索引擎 3外部链接 4内部访问) + private String searchEngine; // 使用的搜索引擎 + private String searchWord; // 搜索的关键词 + private String remoteAddr; // 客户IP地址 + private String userAgent; // 用户代理字符串 + private String userLanguage; // 客户机语言 + private String userScreenSize; // 客户机屏幕大小0x0 + private String userDevice; // 客户机设备类型(电脑、平板、手机、未知) + private String userOsName; // 客户机操作系统 + private String userBrowser; // 客户机浏览器 + private String userBrowserVersion; // 浏览器版本 + private String uniqueVisitId; // 唯一访问标识 + private String visitDate; // 本次访问日期(年月日) + private Date visitTime; // 本次访问时间 + private String isNewVisit; // 是否新访问(30分内) + private Long firstVisitTime; // 首次访问时间戳(30分钟内) + private Long prevRemainTime; // 上页面停留时间(秒) + private Long totalRemainTime; // 本次访问总停留时间(秒) + private String siteCode; // 站点编码 + private String siteName; // 站点名称 + private String categoryCode; // 栏目编码 + private String categoryName; // 栏目名称 + private String contentId; // 栏目内容编号 + private String contentTitle; // 访问页面标题 + private String visitUserCode; // 访问用户编码 + private String visitUserName; // 访问用户姓名 + + public VisitLog() { + this(null); + } + + public VisitLog(String id){ + super(id); + } + + @Length(min=0, max=1000, message="请求的URL地址长度不能超过 1000 个字符") + public String getRequestUrl() { + return requestUrl; + } + + public void setRequestUrl(String requestUrl) { + this.requestUrl = requestUrl; + } + + @Length(min=0, max=128, message="受访域名长度不能超过 128 个字符") + public String getRequestUrlHost() { + return requestUrlHost; + } + + public void setRequestUrlHost(String requestUrlHost) { + this.requestUrlHost = requestUrlHost; + } + + @Length(min=0, max=1000, message="来源页面/上一个页面长度不能超过 1000 个字符") + public String getSourceReferer() { + return sourceReferer; + } + + public void setSourceReferer(String sourceReferer) { + this.sourceReferer = sourceReferer; + } + + @Length(min=0, max=128, message="来源域名长度不能超过 128 个字符") + public String getSourceRefererHost() { + return sourceRefererHost; + } + + public void setSourceRefererHost(String sourceRefererHost) { + this.sourceRefererHost = sourceRefererHost; + } + + @Length(min=0, max=1, message="访问来源类型长度不能超过 1 个字符") + public String getSourceType() { + return sourceType; + } + + public void setSourceType(String sourceType) { + this.sourceType = sourceType; + } + + @Length(min=0, max=200, message="使用的搜索引擎长度不能超过 200 个字符") + public String getSearchEngine() { + return searchEngine; + } + + public void setSearchEngine(String searchEngine) { + this.searchEngine = searchEngine; + } + + @Length(min=0, max=200, message="搜索的关键词长度不能超过 200 个字符") + public String getSearchWord() { + return searchWord; + } + + public void setSearchWord(String searchWord) { + this.searchWord = searchWord; + } + + @Length(min=0, max=50, message="客户IP地址长度不能超过 50 个字符") + public String getRemoteAddr() { + return remoteAddr; + } + + public void setRemoteAddr(String remoteAddr) { + this.remoteAddr = remoteAddr; + } + + @Length(min=0, max=500, message="用户代理字符串长度不能超过 500 个字符") + public String getUserAgent() { + return userAgent; + } + + public void setUserAgent(String userAgent) { + this.userAgent = userAgent; + } + + @Length(min=0, max=32, message="客户机语言长度不能超过 32 个字符") + public String getUserLanguage() { + return userLanguage; + } + + public void setUserLanguage(String userLanguage) { + this.userLanguage = userLanguage; + } + + @Length(min=0, max=32, message="客户机屏幕大小0x0长度不能超过 32 个字符") + public String getUserScreenSize() { + return userScreenSize; + } + + public void setUserScreenSize(String userScreenSize) { + this.userScreenSize = userScreenSize; + } + + @Length(min=0, max=32, message="客户机设备类型长度不能超过 32 个字符") + public String getUserDevice() { + return userDevice; + } + + public void setUserDevice(String userDevice) { + this.userDevice = userDevice; + } + + @Length(min=0, max=32, message="客户机操作系统长度不能超过 32 个字符") + public String getUserOsName() { + return userOsName; + } + + public void setUserOsName(String userOsName) { + this.userOsName = userOsName; + } + + @Length(min=0, max=32, message="客户机浏览器长度不能超过 32 个字符") + public String getUserBrowser() { + return userBrowser; + } + + public void setUserBrowser(String userBrowser) { + this.userBrowser = userBrowser; + } + + @Length(min=0, max=16, message="浏览器版本长度不能超过 16 个字符") + public String getUserBrowserVersion() { + return userBrowserVersion; + } + + public void setUserBrowserVersion(String userBrowserVersion) { + this.userBrowserVersion = userBrowserVersion; + } + + @Length(min=0, max=64, message="唯一访问标识长度不能超过 64 个字符") + public String getUniqueVisitId() { + return uniqueVisitId; + } + + public void setUniqueVisitId(String uniqueVisitId) { + this.uniqueVisitId = uniqueVisitId; + } + + @Length(min=0, max=8, message="本次访问日期长度不能超过 8 个字符") + public String getVisitDate() { + return visitDate; + } + + public void setVisitDate(String visitDate) { + this.visitDate = visitDate; + } + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + public Date getVisitTime() { + return visitTime; + } + + public void setVisitTime(Date visitTime) { + this.visitTime = visitTime; + } + + @Length(min=0, max=1, message="是否新访问长度不能超过 1 个字符") + public String getIsNewVisit() { + return isNewVisit; + } + + public void setIsNewVisit(String isNewVisit) { + this.isNewVisit = isNewVisit; + } + + public Long getFirstVisitTime() { + return firstVisitTime; + } + + public void setFirstVisitTime(Long firstVisitTime) { + this.firstVisitTime = firstVisitTime; + } + + public Long getPrevRemainTime() { + return prevRemainTime; + } + + public void setPrevRemainTime(Long prevRemainTime) { + this.prevRemainTime = prevRemainTime; + } + + public Long getTotalRemainTime() { + return totalRemainTime; + } + + public void setTotalRemainTime(Long totalRemainTime) { + this.totalRemainTime = totalRemainTime; + } + + @Length(min=0, max=64, message="站点编码长度不能超过 64 个字符") + public String getSiteCode() { + return siteCode; + } + + public void setSiteCode(String siteCode) { + this.siteCode = siteCode; + } + + @Length(min=0, max=100, message="站点名称长度不能超过 100 个字符") + public String getSiteName() { + return siteName; + } + + public void setSiteName(String siteName) { + this.siteName = siteName; + } + + @Length(min=0, max=64, message="栏目编码长度不能超过 64 个字符") + public String getCategoryCode() { + return categoryCode; + } + + public void setCategoryCode(String categoryCode) { + this.categoryCode = categoryCode; + } + + @Length(min=0, max=100, message="栏目名称长度不能超过 100 个字符") + public String getCategoryName() { + return categoryName; + } + + public void setCategoryName(String categoryName) { + this.categoryName = categoryName; + } + + @Length(min=0, max=64, message="栏目内容编号长度不能超过 64 个字符") + public String getContentId() { + return contentId; + } + + public void setContentId(String contentId) { + this.contentId = contentId; + } + + @Length(min=0, max=255, message="访问页面标题长度不能超过 255 个字符") + public String getContentTitle() { + return contentTitle; + } + + public void setContentTitle(String contentTitle) { + this.contentTitle = contentTitle; + } + + @Length(min=0, max=100, message="访问用户编码长度不能超过 100 个字符") + public String getVisitUserCode() { + return visitUserCode; + } + + public void setVisitUserCode(String visitUserCode) { + this.visitUserCode = visitUserCode; + } + + @Length(min=0, max=100, message="访问用户姓名长度不能超过 100 个字符") + public String getVisitUserName() { + return visitUserName; + } + + public void setVisitUserName(String visitUserName) { + this.visitUserName = visitUserName; + } + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/service/ArticleService.java b/modules/cms/src/main/java/com/jeesite/modules/cms/service/ArticleService.java new file mode 100644 index 00000000..d079f4de --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/service/ArticleService.java @@ -0,0 +1,208 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.service; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.jeesite.common.collect.ListUtils; +import com.jeesite.common.config.Global; +import com.jeesite.common.entity.Page; +import com.jeesite.common.lang.DateUtils; +import com.jeesite.common.lang.StringUtils; +import com.jeesite.common.service.CrudService; +import com.jeesite.modules.cms.dao.ArticleDao; +import com.jeesite.modules.cms.dao.ArticleDataDao; +import com.jeesite.modules.cms.entity.Article; +import com.jeesite.modules.cms.entity.ArticleData; +import com.jeesite.modules.cms.entity.Category; +import com.jeesite.modules.cms.utils.CmsUtils; +import com.jeesite.modules.file.utils.FileUploadUtils; +import com.jeesite.modules.sys.utils.UserUtils; + +/** + * 文章表Service + * @author 长春叭哥、ThinkGem + * @version 2020-7-24 + */ +@Service +@Transactional(readOnly = true) +public class ArticleService extends CrudService { + + @Autowired + private ArticleDataDao articleDataDao; + + /** + * 获取单条数据 + * @param article + * @return + */ + @Override + public Article get(Article article) { + Article entity = super.get(article); + if (entity != null && StringUtils.isNotBlank(article.getId())) { + entity.setArticleData(get(new ArticleData(article.getId()))); + } + return entity; + } + + /** + * 获取文章详情内容 + */ + public ArticleData get(ArticleData articleData) { + return articleDataDao.get(articleData); + } + + /** + * 添加数据权限 + */ + @Override + public void addDataScopeFilter(Article entity) { + + } + + /** + * 查询分页数据 + * @param article 查询条件 + * @param article.page 分页对象 + * @return + */ + @Override + public Page
findPage(Article article) { + Thread thread = new Thread("cms-update-expired-weight") { + @Override + public void run() { + updateExpiredWeight(article); + } + }; + thread.setDaemon(true); + thread.start(); + return super.findPage(article); + } + + /** + * 通过编号获取内容标题 + * @return new Object[]{栏目Id,内容Id,内容标题} + */ + public List findByIds(String ids) { + if (ids == null) { + return new ArrayList(); + } + List list = ListUtils.newArrayList(); + String[] idss = StringUtils.split(ids, ","); + Article where = new Article(); + where.setId_in(idss); + List
l = dao.findList(where); + for (Article e : l) { + list.add(new Object[] { e.getCategory().getId(), e.getId(), StringUtils.abbr(e.getTitle(), 50) }); + } + return list; + } + + /** + * 权重更新 + * @param article + * @author ThinkGem + */ + @Transactional(readOnly = false) + public void updateExpiredWeight(Article article) { + // 更新过期的权重,间隔为“6”个小时 + Date updateExpiredWeightDate = CmsUtils.getCache("updateExpiredWeightDateByArticle"); + if (updateExpiredWeightDate == null || (updateExpiredWeightDate != null + && updateExpiredWeightDate.getTime() < System.currentTimeMillis())) { + article.setWeightDate(new Date()); + dao.updateExpiredWeight(article); + CmsUtils.putCache("updateExpiredWeightDateByArticle", DateUtils.addHours(new Date(), 6)); + } + } + + /** + * 保存数据(插入或更新) + * @param article + */ + @Override + @Transactional(readOnly = false) + public void save(Article article) { + Global.assertDemoMode(); + // 设置内容状态 + if (article.getCategory() != null && StringUtils.isNotBlank(article.getCategory().getId())) { + Category category = CmsUtils.getCategory(article.getCategory().getId()); + // 如果栏目不需要审核,或者当前用户有审核权限,则将该内容设为发布状态 + if (Global.YES.equals(category.getIsNeedAudit()) + && !UserUtils.getSubject().isPermitted("cms:article:audit")) { + // 并且不是草稿状态 + if (!article.getStatus().equals(Article.STATUS_DRAFT)){ + article.setStatus(Article.STATUS_AUDIT); + } + } + // 将栏目信息设置到实体对象(全文检索需要) + article.setCategory(category); + } else { + throw new RuntimeException("归属栏目不能为空。"); + } + // 保存详细内容 + if (article.getIsNewRecord()) { + dao.insert(article); + article.getArticleData().setId(article.getId()); + articleDataDao.insert(article.getArticleData()); + } else { + dao.update(article); + article.getArticleData().setId(article.getId()); + articleDataDao.update(article.getArticleData()); + } + // 保存上传图片 + FileUploadUtils.saveFileUpload(article.getId(), "article_image"); +// // 保存上传附件 +// FileUploadUtils.saveFileUpload(article.getId(), "article_file"); + } + + /** + * 更新状态 + * @param article + */ + @Override + @Transactional(readOnly = false) + public void updateStatus(Article article) { + super.updateStatus(article); + } + + /** + * 获取文章获取文章并点击数加一 + */ + @Transactional(readOnly = false) + public void updateHitsAddOne(String id) { + dao.updateHitsAddOne(id); + } + + /** + * 删除数据 + * @param article + */ + @Override + @Transactional(readOnly = false) + public void delete(Article article) { + super.delete(article); + } + + /** + * 文章高级搜索 + * @param page 分页对象 + * @param qStr 搜索字符串 + * @param qand 包含的字符串 + * @param qnot 不包含的字符串 + * @param bd 开始日期 + * @param ed 结束日期 + */ + public Page> searchPage(Page> page, String qStr, + String qand, String qnot, String bd, String ed, Map params) { + return page; + } + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/service/CategoryService.java b/modules/cms/src/main/java/com/jeesite/modules/cms/service/CategoryService.java new file mode 100644 index 00000000..4234dbb1 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/service/CategoryService.java @@ -0,0 +1,102 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.service; + +import java.util.List; + +import org.apache.commons.text.StringEscapeUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.jeesite.common.lang.StringUtils; +import com.jeesite.common.service.TreeService; +import com.jeesite.modules.cms.dao.CategoryDao; +import com.jeesite.modules.cms.entity.Category; +import com.jeesite.modules.cms.utils.CmsUtils; +import com.jeesite.modules.file.utils.FileUploadUtils; + +/** + * 栏目表Service + * @author 长春叭哥、ThinkGem + * @version 2020-7-24 + */ +@Service +@Transactional(readOnly = true) +public class CategoryService extends TreeService { + + /** + * 获取单条数据 + * @param category + * @return + */ + @Override + public Category get(Category category) { + return super.get(category); + } + + /** + * 添加数据权限 + */ + @Override + public void addDataScopeFilter(Category entity) { + + } + + /** + * 查询列表数据 + * @param category + * @return + */ + @Override + public List findList(Category category) { + return super.findList(category); + } + + /** + * 保存数据(插入或更新) + * @param category + */ + @Override + @Transactional(readOnly = false) + public void save(Category category) { + if (StringUtils.isNotBlank(category.getViewConfig())){ + category.setViewConfig(StringEscapeUtils.unescapeHtml4(category.getViewConfig())); + } + super.save(category); + CmsUtils.removeCache("mainNavList_"+category.getSite().getId()); + // 保存上传图片 + FileUploadUtils.saveFileUpload(category.getId(), "category_image"); + } + + /** + * 更新子节点,并设置子节点[sysCode]与父类相同 + */ + @Override + protected void updateChildNode(Category childEntity, Category parentEntity) { + childEntity.setSite(parentEntity.getSite()); + childEntity.getSqlMap().updateTreeDataExtSql("site_code = #{site.siteCode}"); + super.updateChildNode(childEntity, parentEntity); + } + + /** + * 更新状态 + * @param category + */ + @Override + @Transactional(readOnly = false) + public void updateStatus(Category category) { + super.updateStatus(category); + } + + /** + * 删除数据 + * @param category + */ + @Override + @Transactional(readOnly = false) + public void delete(Category category) { + super.delete(category); + } + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/service/CommentService.java b/modules/cms/src/main/java/com/jeesite/modules/cms/service/CommentService.java new file mode 100644 index 00000000..576dede1 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/service/CommentService.java @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.service; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.jeesite.common.entity.Page; +import com.jeesite.common.service.CrudService; +import com.jeesite.modules.cms.dao.CommentDao; +import com.jeesite.modules.cms.entity.Comment; +import com.jeesite.modules.file.utils.FileUploadUtils; + +/** + * 文章评论表Service + * @author 长春叭哥、ThinkGem + * @version 2020-7-24 + */ +@Service +@Transactional(readOnly=true) +public class CommentService extends CrudService { + + /** + * 获取单条数据 + * @param comment + * @return + */ + @Override + public Comment get(Comment comment) { + return super.get(comment); + } + + /** + * 查询分页数据 + * @param comment 查询条件 + * @param comment.page 分页对象 + * @return + */ + @Override + public Page findPage(Comment comment) { + return super.findPage(comment); + } + + /** + * 保存数据(插入或更新) + * @param comment + */ + @Override + @Transactional(readOnly=false) + public void save(Comment comment) { + super.save(comment); + // 保存上传图片 + FileUploadUtils.saveFileUpload(comment.getId(), "comment_image"); + // 保存上传附件 + FileUploadUtils.saveFileUpload(comment.getId(), "comment_file"); + } + + /** + * 更新状态 + * @param comment + */ + @Override + @Transactional(readOnly=false) + public void updateStatus(Comment comment) { + super.updateStatus(comment); + } + + /** + * 删除数据 + * @param comment + */ + @Override + @Transactional(readOnly=false) + public void delete(Comment comment) { + super.delete(comment); + } + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/service/FileTempleteService.java b/modules/cms/src/main/java/com/jeesite/modules/cms/service/FileTempleteService.java new file mode 100644 index 00000000..dbc4e315 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/service/FileTempleteService.java @@ -0,0 +1,90 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.service; + +import java.io.IOException; +import java.util.List; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.beust.jcommander.internal.Lists; +import com.jeesite.modules.cms.entity.FileTemplete; +import com.jeesite.modules.cms.entity.Site; +import com.jeesite.modules.cms.utils.CmsUtils; +import com.jeesite.modules.cms.utils.FileTempleteUtils; +import com.jeesite.modules.sys.entity.DictData; + +/** + * 模版文件Service + * @author 长春叭哥、ThinkGem + * @version 2020-7-7 + */ +@Service +@Transactional(readOnly = true) +public class FileTempleteService { + +// public List getTempleteContent(String prefix) throws IOException { +// List tplList = getFileTempleteNameListByPrefix(CmsUtils.getSite(Site.getCurrentSiteCode()).getSolutionPath()); +// tplList = FilesTempleteUtils.templeteTrim(tplList, prefix, ""); +// return tplList; +// } + + /** + * 获取对应视图模板列表,兼容 Select 字典 + * @param prefix + */ + public List getTempleteContentDict(String prefix) throws IOException { + List listSite = Lists.newArrayList(); + String solutionPath = CmsUtils.getSite(Site.getCurrentSiteCode()).getSolutionPath(); + List tplList = FileTempleteUtils.getFileTempleteListByPath(solutionPath); + for (FileTemplete tpl : tplList) { + if (tpl.getFileName().startsWith(prefix)) { + listSite.add(new DictData(tpl.getFileName() + .substring(0, tpl.getFileName().indexOf(".")))); + } + } + return listSite; + } + +// /** +// * 通过前缀获取文件名集合 +// * @param filePath +// * @return List 文件名集合 +// * @author 长春叭哥 +// * @throws IOException +// */ +// public List getFileTempleteNameListByPrefix(String filePath) throws IOException { +// return FilesTempleteUtils.getFileTempleteNameListByPrefix(filePath); +// } + +// /** +// * 获取模版文件列表 +// * @param path 路径 +// * @param directory +// * @return List 模版文件集合 +// * @author 长春叭哥 +// * @throws IOException +// */ +// public List getFileTempleteListByPath(String path, boolean directory) throws IOException { +// return FilesTempleteUtils.getFileTempleteListByPath(path, directory); +// } + + /** + * 获取编辑文件列表 + * @param path 模板路径 + */ + public List getFileTempleteListForEdit(String path) throws IOException { + return FileTempleteUtils.getFileTempleteListForEdit(path); + } + + /** + * 获取模版文件内容 + * @param fileName 模板文件 + */ + public FileTemplete getFileTemplete(String fileName) throws IOException { + return FileTempleteUtils.getFileTempleteByResource(fileName); + } + +} diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/service/ReportService.java b/modules/cms/src/main/java/com/jeesite/modules/cms/service/ReportService.java new file mode 100644 index 00000000..d651d298 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/service/ReportService.java @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.service; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.jeesite.common.entity.Page; +import com.jeesite.common.service.CrudService; +import com.jeesite.modules.cms.entity.Report; +import com.jeesite.modules.cms.dao.ReportDao; +import com.jeesite.modules.file.utils.FileUploadUtils; + +/** + * 内容举报表Service + * @author 长春叭哥、ThinkGem + * @version 2020-7-24 + */ +@Service +@Transactional(readOnly=true) +public class ReportService extends CrudService { + + /** + * 获取单条数据 + * @param report + * @return + */ + @Override + public Report get(Report report) { + return super.get(report); + } + + /** + * 查询分页数据 + * @param report 查询条件 + * @param report.page 分页对象 + * @return + */ + @Override + public Page findPage(Report report) { + return super.findPage(report); + } + + /** + * 保存数据(插入或更新) + * @param report + */ + @Override + @Transactional(readOnly=false) + public void save(Report report) { + super.save(report); + // 保存上传图片 + FileUploadUtils.saveFileUpload(report.getId(), "report_image"); + // 保存上传附件 + FileUploadUtils.saveFileUpload(report.getId(), "report_file"); + } + + /** + * 更新状态 + * @param report + */ + @Override + @Transactional(readOnly=false) + public void updateStatus(Report report) { + super.updateStatus(report); + } + + /** + * 删除数据 + * @param report + */ + @Override + @Transactional(readOnly=false) + public void delete(Report report) { + super.delete(report); + } + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/service/SiteService.java b/modules/cms/src/main/java/com/jeesite/modules/cms/service/SiteService.java new file mode 100644 index 00000000..95b7009b --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/service/SiteService.java @@ -0,0 +1,91 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.service; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.jeesite.common.entity.Page; +import com.jeesite.common.service.CrudService; +import com.jeesite.modules.cms.dao.SiteDao; +import com.jeesite.modules.cms.entity.Site; +import com.jeesite.modules.cms.utils.CmsUtils; +import com.jeesite.modules.file.utils.FileUploadUtils; + +/** + * 站点表Service + * @author 长春叭哥、ThinkGem + * @version 2020-7-24 + */ +@Service +@Transactional(readOnly = true) +public class SiteService extends CrudService { + + /** + * 获取单条数据 + * @param site + * @return + */ + @Override + public Site get(Site site) { + return super.get(site); + } + + /** + * 查询分页数据 + * @param site 查询条件 + * @param site.page 分页对象 + * @return + */ + @Override + public Page findPage(Site site) { + return super.findPage(site); + } + + /** + * 保存数据(插入或更新) + * @param site + */ + @Override + @Transactional(readOnly = false) + public void save(Site site) { + super.save(site); + CmsUtils.removeCache("siteList"); + // 保存logo + FileUploadUtils.saveFileUpload(site.getId(), "site_logo"); + } + + /** + * 更新状态 + * @param site + */ + @Override + @Transactional(readOnly = false) + public void updateStatus(Site site) { + super.updateStatus(site); + } + + /** + * 删除数据 + * @param site + */ + @Override + @Transactional(readOnly = false) + public void delete(Site site) { + super.delete(site); + } + + /** + * 删除站点 + * @param site + * @param isRe + */ + @Transactional(readOnly = false) + public void delete(Site site, Boolean isRe) { + site.setStatus(isRe != null && isRe ? Site.STATUS_NORMAL : Site.STATUS_DELETE); + super.delete(site); + CmsUtils.removeCache("siteList"); + } + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/service/TagService.java b/modules/cms/src/main/java/com/jeesite/modules/cms/service/TagService.java new file mode 100644 index 00000000..b66bf863 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/service/TagService.java @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.service; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.jeesite.common.entity.Page; +import com.jeesite.common.service.CrudService; +import com.jeesite.modules.cms.dao.TagDao; +import com.jeesite.modules.cms.entity.Tag; + +/** + * 内容标签Service + * @author 长春叭哥、ThinkGem + * @version 2020-7-24 + */ +@Service +@Transactional(readOnly=true) +public class TagService extends CrudService { + + /** + * 获取单条数据 + * @param tag + * @return + */ + @Override + public Tag get(Tag tag) { + return super.get(tag); + } + + /** + * 查询分页数据 + * @param tag 查询条件 + * @param tag.page 分页对象 + * @return + */ + @Override + public Page findPage(Tag tag) { + return super.findPage(tag); + } + + /** + * 保存数据(插入或更新) + * @param tag + */ + @Override + @Transactional(readOnly=false) + public void save(Tag tag) { + super.save(tag); + } + + /** + * 更新状态 + * @param tag + */ + @Override + @Transactional(readOnly=false) + public void updateStatus(Tag tag) { + super.updateStatus(tag); + } + + /** + * 删除数据 + * @param tag + */ + @Override + @Transactional(readOnly=false) + public void delete(Tag tag) { + super.delete(tag); + } + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/service/VisitLogService.java b/modules/cms/src/main/java/com/jeesite/modules/cms/service/VisitLogService.java new file mode 100644 index 00000000..43f4f2a9 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/service/VisitLogService.java @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.service; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.jeesite.common.entity.Page; +import com.jeesite.common.service.CrudService; +import com.jeesite.modules.cms.dao.VisitLogDao; +import com.jeesite.modules.cms.entity.VisitLog; +import com.jeesite.modules.file.utils.FileUploadUtils; + +/** + * 访问日志表Service + * @author 长春叭哥、ThinkGem + * @version 2020-7-24 + */ +@Service +@Transactional(readOnly=true) +public class VisitLogService extends CrudService { + + /** + * 获取单条数据 + * @param visitLog + * @return + */ + @Override + public VisitLog get(VisitLog visitLog) { + return super.get(visitLog); + } + + /** + * 查询分页数据 + * @param visitLog 查询条件 + * @param visitLog.page 分页对象 + * @return + */ + @Override + public Page findPage(VisitLog visitLog) { + return super.findPage(visitLog); + } + + /** + * 保存数据(插入或更新) + * @param visitLog + */ + @Override + @Transactional(readOnly=false) + public void save(VisitLog visitLog) { + super.save(visitLog); + // 保存上传图片 + FileUploadUtils.saveFileUpload(visitLog.getId(), "visitLog_image"); + // 保存上传附件 + FileUploadUtils.saveFileUpload(visitLog.getId(), "visitLog_file"); + } + + /** + * 更新状态 + * @param visitLog + */ + @Override + @Transactional(readOnly=false) + public void updateStatus(VisitLog visitLog) { + super.updateStatus(visitLog); + } + + /** + * 删除数据 + * @param visitLog + */ + @Override + @Transactional(readOnly=false) + public void delete(VisitLog visitLog) { + super.delete(visitLog); + } + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/utils/CmsUtils.java b/modules/cms/src/main/java/com/jeesite/modules/cms/utils/CmsUtils.java new file mode 100644 index 00000000..d08c8073 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/utils/CmsUtils.java @@ -0,0 +1,484 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.utils; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import javax.servlet.ServletContext; + +import org.springframework.ui.Model; + +import com.jeesite.common.cache.CacheUtils; +import com.jeesite.common.collect.ListUtils; +import com.jeesite.common.config.Global; +import com.jeesite.common.entity.Page; +import com.jeesite.common.lang.ObjectUtils; +import com.jeesite.common.lang.StringUtils; +import com.jeesite.common.mapper.JsonMapper; +import com.jeesite.common.utils.SpringUtils; +import com.jeesite.modules.cms.entity.Article; +import com.jeesite.modules.cms.entity.Category; +import com.jeesite.modules.cms.entity.Site; +import com.jeesite.modules.cms.service.ArticleService; +import com.jeesite.modules.cms.service.CategoryService; +import com.jeesite.modules.cms.service.SiteService; + +/** + * CmsUtils + * @author 长春叭哥、ThinkGem + * @version 2020-7-24 + */ +public class CmsUtils { + + private static final class Static { + private static SiteService siteService = SpringUtils.getBean(SiteService.class); + private static CategoryService categoryService = SpringUtils.getBean(CategoryService.class); + private static ArticleService articleService = SpringUtils.getBean(ArticleService.class); + private static ServletContext context = SpringUtils.getBean(ServletContext.class); + } + + private static final String CMS_CACHE = "cmsCache"; + + /** + * 获得当前站点信息 + * @param siteCode 站点编号 + */ + public static Site getCurrentSite() { + return getSite(Site.getCurrentSiteCode()); + } + + /** + * 获得站点信息 + * @param siteCode 站点编号 + */ + public static Site getSite(String siteCode) { + String code = Site.MAIN_SITE_CODE; + if (StringUtils.isNotBlank(siteCode)) { + code = siteCode; + } + // 根据编码获取站点 + for (Site site : getSiteList()) { + if (site.getSiteCode().equals(code)) { + return site; + } + } + return new Site(code); + } + + /** + * 获得站点列表 + */ + public static List getSiteList() { + @SuppressWarnings("unchecked") + List siteList = (List) getCache("siteList"); + if (siteList == null) { + siteList = Static.siteService.findList(new Site()); + putCache("siteList", siteList); + } + return siteList; + } + + /** + * 获得主导航列表 + * @param siteCode 站点编号 + */ + public static List getMainNavList(String siteCode) { + @SuppressWarnings("unchecked") + List mainNavList = (List) getCache("mainNavList_" + siteCode); + if (mainNavList == null) { + Category category = new Category(); + category.setSite(new Site(siteCode)); + category.setParent(new Category(Category.ROOT_CODE)); + category.setInMenu(Global.SHOW); + mainNavList = Static.categoryService.findList(category); + putCache("mainNavList_" + siteCode, mainNavList); + } + return mainNavList; + } + + /** + * 获取栏目 + * @param categoryCode 栏目编号 + * @return + */ + public static Category getCategory(String categoryCode) { + return Static.categoryService.get(categoryCode); + } + + /** + * 获得栏目列表 + * @param siteCode 站点编号 + * @param parentCode 分类父编号 + * @param number 获取数目 + * @param params 预留参数,例: key1:'value1', key2:'value2' ...
+ * sortGrades : 获取的层次级别(从0开始,例如:sortGrades: \"0,1,2\" 则只获取0级1级2级的栏目)
+ * isChildList : 是否后续进行childList转换(1:进行获取childList列表)
+ * 调用举例(Beetl):
+ * 1、获取前10条一级栏目:${categoryList(site.siteCode, '0', 10)}
+ * 2、获取前200条一级和二级栏目,并对栏目进行子节点(childList)获取(注意:获取多级栏目的时候,这个200条数是全部的栏目条数包括所有子级个数): + * ${categoryList(site.siteCode, '0', 200, 'sortGrades:\"0,1\", isChildList:1')}
+ * 3、获取二级栏目下的两级栏目: ${categoryList(site.siteCode, 'xcl', 200, 'sortGrades:\"1,2\"')} + */ + public static List getCategoryList(String siteCode, String parentCode, int number, String params) { + if (StringUtils.isBlank(siteCode) || StringUtils.isBlank(parentCode)) { + return ListUtils.newArrayList(); + } + Page page = new Page(1, number, -1); + Category category = new Category(); + category.setSite(new Site(siteCode)); + category.setParentCode(parentCode); + Boolean isChildList = false; // 是否进行childList转换 + if (StringUtils.isNotBlank(params)) { + @SuppressWarnings({ "rawtypes" }) + Map map = JsonMapper.fromJson("{" + params.trim() + "}", Map.class); + + // 获取的层级级别 + String sortGrades = ObjectUtils.toString(map.get("sortGrades")); + if (StringUtils.isNotBlank(sortGrades)) { + + // 如果设置了级别,则清理ParentCode,并使用ParentCodes进行查询 + category.setParentCode(null); + + // 如果是跟节点则不加入条件,代表查询全部,不是跟节点的时候获取指定节点的所有下级 + if (!Category.ROOT_CODE.equals(parentCode)) { + category.setParentCodes("%," + parentCode + ",%"); + } + + // 增加获取层次级别条件 + List sortGradeList = ListUtils.newArrayList(); + for (String s : StringUtils.split(sortGrades, ",")) { + sortGradeList.add(ObjectUtils.toInteger(s)); + } + category.setSortGradeList(sortGradeList); + } + // 是否进行childList转换 + isChildList = ObjectUtils.toBoolean(map.get("isChildList")); + } + category.setPage(page); + page = Static.categoryService.findPage(category); + // 进行childList转换 + if (isChildList) { + List sourceList = page.getList(); + List targetList = Static.categoryService.convertTreeList(sourceList, parentCode); + page.setList(targetList); + } + return page.getList(); + } + + /** + * 获取文章 + * @param articleId 文章编号 + */ + public static Article getArticle(String articleId) { + return Static.articleService.get(articleId); + } + + /** + * 获取文章获取文章并点击数加一 + */ + public static Article getArticleAndHitsAddOne(String articleId) { + Article article = Static.articleService.get(articleId); + Static.articleService.updateHitsAddOne(articleId); + return article; + } + + /** + * 获取文章列表 + * @param siteCode 站点编号 + * @param categoryCode 分类编号 + * @param number 获取数目 + * @param param 预留参数,例: key1:'value1', key2:'value2' ...
+ * posid : 推荐位(1:首页焦点图;2:栏目页文章推荐;)
+ * image : 文章图片(1:有图片的文章)
+ * isQueryArticleData : 是否查询文章详情信息,查询会影响效率
+ * orderBy : 排序字符串(字符串类型的需要加引号如:orderBy: \"hits desc\" )
+ * 调用举例(Beetl):
+ * 1、查询当前栏目下的前10篇文章: ${articleList(category.site.siteCode, category.categoryCode, 10, '')}
+ * 2、查询当前栏目下的前10篇文章,并且是栏目页推荐文章,并按照访问次数排序: + * ${articleList(category.site.siteCode, category.categoryCode, 10, 'posid:2, orderBy: \"hits desc\"')}
+ * 3、查询当前栏目下的前10篇文章,并且是有图片的文章: ${articleList(category.site.siteCode, category.categoryCode, 10, 'image:1')} + */ + public static List
getArticleList(String siteCode, String categoryCode, int number, String params) { + if (StringUtils.isBlank(siteCode) || StringUtils.isBlank(categoryCode)) { + return ListUtils.newArrayList(); + } + Category category = new Category(); + category.setSite(new Site(siteCode)); + Page
page = new Page
(1, number, -1); + if (!Category.ROOT_CODE.equals(categoryCode)) { + category.setCategoryCode(categoryCode); + category.setParentCodes(categoryCode); + } + Article article = new Article(category); + if (StringUtils.isNotBlank(params)) { + @SuppressWarnings({ "rawtypes" }) + Map map = JsonMapper.fromJson("{" + params.trim() + "}", Map.class); + // 推荐位 + //String postid = ObjectUtils.toString(map.get("posid")); + // 文章图片 + if (ObjectUtils.toBoolean(map.get("image"))) { + article.setImage(Global.YES); + } + // 是否查询文章详情信息,查询会影响效率 + if (ObjectUtils.toBoolean(map.get("isQueryArticleData"))) { + article.setIsQueryArticleData(true); + } + // 排序字符串 + String orderBy = ObjectUtils.toString(map.get("orderBy")); + if (StringUtils.isNotBlank(orderBy)) { + page.setOrderBy(orderBy); + } + } + article.setStatus(Article.STATUS_NORMAL); + article.setPage(page); + page = Static.articleService.findPage(article); + return page.getList(); + } + + public static V getCache(String key) { + return CacheUtils.get(CMS_CACHE, key); + } + + public static V getCache(String key, V defaultValue) { + V value = CacheUtils.get(CMS_CACHE, key); + return value != null ? value : defaultValue; + } + + public static void putCache(String key, Object value) { + CacheUtils.put(CMS_CACHE, key, value); + } + + public static void removeCache(String key) { + CacheUtils.remove(CMS_CACHE, key); + } + + /** + * 获得文章动态URL地址 + * @param article + * @return url + */ + public static String getUrlDynamic(Article article) { + StringBuilder str = new StringBuilder(); + str.append(Static.context.getContextPath()); + if (StringUtils.isNotBlank(article.getHref())) { + if (article.getHref().contains("://")) { + return article.getHref(); + } else { + str.append(article.getHref()); + return str.toString(); + } + } + str.append(Global.getFrontPath()); + str.append("/view-").append(article.getCategory().getCategoryCode()); + str.append("-").append(article.getId()).append(".html"); + return str.toString(); + } + + /** + * 获得栏目动态URL地址 + * @param category + * @return url + */ + public static String getUrlDynamic(Category category) { + StringBuilder str = new StringBuilder(); + str.append(Static.context.getContextPath()).append(Global.getFrontPath()); + if (StringUtils.isNotBlank(category.getHref())) { + if (category.getHref().contains("://")) { + return category.getHref(); + } else { + str.append(category.getHref()); + return str.toString(); + } + } + str.append("/list-").append(category.getCategoryCode()).append(".html"); + return str.toString(); + } + + /** + * 获得栏目动态URL地址 + * @param category + * @return url + */ + public static String getAdminUrlDynamic(Category category) { + StringBuilder str = new StringBuilder(); + str.append(Static.context.getContextPath()).append(Global.getAdminPath()); + String adminUrlParam = null; // 管理地址的参数 + // 如果试图配置里配置了管理路径,则使用视图中的管理路径 + if (StringUtils.isNotBlank(category.getViewConfig())) { + @SuppressWarnings("rawtypes") + Map map = JsonMapper.fromJson("{" + category.getViewConfig().trim() + "}", Map.class); + if (map != null) { + // 管理地址 + String adminUrl = ObjectUtils.toString(map.get("adminUrl")); + // 如果给管理地址设置了参数,则加入参数 + adminUrlParam = ObjectUtils.toString(map.get("adminUrlParam")); + // 如果管理路径为false,则表示没有管理URL,则直接返回null + if (Global.FALSE.equals(adminUrl)) { + return "none"; + } + // 如果设置了管理地址,则返回管理路径地址 + if (StringUtils.isNotBlank(adminUrl)) { + // 外部地址,则直接返回 + if (adminUrl.contains("://")) { + return adminUrl; + } + // 内部地址:contextPath + adminPath + adminUrlParam + else { + str.append(adminUrl); + // 加入管理地址参数 + if (StringUtils.isNotBlank(adminUrlParam)) { + if (str.toString().contains("?")) { + str.append("&"); + } else { + str.append("?"); + } + str.append(adminUrlParam); + } + return str.toString(); + } + } + } + } + // 如果设置了外部链接,则返回外部链接地址 + if (StringUtils.isNotBlank(category.getHref())) { + // 外部地址,则直接返回 + if (category.getHref().contains("://")) { + return category.getHref(); + } + // 内部地址:contextPath + adminPath + /cms + href + else { + str.append("/cms").append(category.getHref()); + return str.toString(); + } + } + // 如果为公共栏目,则返回空,无管理地址 + if (StringUtils.isBlank(category.getModuleType())) { + return StringUtils.EMPTY; + } + // 返回默认的栏目管理地址:contextPath + adminPath + /cms/ + module + /list + str.append("/cms/").append(category.getModuleType()); + str.append("/list?category.categoryCode=").append(category.getCategoryCode()); + // 加入管理地址参数 + if (StringUtils.isNotBlank(adminUrlParam)) { + str.append("&").append(adminUrlParam); + } + // 默认使用大纲视图的站点(栏目的站点不为空,必须包含在配置中,已配置的地址中未配置outlineView时生效) + String outlineViewOfSiteCodes = Global.getConfig("cms.article.outlineViewOfSiteCodes"); + if (StringUtils.isNotBlank(outlineViewOfSiteCodes) && !"0".equals(outlineViewOfSiteCodes)) { + if (category.getSite() != null && StringUtils.isNotBlank(category.getSite().getSiteCode())) { + if (StringUtils.inString(category.getSite().getSiteCode(), StringUtils.split(outlineViewOfSiteCodes, ","))) { + if (!StringUtils.contains(str.toString(), "&outlineView=")) { + str.append("&outlineView=true"); + } + } + } + } + return str.toString(); + } + + /** + * 从图片地址中去除ContextPath地址 + * @param src + * @return + */ + public static String formatImageSrcToDb(String src) { + if (StringUtils.isBlank(src)) { + return src; + } + if (src.startsWith(Static.context.getContextPath() + "/userfiles")) { + return src.substring(Static.context.getContextPath().length()); + } else { + return src; + } + } + + /** + * 从图片地址中加入ContextPath地址 + * @param src + * @return + */ + public static String formatImageSrcToWeb(String src) { + if (StringUtils.isBlank(src)) { + return src; + } + if (src.startsWith(Static.context.getContextPath() + "/userfiles")) { + return src; + } else { + return Static.context.getContextPath() + src; + } + } + + /** + * 获取文章视图 + * @param article + * @return + */ + public static String getArticleView(Article article) { + if (StringUtils.isBlank(article.getCustomContentView())) { + String view = null; + Category c = article.getCategory(); + while (c != null) { + if (StringUtils.isNotBlank(c.getCustomContentView())) { + view = c.getCustomContentView(); + break; + } else if (!c.getIsRoot()) { + c = getCategory(c.getParentCode()); + if (c == null) { + break; + } + } else { + break; + } + } + return StringUtils.isBlank(view) ? Article.DEFAULT_TEMPLATE : view; + } else { + return article.getCustomContentView(); + } + } + + /** + * 视图配置属性设置 + * @param model + * @param params + */ + public static void addViewConfigAttribute(Model model, String params) { + if (StringUtils.isNotBlank(params)) { + @SuppressWarnings("rawtypes") + Map map = JsonMapper.fromJson("{" + params.trim() + "}", Map.class); + if (map != null) { + for (Object o : map.keySet()) { + model.addAttribute("viewConfig_" + o.toString(), map.get(o)); + } + } + } + } + + /** + * 视图配置属性设置 + * @param model + * @param category + */ + public static void addViewConfigAttribute(Model model, Category category) { + List categoryList = ListUtils.newArrayList(); + Category c = category; + while (c != null) { + categoryList.add(c); + if (!c.getIsRoot()) { + c = getCategory(c.getParentCode()); + if (c == null) { + break; + } + } else { + break; + } + } + Collections.reverse(categoryList); // 顺序逆反,子集高优先级。 + for (Category ca : categoryList) { + addViewConfigAttribute(model, ca.getViewConfig()); + } + } + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/utils/FileTempleteUtils.java b/modules/cms/src/main/java/com/jeesite/modules/cms/utils/FileTempleteUtils.java new file mode 100644 index 00000000..90fff1d7 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/utils/FileTempleteUtils.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.utils; + +import java.io.IOException; +import java.util.List; +import java.util.Set; + +import org.springframework.core.io.Resource; + +import com.jeesite.common.collect.ListUtils; +import com.jeesite.common.collect.SetUtils; +import com.jeesite.common.io.ResourceUtils; +import com.jeesite.modules.cms.entity.FileTemplete; + +/** + * 模板文件公共类库 + * @author 长春叭哥、ThinkGem + * @version 2020-7-7 + */ +public class FileTempleteUtils { + + /** + * 获取模版文件 + * @param fileName + */ + public static FileTemplete getFileTempleteByResource(String fileName) throws IOException { + Resource resource = ResourceUtils.getResource(fileName); + return new FileTemplete(resource, fileName); + } + + /** + * 获取模板文件集合 + * @param path 前缀路径 + */ + public static List getFileTempleteListByPath(String path) throws IOException { + Set set = SetUtils.newTreeSet(); + Resource[] resources = ResourceUtils.getResources("classpath*:" + path + "/**/*.html"); + for (Resource resource : resources) { + if (resource.exists()) { + set.add(new FileTemplete(resource, path)); + } + } + return ListUtils.newArrayList(set); + } + + /** + * 获取模板文件相关属性(含目录) + * @param path 前缀路径 + */ + public static List getFileTempleteListForEdit(String path) throws IOException { + + List list = getFileTempleteListByPath(path); + Set set = SetUtils.newLinkedHashSet(); + + // 获取目录 + list.forEach(e -> { + set.add(new FileTemplete(e)); + }); + set.addAll(list); + + return ListUtils.newArrayList(set); + } + +} diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/web/ArticleController.java b/modules/cms/src/main/java/com/jeesite/modules/cms/web/ArticleController.java new file mode 100644 index 00000000..25d82786 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/web/ArticleController.java @@ -0,0 +1,191 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.web; + +import java.io.IOException; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import com.jeesite.common.config.Global; +import com.jeesite.common.entity.Page; +import com.jeesite.common.lang.StringUtils; +import com.jeesite.common.web.BaseController; +import com.jeesite.modules.cms.entity.Article; +import com.jeesite.modules.cms.entity.ArticleData; +import com.jeesite.modules.cms.entity.Category; +import com.jeesite.modules.cms.entity.Site; +import com.jeesite.modules.cms.service.ArticleService; +import com.jeesite.modules.cms.service.CategoryService; +import com.jeesite.modules.cms.service.FileTempleteService; +import com.jeesite.modules.cms.utils.CmsUtils; +import com.jeesite.modules.sys.utils.UserUtils; + +/** + * 文章表Controller + * @author 长春叭哥、ThinkGem + * @version 2020-7-24 + */ +@Controller +@RequestMapping(value = "${adminPath}/cms/article") +public class ArticleController extends BaseController { + + @Autowired + private ArticleService articleService; + @Autowired + private CategoryService categoryService; + @Autowired + private FileTempleteService fileTempleteService; + + /** + * 获取数据 + */ + @ModelAttribute + public Article get(String id, boolean isNewRecord) { + return articleService.get(id, isNewRecord); + } + + /** + * 查询列表 + * @throws IOException + */ + @RequiresPermissions("cms:article:view") + @RequestMapping(value = { "list", "" }) + public String list(Article article, Boolean isAll, Model model) throws IOException { + if (StringUtils.isNotBlank(article.getCategory().getCategoryCode()) + && !Category.ROOT_CODE.equals(article.getCategory().getCategoryCode())) { + article.setCategory(CmsUtils.getCategory(article.getCategory().getCategoryCode())); + } + // 栏目展现模式,当为(3:简介类栏目,栏目第一条内容)时,自动维护第一条内容 + if (Category.SHOW_MODES_FIRST_CONTENT.equals(article.getCategory().getShowModes())) { + // 获取文章内容 + Page
page = new Page
(1, 1, -1); + article.setPage(page); + page = articleService.findPage(article); + if (page.getList().size() > 0) { + article = page.getList().get(0); + article.setArticleData(articleService.get(new ArticleData(article.getId()))); + } + return form(article, model); + } + model.addAttribute("isAll", isAll); + return "modules/cms/articleList"; + } + + /** + * 查询列表数据 + */ + @RequiresPermissions("cms:article:view") + @RequestMapping(value = "listData") + @ResponseBody + public Page
listData(Article article, Boolean isAll, HttpServletRequest request, HttpServletResponse response) { + article.setPage(new Page<>(request, response)); + if (StringUtils.isBlank(article.getCategory().getSite().getSiteCode())) { + article.getCategory().setSite(new Site(Site.getCurrentSiteCode())); + } + // 是否查询全部,不过滤权限 + if (!(isAll != null && isAll)) { + articleService.addDataScopeFilter(article); + } + if (!article.getCurrentUser().isAdmin()) { + // 如果没有审核权限,或者 草稿状态的文章 则只查看自己创建的文章。 + if (!UserUtils.getSubject().isPermitted("cms:article:audit")) { + article.setCreateBy(article.getCurrentUser().getUserCode()); + } else if (Article.STATUS_DRAFT.equals(article.getStatus())) { + article.setCreateBy(article.getCurrentUser().getUserCode()); + } + } + Page
page = articleService.findPage(article); + return page; + } + + /** + * 查看编辑表单 + * @throws IOException + */ + @RequiresPermissions("cms:article:view") + @RequestMapping(value = "form") + public String form(Article article, Model model) throws IOException { + if (StringUtils.isNotBlank(article.getCategory().getCategoryCode())) { + Category categoryParam = new Category(); + categoryParam.setSite(new Site(Site.getCurrentSiteCode())); + categoryParam.setParentCode(article.getCategory().getCategoryCode()); + List list = categoryService.findList(categoryParam); + if (list.size() > 0) { + article.setCategory(null); + } else { + article.setCategory(categoryService.get(article.getCategory().getId())); + } + } +// if (article.getCategory()=null && StringUtils.isNotBlank(article.getCategory().getId())){ +// Category category = categoryService.get(article.getCategory().getId()); +// } + if (StringUtils.isBlank(article.getId())) { + article.setStatus(Article.STATUS_DRAFT); + } + model.addAttribute("contentViewList", fileTempleteService.getTempleteContentDict(Article.DEFAULT_TEMPLATE)); + model.addAttribute("article_DEFAULT_TEMPLATE", Article.DEFAULT_TEMPLATE); + model.addAttribute("article", article); + CmsUtils.addViewConfigAttribute(model, article.getCategory()); + return "modules/cms/articleForm"; + } + + /** + * 保存文章表 + */ + @RequiresPermissions("cms:article:edit") + @PostMapping(value = "save") + @ResponseBody + public String save(@Validated Article article) { + articleService.save(article); + return renderResult(Global.TRUE, text("保存文章表成功!")); + } + + /** + * 停用文章表 + */ + @RequiresPermissions("cms:article:edit") + @RequestMapping(value = "disable") + @ResponseBody + public String disable(Article article) { + article.setStatus(Article.STATUS_DISABLE); + articleService.updateStatus(article); + return renderResult(Global.TRUE, text("停用文章表成功")); + } + + /** + * 启用文章表 + */ + @RequiresPermissions("cms:article:edit") + @RequestMapping(value = "enable") + @ResponseBody + public String enable(Article article) { + article.setStatus(Article.STATUS_NORMAL); + articleService.updateStatus(article); + return renderResult(Global.TRUE, text("启用文章表成功")); + } + + /** + * 删除文章表 + */ + @RequiresPermissions("cms:article:edit") + @RequestMapping(value = "delete") + @ResponseBody + public String delete(Article article) { + articleService.delete(article); + return renderResult(Global.TRUE, text("删除文章表成功!")); + } + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/web/CategoryController.java b/modules/cms/src/main/java/com/jeesite/modules/cms/web/CategoryController.java new file mode 100644 index 00000000..6c78f8bd --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/web/CategoryController.java @@ -0,0 +1,318 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.web; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import com.jeesite.common.collect.ListUtils; +import com.jeesite.common.collect.MapUtils; +import com.jeesite.common.config.Global; +import com.jeesite.common.idgen.IdGen; +import com.jeesite.common.lang.StringUtils; +import com.jeesite.common.web.BaseController; +import com.jeesite.modules.cms.entity.Article; +import com.jeesite.modules.cms.entity.Category; +import com.jeesite.modules.cms.entity.Site; +import com.jeesite.modules.cms.service.CategoryService; +import com.jeesite.modules.cms.service.FileTempleteService; +import com.jeesite.modules.cms.utils.CmsUtils; +import com.jeesite.modules.sys.entity.Office; +import com.jeesite.modules.sys.utils.DictUtils; +import com.jeesite.modules.sys.utils.UserUtils; + +/** + * 栏目表Controller + * @author 长春叭哥、ThinkGem + * @version 2020-7-24 + */ +@Controller +@RequestMapping(value = "${adminPath}/cms/category") +public class CategoryController extends BaseController { + + @Autowired + private CategoryService categoryService; + + @Autowired + private FileTempleteService fileTempleteService; + + /** + * 获取数据 + */ + @ModelAttribute + public Category get(String categoryCode, boolean isNewRecord) { + return categoryService.get(categoryCode, isNewRecord); + } + + /** + * 查询列表 + */ + @RequiresPermissions("cms:category:view") + @RequestMapping(value = { "list", "" }) + public String list(Category category, Model model) { + if (StringUtils.isBlank(category.getSite().getSiteCode())) { + category.setSite(new Site(Site.getCurrentSiteCode())); + } + category.setSite(CmsUtils.getSite(category.getSite().getSiteCode())); + model.addAttribute("category", category); + return "modules/cms/categoryList"; + } + + /** + * 查询列表数据 + */ + @RequiresPermissions("cms:category:view") + @RequestMapping(value = "listData") + @ResponseBody + public List listData(Category category) { + if (StringUtils.isBlank(category.getParentCode())) { + category.setParentCode(Office.ROOT_CODE); + } + if (StringUtils.isBlank(category.getSite().getSiteCode())) { + category.setSite(new Site(Site.getCurrentSiteCode())); + } + List list = null; + if (StringUtils.isNotBlank(category.getCategoryCode())) { + list = ListUtils.newArrayList(get(category.getCategoryCode(), false)); + } else { + list = categoryService.findList(category); + } + return list; + } + + /** + * 查看编辑表单 + * @throws IOException + */ + @RequiresPermissions("cms:category:view") + @RequestMapping(value = "form") + public String form(Category category, Model model) throws IOException { + // 创建并初始化下一个节点信息 + category = createNextNode(category); + if (category.getParent() != null && StringUtils.isNotBlank(category.getParent().getId())) { + category.setParent(categoryService.get(category.getParent().getCategoryCode())); + if (category.getIsNewRecord()) { + Category categoryChild = new Category(); + categoryChild.setParent(new Category(category.getParentCode())); + List list = categoryService.findList(category); + if (list.size() > 0) { + category.setTreeSort(list.get(list.size() - 1).getTreeSort()); + if (category.getTreeSort() != null) { + category.setTreeSort(category.getTreeSort() + 30); + } + } + } + if (category.getParent() != null) { + // 继承上级的模块类型 + if (StringUtils.isBlank(category.getModuleType())) { + category.setModuleType(category.getParent().getModuleType()); + } + // 继承上级的视图配置参数 + if (StringUtils.isBlank(category.getViewConfig())) { + category.setViewConfig(category.getParent().getViewConfig()); + } + } + } + if (category.getModuleType() == null) { + category.setModuleType("article"); + } + if (category.getInMenu() == null) { + category.setInMenu(Global.HIDE); + } + if (category.getInList() == null) { + category.setInList(Global.SHOW); + } + if (category.getShowModes() == null) { + category.setShowModes(Category.SHOW_MODES_AUTO); + } + if (category.getIsCanComment() == null) { + category.setIsCanComment(Global.NO); + } + if (category.getIsNeedAudit() == null) { + category.setIsNeedAudit(Global.NO); + } + model.addAttribute("listViewList", fileTempleteService.getTempleteContentDict(Category.DEFAULT_TEMPLATE)); + model.addAttribute("category_DEFAULT_TEMPLATE", Category.DEFAULT_TEMPLATE); + model.addAttribute("contentViewList", fileTempleteService.getTempleteContentDict(Article.DEFAULT_TEMPLATE)); + model.addAttribute("article_DEFAULT_TEMPLATE", Article.DEFAULT_TEMPLATE); + model.addAttribute("category", category); + return "modules/cms/categoryForm"; + } + + /** + * 创建并初始化下一个节点信息,如:排序号、默认值 + */ + @RequiresPermissions("cms:category:edit") + @RequestMapping(value = "createNextNode") + @ResponseBody + public Category createNextNode(Category category) { + if (StringUtils.isNotBlank(category.getParentCode())) { + category.setParent(categoryService.get(category.getParentCode())); + } + if (category.getIsNewRecord()) { + Category where = new Category(); + where.setParentCode(category.getParentCode()); + Category last = categoryService.getLastByParentCode(where); + // 获取到下级最后一个节点 + if (last != null) { + category.setTreeSort(last.getTreeSort() + 30); + category.setCategoryCode(IdGen.nextCode(last.getCategoryCode())); + } else if (category.getParent() != null) { + category.setCategoryCode(category.getParent().getCategoryCode() + "001"); + } + } + // 以下设置表单默认数据 + if (category.getTreeSort() == null) { + category.setTreeSort(Category.DEFAULT_TREE_SORT); + } + return category; + } + + /** + * 保存栏目表 + */ + @RequiresPermissions("cms:category:edit") + @PostMapping(value = "save") + @ResponseBody + public String save(@Validated Category category) { + // 如果保存的时候,没有上一级,或者是根级别,给一个默认的站点 + if (Category.ROOT_CODE.equals(category.getParentCode())) { + category.setSite(new Site(Site.getCurrentSiteCode())); + } + // 如果存在上级则保存时,归属站点与上一级同步 + else if (StringUtils.isNotBlank(category.getParent().getId())) { + category.setSite(categoryService.get(category.getParent()).getSite()); + } + // 同步到ID + if (category.getParent() != null) { + category.getParent().setId(category.getParent().getCategoryCode()); + } + categoryService.save(category); + return renderResult(Global.TRUE, text("保存栏目表成功!")); + } + + /** + * 停用栏目表 + */ + @RequiresPermissions("cms:category:edit") + @RequestMapping(value = "disable") + @ResponseBody + public String disable(Category category) { + Category where = new Category(); + where.setStatus(Category.STATUS_NORMAL); + where.setParentCodes("," + category.getId() + ","); + long count = categoryService.findCount(where); + if (count > 0) { + return renderResult(Global.FALSE, text("该栏目表包含未停用的子栏目表!")); + } + category.setStatus(Category.STATUS_DISABLE); + categoryService.updateStatus(category); + return renderResult(Global.TRUE, text("停用栏目表成功")); + } + + /** + * 启用栏目表 + */ + @RequiresPermissions("cms:category:edit") + @RequestMapping(value = "enable") + @ResponseBody + public String enable(Category category) { + category.setStatus(Category.STATUS_NORMAL); + categoryService.updateStatus(category); + return renderResult(Global.TRUE, text("启用栏目表成功")); + } + + /** + * 删除栏目表 + */ + @RequiresPermissions("cms:category:edit") + @RequestMapping(value = "delete") + @ResponseBody + public String delete(Category category) { + categoryService.delete(category); + return renderResult(Global.TRUE, text("删除栏目表成功!")); + } + + /** + * 获取树结构数据 + * @param excludeCode 排除的Code + * @param isShowCode 是否显示编码(true or 1:显示在左侧;2:显示在右侧;false or null:不显示) + * @return + */ + @RequiresPermissions("cms:category:view") + @RequestMapping(value = "treeData") + @ResponseBody + public List> treeData(String siteCode, String module, String extCode, Boolean isAll, String isShowCode) { + List> mapList = ListUtils.newArrayList(); + List categoryList = null; + Category category = new Category(); + // 站点条件 + if (StringUtils.isNotBlank(siteCode)) { + category.setSite(new Site(siteCode)); + } else { + category.setSite(new Site(Site.getCurrentSiteCode())); + } + // 栏目模型条件 + if (StringUtils.isNotBlank(module)) { + category.setModuleType(module); + } + // 是否查询全部,不过滤权限 + if (!(isAll != null && isAll)) { + categoryService.addDataScopeFilter(category); + } + categoryList = categoryService.findList(category); + // 处理转换数据,并返回ztree支持的格式 + for (int i = 0; i < categoryList.size(); i++) { + Category e = categoryList.get(i); + if (extCode == null || (extCode != null && !extCode.equals(e.getId()) && e.getParentCodes().indexOf("," + extCode + ",") == -1)) { + Map map = MapUtils.newHashMap(); + map.put("id", e.getId()); + map.put("pId", e.getParent() != null ? e.getParent().getId() : 0); + if ("true".equals(isShowCode) || "1".equals(isShowCode)) { + map.put("name", "(" + e.getCategoryCode() + ")" + e.getCategoryName()); + } else if ("2".equals(isShowCode)) { + map.put("name", e.getCategoryName() + "(" + e.getCategoryCode() + ")"); + } else { + map.put("name", e.getCategoryName()); + } + map.put("title", e.getCategoryName() + " [" + DictUtils.getDictLabel(e.getModuleType(), "cms_module", "公共模型") + "]"); + map.put("module", e.getModuleType()); + map.put("showModes", e.getShowModes()); + // 是否仅获取可管理的栏目,指定 true 或 false + String adminUrl = e.getAdminUrl(); + if (!"none".equals(adminUrl)) { + map.put("adminUrl", "".equals(adminUrl) ? "none" : adminUrl); + mapList.add(map); + } + } + } + return mapList; + } + + /** + * 修复表结构相关数据 + */ + @RequiresPermissions("cms:category:edit") + @RequestMapping(value = "fixTreeData") + @ResponseBody + public String fixTreeData(Category category) { + if (!UserUtils.getUser().isAdmin()) { + return renderResult(Global.FALSE, "操作失败,只有管理员才能进行修复!"); + } + categoryService.fixTreeData(); + return renderResult(Global.TRUE, "数据修复成功"); + } + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/web/CmsIndexController.java b/modules/cms/src/main/java/com/jeesite/modules/cms/web/CmsIndexController.java new file mode 100644 index 00000000..b0811aa7 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/web/CmsIndexController.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.web; + +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; + +import com.jeesite.common.web.BaseController; + +/** + * 内容管理Controller + * @author 长春叭哥、ThinkGem + * @version 2020-7-24 + */ +@Controller +@RequestMapping(value = "${adminPath}/cms") +public class CmsIndexController extends BaseController { + + @RequiresPermissions("cms:view") + @RequestMapping(value = "index") + public String index() { + return "modules/cms/cmsIndex"; + } + + @RequiresPermissions("cms:view") + @RequestMapping(value = "view") + public String view(Model model) { + return "modules/cms/cmsView"; + } + + @RequiresPermissions("cms:view") + @RequestMapping(value = "none") + public String none() { + return "modules/cms/cmsNone"; + } + +} diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/web/CommentController.java b/modules/cms/src/main/java/com/jeesite/modules/cms/web/CommentController.java new file mode 100644 index 00000000..f32ae984 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/web/CommentController.java @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.web; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import com.jeesite.common.config.Global; +import com.jeesite.common.entity.Page; +import com.jeesite.common.web.BaseController; +import com.jeesite.modules.cms.entity.Comment; +import com.jeesite.modules.cms.service.CommentService; + +/** + * 文章评论表Controller + * @author 长春叭哥、ThinkGem + * @version 2020-7-24 + */ +@Controller +@RequestMapping(value = "${adminPath}/cms/comment") +public class CommentController extends BaseController { + + @Autowired + private CommentService commentService; + + /** + * 获取数据 + */ + @ModelAttribute + public Comment get(String id, boolean isNewRecord) { + return commentService.get(id, isNewRecord); + } + + /** + * 查询列表 + */ + @RequiresPermissions("cms:comment:view") + @RequestMapping(value = {"list", ""}) + public String list(Comment comment, Model model) { + model.addAttribute("comment", comment); + return "modules/cms/commentList"; + } + + /** + * 查询列表数据 + */ + @RequiresPermissions("cms:comment:view") + @RequestMapping(value = "listData") + @ResponseBody + public Page listData(Comment comment, HttpServletRequest request, HttpServletResponse response) { + comment.setPage(new Page<>(request, response)); + Page page = commentService.findPage(comment); + return page; + } + + /** + * 查看编辑表单 + */ + @RequiresPermissions("cms:comment:view") + @RequestMapping(value = "form") + public String form(Comment comment, Model model) { + model.addAttribute("comment", comment); + return "modules/cms/commentForm"; + } + + /** + * 保存文章评论表 + */ + @RequiresPermissions("cms:comment:edit") + @PostMapping(value = "save") + @ResponseBody + public String save(@Validated Comment comment) { + commentService.save(comment); + return renderResult(Global.TRUE, text("保存文章评论表成功!")); + } + + /** + * 停用文章评论表 + */ + @RequiresPermissions("cms:comment:edit") + @RequestMapping(value = "disable") + @ResponseBody + public String disable(Comment comment) { + comment.setStatus(Comment.STATUS_DISABLE); + commentService.updateStatus(comment); + return renderResult(Global.TRUE, text("停用文章评论表成功")); + } + + /** + * 启用文章评论表 + */ + @RequiresPermissions("cms:comment:edit") + @RequestMapping(value = "enable") + @ResponseBody + public String enable(Comment comment) { + comment.setStatus(Comment.STATUS_NORMAL); + commentService.updateStatus(comment); + return renderResult(Global.TRUE, text("启用文章评论表成功")); + } + + /** + * 删除文章评论表 + */ + @RequiresPermissions("cms:comment:edit") + @RequestMapping(value = "delete") + @ResponseBody + public String delete(Comment comment) { + commentService.delete(comment); + return renderResult(Global.TRUE, text("删除文章评论表成功!")); + } + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/web/FileTemplateController.java b/modules/cms/src/main/java/com/jeesite/modules/cms/web/FileTemplateController.java new file mode 100644 index 00000000..0189f31e --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/web/FileTemplateController.java @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.web; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import com.jeesite.common.collect.ListUtils; +import com.jeesite.common.collect.MapUtils; +import com.jeesite.common.web.BaseController; +import com.jeesite.modules.cms.entity.FileTemplete; +import com.jeesite.modules.cms.entity.Site; +import com.jeesite.modules.cms.service.FileTempleteService; + +/** + * 模板管理 + * @author 长春叭哥、ThinkGem + * @version 2020-7-24 + */ +@Controller +@RequestMapping(value = "${adminPath}/cms/template") +public class FileTemplateController extends BaseController { + + //构想,给一个模板列表,模板下存放一個screenshots1~10.png,做为模版快照。 + //README.md模版使用与说明文件 + //zip上传模版文件 + //模版目录格式:{design:{index.png,list-x.png,detail-x.png},readme.md,shots} + //支持在线 安装与卸载 模板 if()是否存在这个主题文件夹, 存在则判断init内配置文件 开启|关闭的配置 + + @Autowired + private FileTempleteService fileTempleteService; + + @RequiresPermissions("cms:template:edit") + @RequestMapping(value = { "list", "" }) + public String index() { + return "modules/cms/tplIndex"; + } + +// @RequiresPermissions("cms:template:edit") +// @RequestMapping(value = "tree") +// public String tree(Model model) throws IOException { +// //根据系统默认的主题获取模板地址 +// model.addAttribute("templateList", fileTempleteService +// .getFileTempleteListForEdit(Site.TEMPLETE_BASE_DIRECTION + "/" + "default")); +// return "modules/cms/tplTree"; +// } + + @RequiresPermissions("cms:template:edit") + @RequestMapping(value = "form") + public String form(String name, Model model) throws IOException { + model.addAttribute("template", fileTempleteService.getFileTemplete(name)); + return "modules/cms/tplForm"; + } + +// @RequiresPermissions("cms:template:edit") +// @RequestMapping(value = "saveFileTemplate") +// @ResponseBody +// public String saveFileTemplate(String filePath, String fileName, String fileSource, Model model) throws IOException { +// +// FileTemplete currentFile = FilesTempleteUtils.getFileTempleteByResource(filePath); +// //在修改文件之前,开启模版的备份模式 +// FileUtils.copyDirectory(currentFile.getFile().getAbsolutePath(), +// currentFile.getFile().getAbsolutePath().replaceAll(currentFile.getFile().getName(), "") + DateUtils.getDate() +// + currentFile.getFile()); +// FileUtils.writeToFile(currentFile.getFile().getAbsolutePath(), EncodeUtils.decodeHtml(fileSource), false); +// +// if (!currentFile.getFile().getName().equals(fileName)) { +// String path = currentFile.getFile().getAbsolutePath().replaceAll(currentFile.getFile().getName(), "") + fileName; +// currentFile.getFile().renameTo(new File(path)); +// return renderResult(Global.SHOW, "模版保存成功,请左侧菜单刷新后再操作模版!"); +// } +// +// return renderResult(Global.TRUE, "模版保存成功!"); +// } + + @RequiresPermissions("cms:template:edit") + @RequestMapping(value = "help") + public String help() { + return "modules/cms/tplHelp"; + } + + /** + * 获取树结构数据 + * @param excludeCode 排除的Code + * @param isShowCode 是否显示编码(true or 1:显示在左侧;2:显示在右侧;false or null:不显示) + * @return + * @throws IOException + */ + @RequiresPermissions("cms:template:edit") + @RequestMapping(value = "treeData") + @ResponseBody + public List> treeData(String siteCode, String module, String extCode, Boolean isAll, String isShowCode) + throws IOException { + List> mapList = ListUtils.newArrayList(); + //根据系统默认的主题获取模板地址 + List listFileTemplete = fileTempleteService + .getFileTempleteListForEdit(Site.TEMPLETE_BASE_DIRECTION); + // 处理转换数据,并返回ztree支持的格式 + for (int i = 0; i < listFileTemplete.size(); i++) { + FileTemplete e = listFileTemplete.get(i); + Map map = MapUtils.newHashMap(); + map.put("id", e.getFilePath() + "/" + e.getFileName()); + map.put("isDirectory", e.isDirectory()); + map.put("pId", e.getFilePath()); + map.put("title", e.getFileName()); + map.put("name", e.getFileName()); + mapList.add(map); + } + return mapList; + } +} diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/web/ReportController.java b/modules/cms/src/main/java/com/jeesite/modules/cms/web/ReportController.java new file mode 100644 index 00000000..2fda34ec --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/web/ReportController.java @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.web; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import com.jeesite.common.config.Global; +import com.jeesite.common.entity.Page; +import com.jeesite.common.web.BaseController; +import com.jeesite.modules.cms.entity.Report; +import com.jeesite.modules.cms.service.ReportService; + +/** + * 内容举报表Controller + * @author 长春叭哥、ThinkGem + * @version 2020-7-24 + */ +@Controller +@RequestMapping(value = "${adminPath}/cms/report") +public class ReportController extends BaseController { + + @Autowired + private ReportService reportService; + + /** + * 获取数据 + */ + @ModelAttribute + public Report get(String id, boolean isNewRecord) { + return reportService.get(id, isNewRecord); + } + + /** + * 查询列表 + */ + @RequiresPermissions("cms:report:view") + @RequestMapping(value = {"list", ""}) + public String list(Report report, Model model) { + model.addAttribute("report", report); + return "modules/cms/reportList"; + } + + /** + * 查询列表数据 + */ + @RequiresPermissions("cms:report:view") + @RequestMapping(value = "listData") + @ResponseBody + public Page listData(Report report, HttpServletRequest request, HttpServletResponse response) { + report.setPage(new Page<>(request, response)); + Page page = reportService.findPage(report); + return page; + } + + /** + * 查看编辑表单 + */ + @RequiresPermissions("cms:report:view") + @RequestMapping(value = "form") + public String form(Report report, Model model) { + model.addAttribute("report", report); + return "modules/cms/reportForm"; + } + + /** + * 保存内容举报表 + */ + @RequiresPermissions("cms:report:edit") + @PostMapping(value = "save") + @ResponseBody + public String save(@Validated Report report) { + reportService.save(report); + return renderResult(Global.TRUE, text("保存内容举报表成功!")); + } + + /** + * 停用内容举报表 + */ + @RequiresPermissions("cms:report:edit") + @RequestMapping(value = "disable") + @ResponseBody + public String disable(Report report) { + report.setStatus(Report.STATUS_DISABLE); + reportService.updateStatus(report); + return renderResult(Global.TRUE, text("停用内容举报表成功")); + } + + /** + * 启用内容举报表 + */ + @RequiresPermissions("cms:report:edit") + @RequestMapping(value = "enable") + @ResponseBody + public String enable(Report report) { + report.setStatus(Report.STATUS_NORMAL); + reportService.updateStatus(report); + return renderResult(Global.TRUE, text("启用内容举报表成功")); + } + + /** + * 删除内容举报表 + */ + @RequiresPermissions("cms:report:edit") + @RequestMapping(value = "delete") + @ResponseBody + public String delete(Report report) { + reportService.delete(report); + return renderResult(Global.TRUE, text("删除内容举报表成功!")); + } + +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cms/web/SiteController.java b/modules/cms/src/main/java/com/jeesite/modules/cms/web/SiteController.java new file mode 100644 index 00000000..adebe646 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cms/web/SiteController.java @@ -0,0 +1,158 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cms.web; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import com.jeesite.common.config.Global; +import com.jeesite.common.entity.Page; +import com.jeesite.common.lang.StringUtils; +import com.jeesite.common.web.BaseController; +import com.jeesite.common.web.CookieUtils; +import com.jeesite.modules.cms.entity.Site; +import com.jeesite.modules.cms.service.FileTempleteService; +import com.jeesite.modules.cms.service.SiteService; +import com.jeesite.modules.sys.utils.CorpUtils; +import com.jeesite.modules.sys.utils.UserUtils; + +/** + * 站点表Controller + * @author 长春叭哥、ThinkGem + * @version 2020-7-24 + */ +@Controller +@RequestMapping(value = "${adminPath}/cms/site") +public class SiteController extends BaseController { + + @Autowired + private SiteService siteService; + + @Autowired + private FileTempleteService fileTempleteService; + + /** + * 获取数据 + */ + @ModelAttribute + public Site get(String siteCode, boolean isNewRecord) { + return siteService.get(siteCode, isNewRecord); + } + + /** + * 查询列表 + */ + @RequiresPermissions("cms:site:view") + @RequestMapping(value = { "list", "" }) + public String list(Site site, Model model) { + + model.addAttribute("site", site); + return "modules/cms/siteList"; + } + + /** + * 查询列表数据 + */ + @RequiresPermissions("cms:site:view") + @RequestMapping(value = "listData") + @ResponseBody + public Page listData(Site site, HttpServletRequest request, HttpServletResponse response) { + site.setPage(new Page<>(request, response)); + Page page = siteService.findPage(site); + return page; + } + + /** + * 查看编辑表单 + * @throws IOException + */ + @RequiresPermissions("cms:site:view") + @RequestMapping(value = "form") + public String form(Site site, Model model) throws IOException { + model.addAttribute("indexViewList", fileTempleteService.getTempleteContentDict(Site.DEFAULT_TEMPLATE)); + model.addAttribute("site_DEFAULT_TEMPLATE", Site.DEFAULT_TEMPLATE); + model.addAttribute("site", site); + model.addAttribute("demos", site); + return "modules/cms/siteForm"; + } + + /** + * 保存站点表 + */ + @RequiresPermissions("cms:site:edit") + @PostMapping(value = "save") + @ResponseBody + public String save(@Validated Site site) { + siteService.save(site); + return renderResult(Global.TRUE, text("保存站点表成功!")); + } + + /** + * 停用站点表 + */ + @RequiresPermissions("cms:site:edit") + @RequestMapping(value = "disable") + @ResponseBody + public String disable(Site site) { + site.setStatus(Site.STATUS_DISABLE); + siteService.updateStatus(site); + return renderResult(Global.TRUE, text("停用站点表成功")); + } + + /** + * 启用站点表 + */ + @RequiresPermissions("cms:site:edit") + @RequestMapping(value = "enable") + @ResponseBody + public String enable(Site site) { + site.setStatus(Site.STATUS_NORMAL); + siteService.updateStatus(site); + return renderResult(Global.TRUE, text("启用站点表成功")); + } + + /** + * 删除站点表 + */ + @RequiresPermissions("cms:site:edit") + @RequestMapping(value = "delete") + @ResponseBody + public String delete(Site site) { + siteService.delete(site); + return renderResult(Global.TRUE, text("删除站点表成功!")); + } + + /** + * 选择站点 + */ + @RequestMapping(value = "select") + public String select(String siteCode, String redirect, HttpServletRequest request, HttpServletResponse response){ + if (StringUtils.isBlank(siteCode)){ + return REDIRECT + adminPath + "/cms/index"; + } + UserUtils.putCache("currentSiteCode", siteCode); + // 保存到Cookie中,下次登录后自动切换到该站点 + String cookieName = "siteCode"; + if (Global.isUseCorpModel()){ + cookieName = CorpUtils.getCurrentCorpCode() + "_" + cookieName; + } + CookieUtils.setCookie(response, cookieName, siteCode); + if (StringUtils.isNotBlank(redirect)){ + return REDIRECT + redirect; + } + return renderResult(response, Global.TRUE, "切换站点成功!"); + } +} \ No newline at end of file diff --git a/modules/cms/src/main/java/com/jeesite/modules/cmsfront/web/FrontController.java b/modules/cms/src/main/java/com/jeesite/modules/cmsfront/web/FrontController.java new file mode 100644 index 00000000..1b9ed11e --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cmsfront/web/FrontController.java @@ -0,0 +1,368 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cmsfront.web; + +import java.util.Date; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +import com.jeesite.common.collect.ListUtils; +import com.jeesite.common.config.Global; +import com.jeesite.common.entity.Page; +import com.jeesite.common.lang.ObjectUtils; +import com.jeesite.common.lang.StringUtils; +import com.jeesite.common.web.BaseController; +import com.jeesite.modules.cms.entity.Article; +import com.jeesite.modules.cms.entity.ArticleData; +import com.jeesite.modules.cms.entity.Category; +import com.jeesite.modules.cms.entity.Comment; +import com.jeesite.modules.cms.entity.Site; +import com.jeesite.modules.cms.service.ArticleService; +import com.jeesite.modules.cms.service.CategoryService; +import com.jeesite.modules.cms.service.CommentService; +import com.jeesite.modules.cms.utils.CmsUtils; +import com.jeesite.modules.sys.utils.ValidCodeUtils; + +/** + * 网站Controller + * @author ThinkGem、三片叶子、长春八哥 + * @version 2020-7-24 + */ +@Controller +@RequestMapping(value = "${frontPath}") +public class FrontController extends BaseController { + + @Autowired + private CategoryService categoryService; + @Autowired + private ArticleService articleService; + @Autowired + private CommentService commentService; + + /** + * 主站首页 + */ + @RequestMapping(value = { "", "index", "index.html" }) + public String index(Model model) { + return REDIRECT + frontPath + "/index-" + Site.MAIN_SITE_CODE + ".html"; + } + + /** + * 站点首页 + */ + @RequestMapping(value = { "index-{siteCode}", "index-{siteCode}.html" }) + public String index(@PathVariable String siteCode, Model model) { + // 如果是主站,获取主站信息并进入主页 + if (Site.isMainSite(siteCode)) { + Site site = CmsUtils.getSite(Site.MAIN_SITE_CODE); + model.addAttribute("site", site); + model.addAttribute("isIndex", true); + return "modules/cmsfront/themes/" + site.getTheme() + "/index"; + } + + // 不是主站,则获取子站点信息 + Site site = CmsUtils.getSite(siteCode); + model.addAttribute("site", site); + + // 子站有独立页面,则显示独立页面 + if (StringUtils.isNotBlank(site.getCustomIndexView())) { + model.addAttribute("isIndex", true); + return "modules/cmsfront/themes/" + site.getTheme() + "/" + site.getCustomIndexView(); + } + + // 否则显示子站第一个栏目 + List mainNavList = CmsUtils.getMainNavList(siteCode); + if (mainNavList.size() > 0) { + String firstCategoryCode = CmsUtils.getMainNavList(siteCode).get(0).getId(); + return REDIRECT + frontPath + "/list-" + firstCategoryCode + ".html"; + } + + // 站点中无栏目,则显示栏目分类空白页 + else { + return "modules/cmsfront/themes/" + site.getTheme() + "/" + Category.DEFAULT_TEMPLATE + "Category"; + } + } + + /** + * 内容列表 + */ + @RequestMapping(value = { "list-{categoryCode}", "list-{categoryCode}.html" }) + public String list(@PathVariable String categoryCode, + @RequestParam(required = false, defaultValue = "1") Integer pageNo, + @RequestParam(required = false, defaultValue = "30") Integer pageSize, Model model, + HttpServletRequest request) { + + // 获取栏目信息 + Category category = CmsUtils.getCategory(categoryCode); + if (category == null || !Category.STATUS_NORMAL.equals(category.getStatus())) { + Site site = CmsUtils.getSite(Site.MAIN_SITE_CODE); + model.addAttribute("site", site); + return "error/404"; + } + + // 如果设置了外部链接,则跳转到指定链接 + if (StringUtils.isNotBlank(category.getHref())) { + if (category.getHref().startsWith(request.getContextPath())) { + category.setHref(category.getHref().replaceFirst(request.getContextPath(), "")); + } + return "redirect:" + category.getHref(); + } + + // 获取站点信息 + Site site = CmsUtils.getSite(category.getSite().getId()); + model.addAttribute("site", site); + + // 当前栏目展现方式为:3:简介类栏目,栏目第一条内容 + if (Category.SHOW_MODES_FIRST_CONTENT.equals(category.getShowModes())) { + return view(categoryCode, null, model, request); + } + + // 当前展现方式为:1:默认,或者,2:栏目列表 + else { + + // 当前栏目的子栏目列表 + List categoryList = null; + + // 如果有子节点,则查询子栏目列表 + if (!category.getIsTreeLeaf()) { + Category categoryParam = new Category(); + categoryParam.setSite(new Site(site.getSiteCode())); + categoryParam.setParentCode(category.getCategoryCode()); + categoryList = categoryService.findList(categoryParam); + model.addAttribute("categoryList", categoryList); + }else{ + categoryList = ListUtils.newArrayList(); + } + + // 当前栏目展现方式为:2 、无子栏目或公共模型,显示栏目内容列表;1:无子栏目或一个子栏目,显示栏目内容列表 + if (Category.SHOW_MODES_CENTENT_LIST.equals(category.getShowModes()) || categoryList.size() <= 1) { + + // 有子栏目并展现方式为2,则获取第一个子栏目;无子栏目,则获取同级分类列表。 + if (categoryList.size() > 0) { + category = categoryList.get(0); + } + + // 如果第一个子栏目为简介类栏目,则获取该栏目第一篇文章并展现 + if (Category.SHOW_MODES_FIRST_CONTENT.equals(category.getShowModes())) { + return view(category.getCategoryCode(), null, model, request); + } + + // 否则,获取内容列表信息 + else { + // 文章模型 + if ("article".equals(category.getModuleType())) { + Page
page = new Page
(pageNo, pageSize); + Article searchArticle= new Article(category); + searchArticle.setPage(page); + page = articleService.findPage(searchArticle); + model.addAttribute("page", page); + } + } + + // 将数据信息传递到视图 + model.addAttribute("category", category); + CmsUtils.addViewConfigAttribute(model, category); + String view = Category.DEFAULT_TEMPLATE; + if (StringUtils.isNotBlank(category.getCustomListView())) { + view = category.getCustomListView(); + } + return "modules/cmsfront/themes/" + site.getTheme() + "/" + view; + } + + // 当前栏目展现方式为:0:默认时,有子栏目:显示子栏目列表 + else { + model.addAttribute("category", category); + CmsUtils.addViewConfigAttribute(model, category); + String view = Category.DEFAULT_TEMPLATE + "Category"; + if (StringUtils.isNotBlank(category.getCustomListView())) { + view = category.getCustomListView(); + } + return "modules/cmsfront/themes/" + site.getTheme() + "/" + view; + } + } + } + + /** + * 内容列表(通过url自定义视图) + */ + @RequestMapping(value = { "list-{categoryCode}-{customView}", "listc-{categoryCode}-{customView}.html" }) + public String listCustom(@PathVariable String categoryCode, @PathVariable String customView, + @RequestParam(required = false, defaultValue = "1") Integer pageNo, + @RequestParam(required = false, defaultValue = "30") Integer pageSize, Model model, + HttpServletRequest request) { + + // 获取栏目信息 + Category category = CmsUtils.getCategory(categoryCode); + if (category == null || !Category.STATUS_NORMAL.equals(category.getStatus())) { + Site site = CmsUtils.getSite(Site.MAIN_SITE_CODE); + model.addAttribute("site", site); + return "error/404"; + } + + // 获取站点信息 + Site site = CmsUtils.getSite(category.getSite().getId()); + model.addAttribute("site", site); + + // 将数据信息传递到视图 + model.addAttribute("category", category); + CmsUtils.addViewConfigAttribute(model, category); + return "modules/cmsfront/themes/" + site.getTheme() + "/" + Category.DEFAULT_TEMPLATE + customView; + } + + /** + * 显示内容 + */ + @RequestMapping(value = { "view-{categoryCode}-{contentId}", "view-{categoryCode}-{contentId}.html" }) + public String view(@PathVariable String categoryCode, @PathVariable String contentId, Model model, + HttpServletRequest request) { + + // 获取栏目信息 + Category category = CmsUtils.getCategory(categoryCode); + if (category == null || !Category.STATUS_NORMAL.equals(category.getStatus())) { + Site site = CmsUtils.getSite(Site.MAIN_SITE_CODE); + model.addAttribute("site", site); + return "error/404"; + } + + // 文章模型 + if ("article".equals(category.getModuleType())) { + +// // 获取当前级别的栏目列表 +// List categoryList = Lists.newArrayList(); +//// if (category.getIsRoot()){ +//// categoryList.add(category); +//// }else{ +//// categoryList = categoryService.findListByParentCode(category.getParentCode(), category.getSite().getId()); +// categoryList = CmsUtils.getCategoryList(category.getSite().getSiteCode(), category.getParentCode(), -1, null); +//// } +// model.addAttribute("categoryList", categoryList); + + // 获取文章 + Article article = null; + // 设置内容ID,则获取文章内容 + if (StringUtils.isNotBlank(contentId)) { + article = articleService.get(new Article(contentId)); + } + + // 如果没有设置内容ID则获取栏目里的第一篇文章 + else { + Page
page = new Page
(1, 1, -1); + Article entity = new Article(category); + entity.setPage(page); + page = articleService.findPage(entity); + if (page.getList().size() > 0) { + article = page.getList().get(0); + article.setArticleData(articleService.get(new ArticleData(article.getId()))); + } + } + + // 如果没有取到文章,则抛到404页面 + if (article == null || !Article.STATUS_NORMAL.equals(article.getStatus())) { + return "error/404"; + } + + // 文章阅读次数+1 + articleService.updateHitsAddOne(contentId); + + // 如果设置了外部链接,则跳转到指定链接 + if (StringUtils.isNotBlank(article.getHref())) { + if (article.getHref().startsWith(request.getContextPath())) { + article.setHref(article.getHref().replaceFirst(request.getContextPath(), "")); + } + return "redirect:" + article.getHref(); + } + + model.addAttribute("article", article); + + // 获取文章归属栏目的全信息 + article.setCategory(CmsUtils.getCategory(article.getCategory().getId())); + model.addAttribute("category", article.getCategory()); + + // 获取栏目所在站点全信息 + Site site = CmsUtils.getSite(category.getSite().getId()); + model.addAttribute("site", site); + + // 获取推荐文章列表 + List relationList = articleService.findByIds(article.getArticleData().getRelation()); + model.addAttribute("relationList", relationList); + + // 将数据信息传递到视图 + CmsUtils.addViewConfigAttribute(model, article.getCategory()); + CmsUtils.addViewConfigAttribute(model, article.getViewConfig()); + return "modules/cmsfront/themes/" + site.getTheme() + "/" + CmsUtils.getArticleView(article); + } + return "error/404"; + } + + /** + * 内容评论 + */ + @RequestMapping(value = "comment", method = RequestMethod.GET) + public String comment(Comment comment, String theme, HttpServletRequest request, HttpServletResponse response, + Model model) { + Page page = new Page(request, response); + Comment c = new Comment(); + c.setCategory(comment.getCategory()); + c.setArticleId(comment.getArticleId()); + c.setStatus(Comment.STATUS_NORMAL); + c.setPage(page); + page = commentService.findPage(c); + model.addAttribute("page", page); + model.addAttribute("comment", comment); + return "modules/cmsfront/themes/" + theme + "/comment"; + } + + /** + * 内容评论保存 + */ + @RequestMapping(value = "comment", method = RequestMethod.POST) + @ResponseBody + public String commentSave(Comment comment, String validCode, @RequestParam(required = false) String replyId, + HttpServletRequest request) { + if (StringUtils.isNotBlank(validCode)) { + if (ValidCodeUtils.validate(request, validCode)) { + if (StringUtils.isNotBlank(replyId)) { + Comment replyComment = commentService.get(replyId); + if (replyComment != null) { + comment.setContent("
" + replyComment.getName() + ":
" + + replyComment.getContent() + "
" + comment.getContent()); + } + } + comment.setIp(request.getRemoteAddr()); + comment.setCreateDate(new Date()); + Boolean isAudit = ObjectUtils.toBoolean(Global.getConfig("cms.comment.isAudit")); + comment.setStatus(isAudit ? Comment.STATUS_AUDIT : Comment.STATUS_NORMAL); + comment.setStatus(Comment.STATUS_AUDIT); + commentService.save(comment); + return "{result:1, message:'提交成功" + (isAudit ? ",请等待审核" : "") + "。'}"; + } else { + return "{result:2, message:'验证码不正确。'}"; + } + } else { + return "{result:2, message:'验证码不能为空。'}"; + } + } + + /** + * 站点地图 + */ + @RequestMapping(value = { "map-{siteCode}", "map-{siteCode}.html" }) + public String map(@PathVariable String siteCode, Model model) { + Site site = CmsUtils.getSite(siteCode); + model.addAttribute("site", site); + return "modules/cmsfront/themes/" + site.getTheme() + "/map"; + } + +} diff --git a/modules/cms/src/main/java/com/jeesite/modules/cmsfront/web/FrontSearchController.java b/modules/cms/src/main/java/com/jeesite/modules/cmsfront/web/FrontSearchController.java new file mode 100644 index 00000000..fd09be57 --- /dev/null +++ b/modules/cms/src/main/java/com/jeesite/modules/cmsfront/web/FrontSearchController.java @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + */ +package com.jeesite.modules.cmsfront.web; + +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; + +import com.jeesite.common.collect.MapUtils; +import com.jeesite.common.entity.Page; +import com.jeesite.common.lang.StringUtils; +import com.jeesite.common.lang.TimeUtils; +import com.jeesite.common.web.BaseController; +import com.jeesite.modules.cms.entity.Site; +import com.jeesite.modules.cms.service.ArticleService; +import com.jeesite.modules.cms.utils.CmsUtils; + +/** + * 网站搜索Controller + * @author ThinkGem + * @version 2020-7-24 + */ +@Controller +@RequestMapping(value = "${frontPath}/search") +public class FrontSearchController extends BaseController{ + + @Autowired + private ArticleService articleService; + + /** + * 全站搜索 + * @param t 搜索类型(article、guestbook) + * @param q 搜索关键字 + * @param qand 包含以下全部的关键词 + * @param qnot 不包含以下关键词 + * @param bd 最后更新日期范围开始 + * @param ed 最后更新日期范围结束 + */ + @RequestMapping(value = "") + public String search(String t, String q, String qand, String qnot, String bd, String ed, + String siteCode, HttpServletRequest request, HttpServletResponse response, Model model) { + long start = System.currentTimeMillis(); + Site site = CmsUtils.getSite(siteCode); + model.addAttribute("site", site); + + // 执行检索(搜索词长度必须大于或等于两个字符) + if (q != null && q.length() >= 2){ + + // 文章检索 + if (StringUtils.isBlank(t) || "article".equals(t)){ + Page> page = new Page>(request, response); + Map parmas = MapUtils.newHashMap(); + if (StringUtils.isNotBlank(siteCode)){ + parmas.put("siteCode", siteCode); + } + page = articleService.searchPage(page, q, qand, qnot, bd, ed, parmas); + page.setPageInfo("匹配结果,共耗时 " + TimeUtils.formatDateAgo(System.currentTimeMillis() - start) + "。"); + model.addAttribute("page", page); + } + + } + + model.addAttribute("t", t); // 搜索类型 + model.addAttribute("q", q); // 搜索关键字 + model.addAttribute("qand", qand); // 包含以下全部的关键词 + model.addAttribute("qnot", qnot); // 不包含以下关键词 + return "modules/cmsfront/themes/"+site.getTheme()+"/search"; + } + +} diff --git a/modules/cms/src/main/resources/config/beetl-cms.properties b/modules/cms/src/main/resources/config/beetl-cms.properties new file mode 100644 index 00000000..e27fdd33 --- /dev/null +++ b/modules/cms/src/main/resources/config/beetl-cms.properties @@ -0,0 +1,21 @@ + +#设置与beetl-default.properties相同的属性将被覆盖默认设置 + +#导入项目中的调用静态方法类(项目中设置,自动合并IMPORT_PACKAGE设置) +IMPORT_PACKAGE_cms=\ + com.jeesite.modules.cms.utils.;\ + +## 内置的方法 +#FN.date = org.beetl.ext.fn.DateFunction + +##内置的功能包 +#FNP.strutil = org.beetl.ext.fn.StringUtil + +##内置的格式化函数 +#FT.dateFormat = org.beetl.ext.format.DateFormat + +##内置的默认格式化函数 +#FTC.java.util.Date = org.beetl.ext.format.DateFormat + +## 标签类 +#TAG.include= org.beetl.ext.tag.IncludeTag diff --git a/modules/cms/src/main/resources/db/create/h2/cms.sql b/modules/cms/src/main/resources/db/create/h2/cms.sql new file mode 100644 index 00000000..bb325544 --- /dev/null +++ b/modules/cms/src/main/resources/db/create/h2/cms.sql @@ -0,0 +1,320 @@ + + +/* Create Tables */ + +-- 文章表 +CREATE TABLE ${_prefix}cms_article +( + id varchar(64) NOT NULL, + category_code varchar(64) NOT NULL, + module_type varchar(50), + title vargraphic(255) NOT NULL, + href vargraphic(1000), + color varchar(50), + image vargraphic(1000), + keywords vargraphic(500), + description vargraphic(500), + weight decimal(10) DEFAULT 0, + weight_date timestamp, + source char(1), + copyfrom vargraphic(255), + hits decimal(20) DEFAULT 0, + hits_plus numeric(10), + hits_minus numeric(10), + word_count numeric(10), + custom_content_view varchar(255), + view_config vargraphic(1000), + status char(1) DEFAULT '0' NOT NULL, + create_by varchar(64) NOT NULL, + create_date timestamp NOT NULL, + update_by varchar(64) NOT NULL, + update_date timestamp NOT NULL, + remarks vargraphic(500), + corp_code varchar(64) DEFAULT '0' NOT NULL, + corp_name vargraphic(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +); + + +-- 文章详情表 +CREATE TABLE ${_prefix}cms_article_data +( + id varchar(64) NOT NULL, + content clob, + relation varchar(1000), + is_can_comment char(1), + extend_s1 vargraphic(500), + extend_s2 vargraphic(500), + extend_s3 vargraphic(500), + extend_s4 vargraphic(500), + extend_s5 vargraphic(500), + extend_s6 vargraphic(500), + extend_s7 vargraphic(500), + extend_s8 vargraphic(500), + extend_i1 decimal(19), + extend_i2 decimal(19), + extend_i3 decimal(19), + extend_i4 decimal(19), + extend_f1 decimal(19,4), + extend_f2 decimal(19,4), + extend_f3 decimal(19,4), + extend_f4 decimal(19,4), + extend_d1 timestamp, + extend_d2 timestamp, + extend_d3 timestamp, + extend_d4 timestamp, + PRIMARY KEY (id) +); + + +-- 文章推荐位 +CREATE TABLE ${_prefix}cms_article_posid +( + article_id varchar(64) NOT NULL, + postid char(1) NOT NULL +); + + +-- 文章与标签关系 +CREATE TABLE ${_prefix}cms_article_tag +( + article_id varchar(64) NOT NULL, + tag_name vargraphic(200) NOT NULL +); + + +-- 栏目表 +CREATE TABLE ${_prefix}cms_category +( + category_code varchar(64) NOT NULL, + parent_code varchar(64) NOT NULL, + parent_codes varchar(1000) NOT NULL, + tree_sort decimal(10) NOT NULL, + tree_sorts varchar(1000) NOT NULL, + tree_leaf char(1) NOT NULL, + tree_level decimal(4) NOT NULL, + tree_names vargraphic(1000) NOT NULL, + category_name vargraphic(100) NOT NULL, + site_code varchar(64) NOT NULL, + module_type varchar(50), + image varchar(255), + href varchar(255), + target varchar(20), + keywords vargraphic(500), + description vargraphic(500), + in_menu char(1), + in_list char(1), + show_modes char(1), + is_need_audit char(1), + is_can_comment char(1), + custom_list_view varchar(255), + custom_content_view varchar(255), + view_config vargraphic(1000), + status char(1) DEFAULT '0' NOT NULL, + create_by varchar(64) NOT NULL, + create_date timestamp NOT NULL, + update_by varchar(64) NOT NULL, + update_date timestamp NOT NULL, + remarks vargraphic(500), + extend_s1 vargraphic(500), + extend_s2 vargraphic(500), + extend_s3 vargraphic(500), + extend_s4 vargraphic(500), + extend_s5 vargraphic(500), + extend_s6 vargraphic(500), + extend_s7 vargraphic(500), + extend_s8 vargraphic(500), + extend_i1 decimal(19), + extend_i2 decimal(19), + extend_i3 decimal(19), + extend_i4 decimal(19), + extend_f1 decimal(19,4), + extend_f2 decimal(19,4), + extend_f3 decimal(19,4), + extend_f4 decimal(19,4), + extend_d1 timestamp, + extend_d2 timestamp, + extend_d3 timestamp, + extend_d4 timestamp, + PRIMARY KEY (category_code) +); + + +-- 栏目与角色关联表 +CREATE TABLE ${_prefix}cms_category_role +( + category_code varchar(64) NOT NULL, + role_code varchar(64) NOT NULL, + ctrl_type varchar(32), + PRIMARY KEY (category_code, role_code) +); + + +-- 文章评论表 +CREATE TABLE ${_prefix}cms_comment +( + id varchar(64) NOT NULL, + category_code varchar(64) NOT NULL, + article_id varchar(64) NOT NULL, + parent_id varchar(64), + article_title vargraphic(255) NOT NULL, + content vargraphic(255) NOT NULL, + name vargraphic(50), + ip varchar(100), + create_by varchar(64), + create_date timestamp NOT NULL, + audit_user_code varchar(64), + audit_date timestamp, + audit_comment vargraphic(200), + hits_plus numeric(10), + hits_minus numeric(10), + status char(1) NOT NULL, + corp_code varchar(64) DEFAULT '0' NOT NULL, + corp_name vargraphic(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +); + + +-- 留言板表 +CREATE TABLE ${_prefix}cms_guestbook +( + id varchar(64) NOT NULL, + type char(1) NOT NULL, + content varchar(255) NOT NULL, + name varchar(100) NOT NULL, + email varchar(100) NOT NULL, + phone varchar(100) NOT NULL, + workunit varchar(100) NOT NULL, + ip varchar(100) NOT NULL, + create_by varchar(64), + create_date timestamp, + re_user_code varchar(64), + re_date timestamp, + re_content varchar(100), + status char(1) NOT NULL, + corp_code varchar(64) DEFAULT '0' NOT NULL, + corp_name vargraphic(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +); + + +-- 内容举报表 +CREATE TABLE ${_prefix}cms_report +( + id varchar(64) NOT NULL, + report_source char(1), + report_content vargraphic(500), + report_url vargraphic(1000), + report_type char(1), + report_cause vargraphic(500), + PRIMARY KEY (id) +); + + +-- 站点表 +CREATE TABLE ${_prefix}cms_site +( + site_code varchar(64) NOT NULL, + site_name vargraphic(100) NOT NULL, + site_sort decimal(10), + title vargraphic(100) NOT NULL, + logo vargraphic(1000), + domain vargraphic(500), + keywords vargraphic(500), + description vargraphic(500), + theme vargraphic(500), + copyright vargraphic(1000), + custom_index_view varchar(500), + status char(1) DEFAULT '0' NOT NULL, + create_by varchar(64) NOT NULL, + create_date timestamp NOT NULL, + update_by varchar(64) NOT NULL, + update_date timestamp NOT NULL, + remarks vargraphic(500), + PRIMARY KEY (site_code) +); + + +-- 内容标签 +CREATE TABLE ${_prefix}cms_tag +( + tag_name vargraphic(200) NOT NULL, + clicknum numeric(10) NOT NULL, + PRIMARY KEY (tag_name) +); + + +-- 访问日志表 +CREATE TABLE ${_prefix}cms_visit_log +( + id varchar(64) NOT NULL, + request_url vargraphic(1000), + request_url_host varchar(128), + source_referer vargraphic(1000), + source_referer_host varchar(128), + source_type char(1), + search_engine varchar(200), + search_word vargraphic(200), + remote_addr varchar(50), + user_agent vargraphic(500), + user_language varchar(32), + user_screen_size varchar(32), + user_device varchar(32), + user_os_name varchar(32), + user_browser varchar(32), + user_browser_version varchar(16), + unique_visit_id varchar(64), + visit_date char(8), + visit_time timestamp, + is_new_visit char(1), + first_visit_time decimal(20), + prev_remain_time decimal(20), + total_remain_time decimal(20), + site_code varchar(64), + site_name vargraphic(100), + category_code varchar(64), + category_name vargraphic(100), + content_id varchar(64), + content_title vargraphic(255), + visit_user_code varchar(100), + visit_user_name varchar(100), + corp_code varchar(64) DEFAULT '0' NOT NULL, + corp_name vargraphic(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +); + + + +/* Create Indexes */ + +CREATE INDEX idx_cms_article_cb ON ${_prefix}cms_article (create_by); +CREATE INDEX idx_cms_article_cc ON ${_prefix}cms_article (category_code); +CREATE INDEX idx_cms_article_corp_code ON ${_prefix}cms_article (corp_code); +CREATE INDEX idx_cms_article_status ON ${_prefix}cms_article (status); +CREATE INDEX idx_cms_article_ud ON ${_prefix}cms_article (update_date); +CREATE INDEX idx_cms_article_weight ON ${_prefix}cms_article (weight); +CREATE INDEX idx_cms_category_pc ON ${_prefix}cms_category (parent_code); +CREATE INDEX idx_cms_category_ts ON ${_prefix}cms_category (tree_sort); +CREATE INDEX idx_cms_category_status ON ${_prefix}cms_category (status); +CREATE INDEX idx_cms_category_tss ON ${_prefix}cms_category (tree_sorts); +CREATE INDEX idx_cms_comment_catc ON ${_prefix}cms_comment (category_code); +CREATE INDEX idx_cms_comment_ai ON ${_prefix}cms_comment (article_id); +CREATE INDEX idx_cms_comment_cc ON ${_prefix}cms_comment (corp_code); +CREATE INDEX idx_cms_comment_status ON ${_prefix}cms_comment (status); +CREATE INDEX idx_cms_guestbook_cc ON ${_prefix}cms_guestbook (corp_code); +CREATE INDEX idx_cms_guestbook_status ON ${_prefix}cms_guestbook (status); +CREATE INDEX idx_cms_guestbook_type ON ${_prefix}cms_guestbook (type); +CREATE INDEX idx_cms_site_status ON ${_prefix}cms_site (status); +CREATE INDEX cms_visit_log_cc ON ${_prefix}cms_visit_log (category_code); +CREATE INDEX cms_visit_log_ci ON ${_prefix}cms_visit_log (content_id); +CREATE INDEX cms_visit_log_fvt ON ${_prefix}cms_visit_log (first_visit_time); +CREATE INDEX cms_visit_log_inv ON ${_prefix}cms_visit_log (is_new_visit); +CREATE INDEX cms_visit_log_ra ON ${_prefix}cms_visit_log (remote_addr); +CREATE INDEX cms_visit_log_sc ON ${_prefix}cms_visit_log (site_code); +CREATE INDEX cms_visit_log_uvid ON ${_prefix}cms_visit_log (unique_visit_id); +CREATE INDEX cms_visit_log_vd ON ${_prefix}cms_visit_log (visit_date); +CREATE INDEX cms_visit_log_vt ON ${_prefix}cms_visit_log (visit_time); +CREATE INDEX idx_cms_visit_log_corpc ON ${_prefix}cms_visit_log (corp_code); + + + diff --git a/modules/cms/src/main/resources/db/create/mssql/cms.sql b/modules/cms/src/main/resources/db/create/mssql/cms.sql new file mode 100644 index 00000000..efd921c3 --- /dev/null +++ b/modules/cms/src/main/resources/db/create/mssql/cms.sql @@ -0,0 +1,320 @@ + + +/* Create Tables */ + +-- 文章表 +CREATE TABLE [${_prefix}cms_article] +( + [id] varchar(64) NOT NULL, + [category_code] varchar(64) NOT NULL, + [module_type] varchar(50), + [title] nvarchar(255) NOT NULL, + [href] nvarchar(1000), + [color] varchar(50), + [image] nvarchar(1000), + [keywords] nvarchar(500), + [description] nvarchar(500), + [weight] decimal(10) DEFAULT 0, + [weight_date] datetime, + [source] char(1), + [copyfrom] nvarchar(255), + [hits] decimal(20) DEFAULT 0, + [hits_plus] numeric(10), + [hits_minus] numeric(10), + [word_count] numeric(10), + [custom_content_view] varchar(255), + [view_config] nvarchar(1000), + [status] char(1) DEFAULT '0' NOT NULL, + [create_by] varchar(64) NOT NULL, + [create_date] datetime NOT NULL, + [update_by] varchar(64) NOT NULL, + [update_date] datetime NOT NULL, + [remarks] nvarchar(500), + [corp_code] varchar(64) DEFAULT '0' NOT NULL, + [corp_name] nvarchar(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY ([id]) +); + + +-- 文章详情表 +CREATE TABLE [${_prefix}cms_article_data] +( + [id] varchar(64) NOT NULL, + [content] text, + [relation] varchar(1000), + [is_can_comment] char(1), + [extend_s1] nvarchar(500), + [extend_s2] nvarchar(500), + [extend_s3] nvarchar(500), + [extend_s4] nvarchar(500), + [extend_s5] nvarchar(500), + [extend_s6] nvarchar(500), + [extend_s7] nvarchar(500), + [extend_s8] nvarchar(500), + [extend_i1] decimal(19), + [extend_i2] decimal(19), + [extend_i3] decimal(19), + [extend_i4] decimal(19), + [extend_f1] decimal(19,4), + [extend_f2] decimal(19,4), + [extend_f3] decimal(19,4), + [extend_f4] decimal(19,4), + [extend_d1] datetime, + [extend_d2] datetime, + [extend_d3] datetime, + [extend_d4] datetime, + PRIMARY KEY ([id]) +); + + +-- 文章推荐位 +CREATE TABLE [${_prefix}cms_article_posid] +( + [article_id] varchar(64) NOT NULL, + [postid] char(1) NOT NULL +); + + +-- 文章与标签关系 +CREATE TABLE [${_prefix}cms_article_tag] +( + [article_id] varchar(64) NOT NULL, + [tag_name] nvarchar(200) NOT NULL +); + + +-- 栏目表 +CREATE TABLE [${_prefix}cms_category] +( + [category_code] varchar(64) NOT NULL, + [parent_code] varchar(64) NOT NULL, + [parent_codes] varchar(1000) NOT NULL, + [tree_sort] decimal(10) NOT NULL, + [tree_sorts] varchar(1000) NOT NULL, + [tree_leaf] char(1) NOT NULL, + [tree_level] decimal(4) NOT NULL, + [tree_names] nvarchar(1000) NOT NULL, + [category_name] nvarchar(100) NOT NULL, + [site_code] varchar(64) NOT NULL, + [module_type] varchar(50), + [image] varchar(255), + [href] varchar(255), + [target] varchar(20), + [keywords] nvarchar(500), + [description] nvarchar(500), + [in_menu] char(1), + [in_list] char(1), + [show_modes] char(1), + [is_need_audit] char(1), + [is_can_comment] char(1), + [custom_list_view] varchar(255), + [custom_content_view] varchar(255), + [view_config] nvarchar(1000), + [status] char(1) DEFAULT '0' NOT NULL, + [create_by] varchar(64) NOT NULL, + [create_date] datetime NOT NULL, + [update_by] varchar(64) NOT NULL, + [update_date] datetime NOT NULL, + [remarks] nvarchar(500), + [extend_s1] nvarchar(500), + [extend_s2] nvarchar(500), + [extend_s3] nvarchar(500), + [extend_s4] nvarchar(500), + [extend_s5] nvarchar(500), + [extend_s6] nvarchar(500), + [extend_s7] nvarchar(500), + [extend_s8] nvarchar(500), + [extend_i1] decimal(19), + [extend_i2] decimal(19), + [extend_i3] decimal(19), + [extend_i4] decimal(19), + [extend_f1] decimal(19,4), + [extend_f2] decimal(19,4), + [extend_f3] decimal(19,4), + [extend_f4] decimal(19,4), + [extend_d1] datetime, + [extend_d2] datetime, + [extend_d3] datetime, + [extend_d4] datetime, + PRIMARY KEY ([category_code]) +); + + +-- 栏目与角色关联表 +CREATE TABLE [${_prefix}cms_category_role] +( + [category_code] varchar(64) NOT NULL, + [role_code] varchar(64) NOT NULL, + [ctrl_type] varchar(32), + PRIMARY KEY ([category_code], [role_code]) +); + + +-- 文章评论表 +CREATE TABLE [${_prefix}cms_comment] +( + [id] varchar(64) NOT NULL, + [category_code] varchar(64) NOT NULL, + [article_id] varchar(64) NOT NULL, + [parent_id] varchar(64), + [article_title] nvarchar(255) NOT NULL, + [content] nvarchar(255) NOT NULL, + [name] nvarchar(50), + [ip] varchar(100), + [create_by] varchar(64), + [create_date] datetime NOT NULL, + [audit_user_code] varchar(64), + [audit_date] datetime, + [audit_comment] nvarchar(200), + [hits_plus] numeric(10), + [hits_minus] numeric(10), + [status] char(1) NOT NULL, + [corp_code] varchar(64) DEFAULT '0' NOT NULL, + [corp_name] nvarchar(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY ([id]) +); + + +-- 留言板表 +CREATE TABLE [${_prefix}cms_guestbook] +( + [id] varchar(64) NOT NULL, + [type] char(1) NOT NULL, + [content] varchar(255) NOT NULL, + [name] varchar(100) NOT NULL, + [email] varchar(100) NOT NULL, + [phone] varchar(100) NOT NULL, + [workunit] varchar(100) NOT NULL, + [ip] varchar(100) NOT NULL, + [create_by] varchar(64), + [create_date] datetime, + [re_user_code] varchar(64), + [re_date] datetime, + [re_content] varchar(100), + [status] char(1) NOT NULL, + [corp_code] varchar(64) DEFAULT '0' NOT NULL, + [corp_name] nvarchar(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY ([id]) +); + + +-- 内容举报表 +CREATE TABLE [${_prefix}cms_report] +( + [id] varchar(64) NOT NULL, + [report_source] char(1), + [report_content] nvarchar(500), + [report_url] nvarchar(1000), + [report_type] char(1), + [report_cause] nvarchar(500), + PRIMARY KEY ([id]) +); + + +-- 站点表 +CREATE TABLE [${_prefix}cms_site] +( + [site_code] varchar(64) NOT NULL, + [site_name] nvarchar(100) NOT NULL, + [site_sort] decimal(10), + [title] nvarchar(100) NOT NULL, + [logo] nvarchar(1000), + [domain] nvarchar(500), + [keywords] nvarchar(500), + [description] nvarchar(500), + [theme] nvarchar(500), + [copyright] nvarchar(1000), + [custom_index_view] varchar(500), + [status] char(1) DEFAULT '0' NOT NULL, + [create_by] varchar(64) NOT NULL, + [create_date] datetime NOT NULL, + [update_by] varchar(64) NOT NULL, + [update_date] datetime NOT NULL, + [remarks] nvarchar(500), + PRIMARY KEY ([site_code]) +); + + +-- 内容标签 +CREATE TABLE [${_prefix}cms_tag] +( + [tag_name] nvarchar(200) NOT NULL, + [clicknum] numeric(10) NOT NULL, + PRIMARY KEY ([tag_name]) +); + + +-- 访问日志表 +CREATE TABLE [${_prefix}cms_visit_log] +( + [id] varchar(64) NOT NULL, + [request_url] nvarchar(1000), + [request_url_host] varchar(128), + [source_referer] nvarchar(1000), + [source_referer_host] varchar(128), + [source_type] char(1), + [search_engine] varchar(200), + [search_word] nvarchar(200), + [remote_addr] varchar(50), + [user_agent] nvarchar(500), + [user_language] varchar(32), + [user_screen_size] varchar(32), + [user_device] varchar(32), + [user_os_name] varchar(32), + [user_browser] varchar(32), + [user_browser_version] varchar(16), + [unique_visit_id] varchar(64), + [visit_date] char(8), + [visit_time] datetime, + [is_new_visit] char(1), + [first_visit_time] decimal(20), + [prev_remain_time] decimal(20), + [total_remain_time] decimal(20), + [site_code] varchar(64), + [site_name] nvarchar(100), + [category_code] varchar(64), + [category_name] nvarchar(100), + [content_id] varchar(64), + [content_title] nvarchar(255), + [visit_user_code] varchar(100), + [visit_user_name] varchar(100), + [corp_code] varchar(64) DEFAULT '0' NOT NULL, + [corp_name] nvarchar(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY ([id]) +); + + + +/* Create Indexes */ + +CREATE INDEX [idx_cms_article_cb] ON [${_prefix}cms_article] ([create_by]); +CREATE INDEX [idx_cms_article_cc] ON [${_prefix}cms_article] ([category_code]); +CREATE INDEX [idx_cms_article_corp_code] ON [${_prefix}cms_article] ([corp_code]); +CREATE INDEX [idx_cms_article_status] ON [${_prefix}cms_article] ([status]); +CREATE INDEX [idx_cms_article_ud] ON [${_prefix}cms_article] ([update_date]); +CREATE INDEX [idx_cms_article_weight] ON [${_prefix}cms_article] ([weight]); +CREATE INDEX [idx_cms_category_pc] ON [${_prefix}cms_category] ([parent_code]); +CREATE INDEX [idx_cms_category_ts] ON [${_prefix}cms_category] ([tree_sort]); +CREATE INDEX [idx_cms_category_status] ON [${_prefix}cms_category] ([status]); +CREATE INDEX [idx_cms_category_tss] ON [${_prefix}cms_category] ([tree_sorts]); +CREATE INDEX [idx_cms_comment_catc] ON [${_prefix}cms_comment] ([category_code]); +CREATE INDEX [idx_cms_comment_ai] ON [${_prefix}cms_comment] ([article_id]); +CREATE INDEX [idx_cms_comment_cc] ON [${_prefix}cms_comment] ([corp_code]); +CREATE INDEX [idx_cms_comment_status] ON [${_prefix}cms_comment] ([status]); +CREATE INDEX [idx_cms_guestbook_cc] ON [${_prefix}cms_guestbook] ([corp_code]); +CREATE INDEX [idx_cms_guestbook_status] ON [${_prefix}cms_guestbook] ([status]); +CREATE INDEX [idx_cms_guestbook_type] ON [${_prefix}cms_guestbook] ([type]); +CREATE INDEX [idx_cms_site_status] ON [${_prefix}cms_site] ([status]); +CREATE INDEX [cms_visit_log_cc] ON [${_prefix}cms_visit_log] ([category_code]); +CREATE INDEX [cms_visit_log_ci] ON [${_prefix}cms_visit_log] ([content_id]); +CREATE INDEX [cms_visit_log_fvt] ON [${_prefix}cms_visit_log] ([first_visit_time]); +CREATE INDEX [cms_visit_log_inv] ON [${_prefix}cms_visit_log] ([is_new_visit]); +CREATE INDEX [cms_visit_log_ra] ON [${_prefix}cms_visit_log] ([remote_addr]); +CREATE INDEX [cms_visit_log_sc] ON [${_prefix}cms_visit_log] ([site_code]); +CREATE INDEX [cms_visit_log_uvid] ON [${_prefix}cms_visit_log] ([unique_visit_id]); +CREATE INDEX [cms_visit_log_vd] ON [${_prefix}cms_visit_log] ([visit_date]); +CREATE INDEX [cms_visit_log_vt] ON [${_prefix}cms_visit_log] ([visit_time]); +CREATE INDEX [idx_cms_visit_log_corpc] ON [${_prefix}cms_visit_log] ([corp_code]); + + + diff --git a/modules/cms/src/main/resources/db/create/mysql/cms.sql b/modules/cms/src/main/resources/db/create/mysql/cms.sql new file mode 100644 index 00000000..6ac402ec --- /dev/null +++ b/modules/cms/src/main/resources/db/create/mysql/cms.sql @@ -0,0 +1,321 @@ +SET SESSION FOREIGN_KEY_CHECKS=0; + + +/* Create Tables */ + +-- 文章表 +CREATE TABLE ${_prefix}cms_article +( + id varchar(64) NOT NULL COMMENT '编号', + category_code varchar(64) NOT NULL COMMENT '栏目编码', + module_type varchar(50) COMMENT '模块类型', + title varchar(255) NOT NULL COMMENT '内容标题', + href varchar(1000) COMMENT '外部链接', + color varchar(50) COMMENT '标题颜色', + image varchar(1000) COMMENT '内容图片', + keywords varchar(500) COMMENT '关键字', + description varchar(500) COMMENT '描述', + weight decimal(10) DEFAULT 0 COMMENT '权重,越大越靠前', + weight_date datetime COMMENT '权重期限', + source char(1) COMMENT '来源(转载/原创)', + copyfrom varchar(255) COMMENT '文章来源出处', + hits decimal(20) DEFAULT 0 COMMENT '点击数', + hits_plus numeric(10) COMMENT '支持数', + hits_minus numeric(10) COMMENT '反对数', + word_count numeric(10) COMMENT '字数(不包含html)', + custom_content_view varchar(255) COMMENT '自定义内容视图', + view_config varchar(1000) COMMENT '视图配置', + status char(1) DEFAULT '0' NOT NULL COMMENT '状态(0正常 1删除 2停用)', + create_by varchar(64) NOT NULL COMMENT '创建者', + create_date datetime NOT NULL COMMENT '创建时间', + update_by varchar(64) NOT NULL COMMENT '更新者', + update_date datetime NOT NULL COMMENT '更新时间', + remarks varchar(500) COMMENT '备注信息', + corp_code varchar(64) DEFAULT '0' NOT NULL COMMENT '租户代码', + corp_name varchar(100) DEFAULT 'JeeSite' NOT NULL COMMENT '租户名称', + PRIMARY KEY (id) +) COMMENT = '文章表'; + + +-- 文章详情表 +CREATE TABLE ${_prefix}cms_article_data +( + id varchar(64) NOT NULL COMMENT '编号', + content longtext COMMENT '文章内容', + relation varchar(1000) COMMENT '相关文章', + is_can_comment char(1) COMMENT '是否允许评论', + extend_s1 varchar(500) COMMENT '扩展 String 1', + extend_s2 varchar(500) COMMENT '扩展 String 2', + extend_s3 varchar(500) COMMENT '扩展 String 3', + extend_s4 varchar(500) COMMENT '扩展 String 4', + extend_s5 varchar(500) COMMENT '扩展 String 5', + extend_s6 varchar(500) COMMENT '扩展 String 6', + extend_s7 varchar(500) COMMENT '扩展 String 7', + extend_s8 varchar(500) COMMENT '扩展 String 8', + extend_i1 decimal(19) COMMENT '扩展 Integer 1', + extend_i2 decimal(19) COMMENT '扩展 Integer 2', + extend_i3 decimal(19) COMMENT '扩展 Integer 3', + extend_i4 decimal(19) COMMENT '扩展 Integer 4', + extend_f1 decimal(19,4) COMMENT '扩展 Float 1', + extend_f2 decimal(19,4) COMMENT '扩展 Float 2', + extend_f3 decimal(19,4) COMMENT '扩展 Float 3', + extend_f4 decimal(19,4) COMMENT '扩展 Float 4', + extend_d1 datetime COMMENT '扩展 Date 1', + extend_d2 datetime COMMENT '扩展 Date 2', + extend_d3 datetime COMMENT '扩展 Date 3', + extend_d4 datetime COMMENT '扩展 Date 4', + PRIMARY KEY (id) +) COMMENT = '文章详情表'; + + +-- 文章推荐位 +CREATE TABLE ${_prefix}cms_article_posid +( + article_id varchar(64) NOT NULL COMMENT '内容编号', + postid char(1) NOT NULL COMMENT '推荐位置(1轮播图 2首页推荐 3栏目页面)' +) COMMENT = '文章推荐位'; + + +-- 文章与标签关系 +CREATE TABLE ${_prefix}cms_article_tag +( + article_id varchar(64) NOT NULL COMMENT '内容编号', + tag_name varchar(200) NOT NULL COMMENT '标签名称' +) COMMENT = '文章与标签关系'; + + +-- 栏目表 +CREATE TABLE ${_prefix}cms_category +( + category_code varchar(64) NOT NULL COMMENT '栏目编码', + parent_code varchar(64) NOT NULL COMMENT '父级编号', + parent_codes varchar(1000) NOT NULL COMMENT '所有父级编号', + tree_sort decimal(10) NOT NULL COMMENT '本级排序号(升序)', + tree_sorts varchar(1000) NOT NULL COMMENT '所有级别排序号', + tree_leaf char(1) NOT NULL COMMENT '是否最末级', + tree_level decimal(4) NOT NULL COMMENT '层次级别', + tree_names varchar(1000) NOT NULL COMMENT '全节点名', + category_name varchar(100) NOT NULL COMMENT '栏目名称', + site_code varchar(64) NOT NULL COMMENT '站点编码', + module_type varchar(50) COMMENT '模块类型', + image varchar(255) COMMENT '栏目图片', + href varchar(255) COMMENT '链接', + target varchar(20) COMMENT '目标', + keywords varchar(500) COMMENT '关键字', + description varchar(500) COMMENT '描述', + in_menu char(1) COMMENT '是否在导航中显示', + in_list char(1) COMMENT '是否在分类页中显示列表', + show_modes char(1) COMMENT '展现模式', + is_need_audit char(1) COMMENT '是否需要审核', + is_can_comment char(1) COMMENT '是否允许评论', + custom_list_view varchar(255) COMMENT '自定义列表视图', + custom_content_view varchar(255) COMMENT '自定义内容视图', + view_config varchar(1000) COMMENT '视图配置', + status char(1) DEFAULT '0' NOT NULL COMMENT '状态(0正常 1删除 2停用)', + create_by varchar(64) NOT NULL COMMENT '创建者', + create_date datetime NOT NULL COMMENT '创建时间', + update_by varchar(64) NOT NULL COMMENT '更新者', + update_date datetime NOT NULL COMMENT '更新时间', + remarks varchar(500) COMMENT '备注信息', + extend_s1 varchar(500) COMMENT '扩展 String 1', + extend_s2 varchar(500) COMMENT '扩展 String 2', + extend_s3 varchar(500) COMMENT '扩展 String 3', + extend_s4 varchar(500) COMMENT '扩展 String 4', + extend_s5 varchar(500) COMMENT '扩展 String 5', + extend_s6 varchar(500) COMMENT '扩展 String 6', + extend_s7 varchar(500) COMMENT '扩展 String 7', + extend_s8 varchar(500) COMMENT '扩展 String 8', + extend_i1 decimal(19) COMMENT '扩展 Integer 1', + extend_i2 decimal(19) COMMENT '扩展 Integer 2', + extend_i3 decimal(19) COMMENT '扩展 Integer 3', + extend_i4 decimal(19) COMMENT '扩展 Integer 4', + extend_f1 decimal(19,4) COMMENT '扩展 Float 1', + extend_f2 decimal(19,4) COMMENT '扩展 Float 2', + extend_f3 decimal(19,4) COMMENT '扩展 Float 3', + extend_f4 decimal(19,4) COMMENT '扩展 Float 4', + extend_d1 datetime COMMENT '扩展 Date 1', + extend_d2 datetime COMMENT '扩展 Date 2', + extend_d3 datetime COMMENT '扩展 Date 3', + extend_d4 datetime COMMENT '扩展 Date 4', + PRIMARY KEY (category_code) +) COMMENT = '栏目表'; + + +-- 栏目与角色关联表 +CREATE TABLE ${_prefix}cms_category_role +( + category_code varchar(64) NOT NULL COMMENT '栏目编码', + role_code varchar(64) NOT NULL COMMENT '角色编码', + ctrl_type varchar(32) COMMENT '控制类型(view查看、edit编辑)', + PRIMARY KEY (category_code, role_code) +) COMMENT = '栏目与角色关联表'; + + +-- 文章评论表 +CREATE TABLE ${_prefix}cms_comment +( + id varchar(64) NOT NULL COMMENT '编号', + category_code varchar(64) NOT NULL COMMENT '栏目编码', + article_id varchar(64) NOT NULL COMMENT '内容编号', + parent_id varchar(64) COMMENT '父级评论', + article_title varchar(255) NOT NULL COMMENT '内容标题', + content varchar(255) NOT NULL COMMENT '评论内容', + name varchar(50) COMMENT '评论姓名', + ip varchar(100) COMMENT '评论IP', + create_by varchar(64) COMMENT '创建者', + create_date datetime NOT NULL COMMENT '创建时间', + audit_user_code varchar(64) COMMENT '审核人', + audit_date datetime COMMENT '审核时间', + audit_comment varchar(200) COMMENT '审核意见', + hits_plus numeric(10) COMMENT '支持数', + hits_minus numeric(10) COMMENT '反对数', + status char(1) NOT NULL COMMENT '状态(0正常 1删除 2停用)', + corp_code varchar(64) DEFAULT '0' NOT NULL COMMENT '租户代码', + corp_name varchar(100) DEFAULT 'JeeSite' NOT NULL COMMENT '租户名称', + PRIMARY KEY (id) +) COMMENT = '文章评论表'; + + +-- 留言板表 +CREATE TABLE ${_prefix}cms_guestbook +( + id varchar(64) NOT NULL COMMENT '编号', + type char(1) NOT NULL COMMENT '留言分类', + content varchar(255) NOT NULL COMMENT '留言内容', + name varchar(100) NOT NULL COMMENT '姓名', + email varchar(100) NOT NULL COMMENT '邮箱', + phone varchar(100) NOT NULL COMMENT '电话', + workunit varchar(100) NOT NULL COMMENT '单位', + ip varchar(100) NOT NULL COMMENT 'IP', + create_by varchar(64) COMMENT '创建者', + create_date datetime COMMENT '创建时间', + re_user_code varchar(64) COMMENT '回复人', + re_date datetime COMMENT '回复时间', + re_content varchar(100) COMMENT '回复内容', + status char(1) NOT NULL COMMENT '状态(0正常 1删除 2停用)', + corp_code varchar(64) DEFAULT '0' NOT NULL COMMENT '租户代码', + corp_name varchar(100) DEFAULT 'JeeSite' NOT NULL COMMENT '租户名称', + PRIMARY KEY (id) +) COMMENT = '留言板表'; + + +-- 内容举报表 +CREATE TABLE ${_prefix}cms_report +( + id varchar(64) NOT NULL COMMENT '编号', + report_source char(1) COMMENT '举报来源(1文章、2评论)', + report_content varchar(500) COMMENT '举报内容(文章标题 评论内容)', + report_url varchar(1000) COMMENT '举报的URL', + report_type char(1) COMMENT '举报类型(色情 政治...)', + report_cause varchar(500) COMMENT '举报原因', + PRIMARY KEY (id) +) COMMENT = '内容举报表'; + + +-- 站点表 +CREATE TABLE ${_prefix}cms_site +( + site_code varchar(64) NOT NULL COMMENT '站点编码', + site_name varchar(100) NOT NULL COMMENT '站点名称', + site_sort decimal(10) COMMENT '站点排序号', + title varchar(100) NOT NULL COMMENT '站点标题', + logo varchar(1000) COMMENT '站点Logo', + domain varchar(500) COMMENT '站点域名', + keywords varchar(500) COMMENT '关键字', + description varchar(500) COMMENT '描述', + theme varchar(500) COMMENT '主题', + copyright varchar(1000) COMMENT '版权信息', + custom_index_view varchar(500) COMMENT '自定义站点首页视图', + status char(1) DEFAULT '0' NOT NULL COMMENT '状态(0正常 1删除 2停用)', + create_by varchar(64) NOT NULL COMMENT '创建者', + create_date datetime NOT NULL COMMENT '创建时间', + update_by varchar(64) NOT NULL COMMENT '更新者', + update_date datetime NOT NULL COMMENT '更新时间', + remarks varchar(500) COMMENT '备注信息', + PRIMARY KEY (site_code) +) COMMENT = '站点表'; + + +-- 内容标签 +CREATE TABLE ${_prefix}cms_tag +( + tag_name varchar(200) NOT NULL COMMENT '标签名称', + clicknum numeric(10) NOT NULL COMMENT '点击次数', + PRIMARY KEY (tag_name) +) COMMENT = '内容标签'; + + +-- 访问日志表 +CREATE TABLE ${_prefix}cms_visit_log +( + id varchar(64) NOT NULL COMMENT '编号', + request_url varchar(1000) COMMENT '请求的URL地址', + request_url_host varchar(128) COMMENT '受访域名', + source_referer varchar(1000) COMMENT '来源页面/上一个页面', + source_referer_host varchar(128) COMMENT '来源域名', + source_type char(1) COMMENT '访问来源类型(1直接访问 2搜索引擎 3外部链接 4内部访问)', + search_engine varchar(200) COMMENT '使用的搜索引擎', + search_word varchar(200) COMMENT '搜索的关键词', + remote_addr varchar(50) COMMENT '客户IP地址', + user_agent varchar(500) COMMENT '用户代理字符串', + user_language varchar(32) COMMENT '客户机语言', + user_screen_size varchar(32) COMMENT '客户机屏幕大小0x0', + user_device varchar(32) COMMENT '客户机设备类型(电脑、平板、手机、未知)', + user_os_name varchar(32) COMMENT '客户机操作系统', + user_browser varchar(32) COMMENT '客户机浏览器', + user_browser_version varchar(16) COMMENT '浏览器版本', + unique_visit_id varchar(64) COMMENT '唯一访问标识', + visit_date char(8) COMMENT '本次访问日期(年月日)', + visit_time datetime COMMENT '本次访问时间', + is_new_visit char(1) COMMENT '是否新访问(30分内)', + first_visit_time decimal(20) COMMENT '首次访问时间戳(30分钟内)', + prev_remain_time decimal(20) COMMENT '上页面停留时间(秒)', + total_remain_time decimal(20) COMMENT '本次访问总停留时间(秒)', + site_code varchar(64) COMMENT '站点编码', + site_name varchar(100) COMMENT '站点名称', + category_code varchar(64) COMMENT '栏目编码', + category_name varchar(100) COMMENT '栏目名称', + content_id varchar(64) COMMENT '栏目内容编号', + content_title varchar(255) COMMENT '访问页面标题', + visit_user_code varchar(100) COMMENT '访问用户编码', + visit_user_name varchar(100) COMMENT '访问用户姓名', + corp_code varchar(64) DEFAULT '0' NOT NULL COMMENT '租户代码', + corp_name varchar(100) DEFAULT 'JeeSite' NOT NULL COMMENT '租户名称', + PRIMARY KEY (id) +) COMMENT = '访问日志表'; + + + +/* Create Indexes */ + +CREATE INDEX idx_cms_article_cb ON ${_prefix}cms_article (create_by ASC); +CREATE INDEX idx_cms_article_cc ON ${_prefix}cms_article (category_code ASC); +CREATE INDEX idx_cms_article_corp_code ON ${_prefix}cms_article (corp_code ASC); +CREATE INDEX idx_cms_article_status ON ${_prefix}cms_article (status ASC); +CREATE INDEX idx_cms_article_ud ON ${_prefix}cms_article (update_date ASC); +CREATE INDEX idx_cms_article_weight ON ${_prefix}cms_article (weight ASC); +CREATE INDEX idx_cms_category_pc ON ${_prefix}cms_category (parent_code ASC); +CREATE INDEX idx_cms_category_ts ON ${_prefix}cms_category (tree_sort ASC); +CREATE INDEX idx_cms_category_status ON ${_prefix}cms_category (status ASC); +CREATE INDEX idx_cms_category_tss ON ${_prefix}cms_category (tree_sorts ASC); +CREATE INDEX idx_cms_comment_catc ON ${_prefix}cms_comment (category_code ASC); +CREATE INDEX idx_cms_comment_ai ON ${_prefix}cms_comment (article_id ASC); +CREATE INDEX idx_cms_comment_cc ON ${_prefix}cms_comment (corp_code ASC); +CREATE INDEX idx_cms_comment_status ON ${_prefix}cms_comment (status ASC); +CREATE INDEX idx_cms_guestbook_cc ON ${_prefix}cms_guestbook (corp_code ASC); +CREATE INDEX idx_cms_guestbook_status ON ${_prefix}cms_guestbook (status ASC); +CREATE INDEX idx_cms_guestbook_type ON ${_prefix}cms_guestbook (type ASC); +CREATE INDEX idx_cms_site_status ON ${_prefix}cms_site (status ASC); +CREATE INDEX cms_visit_log_cc ON ${_prefix}cms_visit_log (category_code ASC); +CREATE INDEX cms_visit_log_ci ON ${_prefix}cms_visit_log (content_id ASC); +CREATE INDEX cms_visit_log_fvt ON ${_prefix}cms_visit_log (first_visit_time ASC); +CREATE INDEX cms_visit_log_inv ON ${_prefix}cms_visit_log (is_new_visit ASC); +CREATE INDEX cms_visit_log_ra ON ${_prefix}cms_visit_log (remote_addr ASC); +CREATE INDEX cms_visit_log_sc ON ${_prefix}cms_visit_log (site_code ASC); +CREATE INDEX cms_visit_log_uvid ON ${_prefix}cms_visit_log (unique_visit_id ASC); +CREATE INDEX cms_visit_log_vd ON ${_prefix}cms_visit_log (visit_date ASC); +CREATE INDEX cms_visit_log_vt ON ${_prefix}cms_visit_log (visit_time ASC); +CREATE INDEX idx_cms_visit_log_corpc ON ${_prefix}cms_visit_log (corp_code ASC); + + + diff --git a/modules/cms/src/main/resources/db/create/oracle/cms.sql b/modules/cms/src/main/resources/db/create/oracle/cms.sql new file mode 100644 index 00000000..56005f2c --- /dev/null +++ b/modules/cms/src/main/resources/db/create/oracle/cms.sql @@ -0,0 +1,537 @@ + + +/* Create Tables */ + +-- 文章表 +CREATE TABLE ${_prefix}cms_article +( + id varchar2(64) NOT NULL, + category_code varchar2(64) NOT NULL, + module_type varchar2(50), + title nvarchar2(255) NOT NULL, + href nvarchar2(1000), + color varchar2(50), + image nvarchar2(1000), + keywords nvarchar2(500), + description nvarchar2(500), + weight number(10) DEFAULT 0, + weight_date timestamp, + source char(1), + copyfrom nvarchar2(255), + hits number(20) DEFAULT 0, + hits_plus number(10), + hits_minus number(10), + word_count number(10), + custom_content_view varchar2(255), + view_config nvarchar2(1000), + status char(1) DEFAULT '0' NOT NULL, + create_by varchar2(64) NOT NULL, + create_date timestamp NOT NULL, + update_by varchar2(64) NOT NULL, + update_date timestamp NOT NULL, + remarks nvarchar2(500), + corp_code varchar2(64) DEFAULT '0' NOT NULL, + corp_name nvarchar2(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +); + + +-- 文章详情表 +CREATE TABLE ${_prefix}cms_article_data +( + id varchar2(64) NOT NULL, + content clob, + relation varchar2(1000), + is_can_comment char(1), + extend_s1 nvarchar2(500), + extend_s2 nvarchar2(500), + extend_s3 nvarchar2(500), + extend_s4 nvarchar2(500), + extend_s5 nvarchar2(500), + extend_s6 nvarchar2(500), + extend_s7 nvarchar2(500), + extend_s8 nvarchar2(500), + extend_i1 number(19), + extend_i2 number(19), + extend_i3 number(19), + extend_i4 number(19), + extend_f1 number(19,4), + extend_f2 number(19,4), + extend_f3 number(19,4), + extend_f4 number(19,4), + extend_d1 timestamp, + extend_d2 timestamp, + extend_d3 timestamp, + extend_d4 timestamp, + PRIMARY KEY (id) +); + + +-- 文章推荐位 +CREATE TABLE ${_prefix}cms_article_posid +( + article_id varchar2(64) NOT NULL, + postid char(1) NOT NULL +); + + +-- 文章与标签关系 +CREATE TABLE ${_prefix}cms_article_tag +( + article_id varchar2(64) NOT NULL, + tag_name nvarchar2(200) NOT NULL +); + + +-- 栏目表 +CREATE TABLE ${_prefix}cms_category +( + category_code varchar2(64) NOT NULL, + parent_code varchar2(64) NOT NULL, + parent_codes varchar2(1000) NOT NULL, + tree_sort number(10) NOT NULL, + tree_sorts varchar2(1000) NOT NULL, + tree_leaf char(1) NOT NULL, + tree_level number(4) NOT NULL, + tree_names nvarchar2(1000) NOT NULL, + category_name nvarchar2(100) NOT NULL, + site_code varchar2(64) NOT NULL, + module_type varchar2(50), + image varchar2(255), + href varchar2(255), + target varchar2(20), + keywords nvarchar2(500), + description nvarchar2(500), + in_menu char(1), + in_list char(1), + show_modes char(1), + is_need_audit char(1), + is_can_comment char(1), + custom_list_view varchar2(255), + custom_content_view varchar2(255), + view_config nvarchar2(1000), + status char(1) DEFAULT '0' NOT NULL, + create_by varchar2(64) NOT NULL, + create_date timestamp NOT NULL, + update_by varchar2(64) NOT NULL, + update_date timestamp NOT NULL, + remarks nvarchar2(500), + extend_s1 nvarchar2(500), + extend_s2 nvarchar2(500), + extend_s3 nvarchar2(500), + extend_s4 nvarchar2(500), + extend_s5 nvarchar2(500), + extend_s6 nvarchar2(500), + extend_s7 nvarchar2(500), + extend_s8 nvarchar2(500), + extend_i1 number(19), + extend_i2 number(19), + extend_i3 number(19), + extend_i4 number(19), + extend_f1 number(19,4), + extend_f2 number(19,4), + extend_f3 number(19,4), + extend_f4 number(19,4), + extend_d1 timestamp, + extend_d2 timestamp, + extend_d3 timestamp, + extend_d4 timestamp, + PRIMARY KEY (category_code) +); + + +-- 栏目与角色关联表 +CREATE TABLE ${_prefix}cms_category_role +( + category_code varchar2(64) NOT NULL, + role_code varchar2(64) NOT NULL, + ctrl_type varchar2(32), + PRIMARY KEY (category_code, role_code) +); + + +-- 文章评论表 +CREATE TABLE ${_prefix}cms_comment +( + id varchar2(64) NOT NULL, + category_code varchar2(64) NOT NULL, + article_id varchar2(64) NOT NULL, + parent_id varchar2(64), + article_title nvarchar2(255) NOT NULL, + content nvarchar2(255) NOT NULL, + name nvarchar2(50), + ip varchar2(100), + create_by varchar2(64), + create_date timestamp NOT NULL, + audit_user_code varchar2(64), + audit_date timestamp, + audit_comment nvarchar2(200), + hits_plus number(10), + hits_minus number(10), + status char(1) NOT NULL, + corp_code varchar2(64) DEFAULT '0' NOT NULL, + corp_name nvarchar2(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +); + + +-- 留言板表 +CREATE TABLE ${_prefix}cms_guestbook +( + id varchar2(64) NOT NULL, + type char(1) NOT NULL, + content varchar2(255) NOT NULL, + name varchar2(100) NOT NULL, + email varchar2(100) NOT NULL, + phone varchar2(100) NOT NULL, + workunit varchar2(100) NOT NULL, + ip varchar2(100) NOT NULL, + create_by varchar2(64), + create_date timestamp, + re_user_code varchar2(64), + re_date timestamp, + re_content varchar2(100), + status char(1) NOT NULL, + corp_code varchar2(64) DEFAULT '0' NOT NULL, + corp_name nvarchar2(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +); + + +-- 内容举报表 +CREATE TABLE ${_prefix}cms_report +( + id varchar2(64) NOT NULL, + report_source char(1), + report_content nvarchar2(500), + report_url nvarchar2(1000), + report_type char(1), + report_cause nvarchar2(500), + PRIMARY KEY (id) +); + + +-- 站点表 +CREATE TABLE ${_prefix}cms_site +( + site_code varchar2(64) NOT NULL, + site_name nvarchar2(100) NOT NULL, + site_sort number(10), + title nvarchar2(100) NOT NULL, + logo nvarchar2(1000), + domain nvarchar2(500), + keywords nvarchar2(500), + description nvarchar2(500), + theme nvarchar2(500), + copyright nvarchar2(1000), + custom_index_view varchar2(500), + status char(1) DEFAULT '0' NOT NULL, + create_by varchar2(64) NOT NULL, + create_date timestamp NOT NULL, + update_by varchar2(64) NOT NULL, + update_date timestamp NOT NULL, + remarks nvarchar2(500), + PRIMARY KEY (site_code) +); + + +-- 内容标签 +CREATE TABLE ${_prefix}cms_tag +( + tag_name nvarchar2(200) NOT NULL, + clicknum number(10) NOT NULL, + PRIMARY KEY (tag_name) +); + + +-- 访问日志表 +CREATE TABLE ${_prefix}cms_visit_log +( + id varchar2(64) NOT NULL, + request_url nvarchar2(1000), + request_url_host varchar2(128), + source_referer nvarchar2(1000), + source_referer_host varchar2(128), + source_type char(1), + search_engine varchar2(200), + search_word nvarchar2(200), + remote_addr varchar2(50), + user_agent nvarchar2(500), + user_language varchar2(32), + user_screen_size varchar2(32), + user_device varchar2(32), + user_os_name varchar2(32), + user_browser varchar2(32), + user_browser_version varchar2(16), + unique_visit_id varchar2(64), + visit_date char(8), + visit_time timestamp, + is_new_visit char(1), + first_visit_time number(20), + prev_remain_time number(20), + total_remain_time number(20), + site_code varchar2(64), + site_name nvarchar2(100), + category_code varchar2(64), + category_name nvarchar2(100), + content_id varchar2(64), + content_title nvarchar2(255), + visit_user_code varchar2(100), + visit_user_name varchar2(100), + corp_code varchar2(64) DEFAULT '0' NOT NULL, + corp_name nvarchar2(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +); + + + +/* Create Indexes */ + +CREATE INDEX idx_cms_article_cb ON ${_prefix}cms_article (create_by); +CREATE INDEX idx_cms_article_cc ON ${_prefix}cms_article (category_code); +CREATE INDEX idx_cms_article_corp_code ON ${_prefix}cms_article (corp_code); +CREATE INDEX idx_cms_article_status ON ${_prefix}cms_article (status); +CREATE INDEX idx_cms_article_ud ON ${_prefix}cms_article (update_date); +CREATE INDEX idx_cms_article_weight ON ${_prefix}cms_article (weight); +CREATE INDEX idx_cms_category_pc ON ${_prefix}cms_category (parent_code); +CREATE INDEX idx_cms_category_ts ON ${_prefix}cms_category (tree_sort); +CREATE INDEX idx_cms_category_status ON ${_prefix}cms_category (status); +CREATE INDEX idx_cms_category_tss ON ${_prefix}cms_category (tree_sorts); +CREATE INDEX idx_cms_comment_catc ON ${_prefix}cms_comment (category_code); +CREATE INDEX idx_cms_comment_ai ON ${_prefix}cms_comment (article_id); +CREATE INDEX idx_cms_comment_cc ON ${_prefix}cms_comment (corp_code); +CREATE INDEX idx_cms_comment_status ON ${_prefix}cms_comment (status); +CREATE INDEX idx_cms_guestbook_cc ON ${_prefix}cms_guestbook (corp_code); +CREATE INDEX idx_cms_guestbook_status ON ${_prefix}cms_guestbook (status); +CREATE INDEX idx_cms_guestbook_type ON ${_prefix}cms_guestbook (type); +CREATE INDEX idx_cms_site_status ON ${_prefix}cms_site (status); +CREATE INDEX cms_visit_log_cc ON ${_prefix}cms_visit_log (category_code); +CREATE INDEX cms_visit_log_ci ON ${_prefix}cms_visit_log (content_id); +CREATE INDEX cms_visit_log_fvt ON ${_prefix}cms_visit_log (first_visit_time); +CREATE INDEX cms_visit_log_inv ON ${_prefix}cms_visit_log (is_new_visit); +CREATE INDEX cms_visit_log_ra ON ${_prefix}cms_visit_log (remote_addr); +CREATE INDEX cms_visit_log_sc ON ${_prefix}cms_visit_log (site_code); +CREATE INDEX cms_visit_log_uvid ON ${_prefix}cms_visit_log (unique_visit_id); +CREATE INDEX cms_visit_log_vd ON ${_prefix}cms_visit_log (visit_date); +CREATE INDEX cms_visit_log_vt ON ${_prefix}cms_visit_log (visit_time); +CREATE INDEX idx_cms_visit_log_corpc ON ${_prefix}cms_visit_log (corp_code); + + + +/* Comments */ + +COMMENT ON TABLE ${_prefix}cms_article IS '文章表'; +COMMENT ON COLUMN ${_prefix}cms_article.id IS '编号'; +COMMENT ON COLUMN ${_prefix}cms_article.category_code IS '栏目编码'; +COMMENT ON COLUMN ${_prefix}cms_article.module_type IS '模块类型'; +COMMENT ON COLUMN ${_prefix}cms_article.title IS '内容标题'; +COMMENT ON COLUMN ${_prefix}cms_article.href IS '外部链接'; +COMMENT ON COLUMN ${_prefix}cms_article.color IS '标题颜色'; +COMMENT ON COLUMN ${_prefix}cms_article.image IS '内容图片'; +COMMENT ON COLUMN ${_prefix}cms_article.keywords IS '关键字'; +COMMENT ON COLUMN ${_prefix}cms_article.description IS '描述'; +COMMENT ON COLUMN ${_prefix}cms_article.weight IS '权重,越大越靠前'; +COMMENT ON COLUMN ${_prefix}cms_article.weight_date IS '权重期限'; +COMMENT ON COLUMN ${_prefix}cms_article.source IS '来源(转载/原创)'; +COMMENT ON COLUMN ${_prefix}cms_article.copyfrom IS '文章来源出处'; +COMMENT ON COLUMN ${_prefix}cms_article.hits IS '点击数'; +COMMENT ON COLUMN ${_prefix}cms_article.hits_plus IS '支持数'; +COMMENT ON COLUMN ${_prefix}cms_article.hits_minus IS '反对数'; +COMMENT ON COLUMN ${_prefix}cms_article.word_count IS '字数(不包含html)'; +COMMENT ON COLUMN ${_prefix}cms_article.custom_content_view IS '自定义内容视图'; +COMMENT ON COLUMN ${_prefix}cms_article.view_config IS '视图配置'; +COMMENT ON COLUMN ${_prefix}cms_article.status IS '状态(0正常 1删除 2停用)'; +COMMENT ON COLUMN ${_prefix}cms_article.create_by IS '创建者'; +COMMENT ON COLUMN ${_prefix}cms_article.create_date IS '创建时间'; +COMMENT ON COLUMN ${_prefix}cms_article.update_by IS '更新者'; +COMMENT ON COLUMN ${_prefix}cms_article.update_date IS '更新时间'; +COMMENT ON COLUMN ${_prefix}cms_article.remarks IS '备注信息'; +COMMENT ON COLUMN ${_prefix}cms_article.corp_code IS '租户代码'; +COMMENT ON COLUMN ${_prefix}cms_article.corp_name IS '租户名称'; +COMMENT ON TABLE ${_prefix}cms_article_data IS '文章详情表'; +COMMENT ON COLUMN ${_prefix}cms_article_data.id IS '编号'; +COMMENT ON COLUMN ${_prefix}cms_article_data.content IS '文章内容'; +COMMENT ON COLUMN ${_prefix}cms_article_data.relation IS '相关文章'; +COMMENT ON COLUMN ${_prefix}cms_article_data.is_can_comment IS '是否允许评论'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_s1 IS '扩展 String 1'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_s2 IS '扩展 String 2'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_s3 IS '扩展 String 3'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_s4 IS '扩展 String 4'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_s5 IS '扩展 String 5'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_s6 IS '扩展 String 6'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_s7 IS '扩展 String 7'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_s8 IS '扩展 String 8'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_i1 IS '扩展 Integer 1'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_i2 IS '扩展 Integer 2'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_i3 IS '扩展 Integer 3'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_i4 IS '扩展 Integer 4'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_f1 IS '扩展 Float 1'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_f2 IS '扩展 Float 2'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_f3 IS '扩展 Float 3'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_f4 IS '扩展 Float 4'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_d1 IS '扩展 Date 1'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_d2 IS '扩展 Date 2'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_d3 IS '扩展 Date 3'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_d4 IS '扩展 Date 4'; +COMMENT ON TABLE ${_prefix}cms_article_posid IS '文章推荐位'; +COMMENT ON COLUMN ${_prefix}cms_article_posid.article_id IS '内容编号'; +COMMENT ON COLUMN ${_prefix}cms_article_posid.postid IS '推荐位置(1轮播图 2首页推荐 3栏目页面)'; +COMMENT ON TABLE ${_prefix}cms_article_tag IS '文章与标签关系'; +COMMENT ON COLUMN ${_prefix}cms_article_tag.article_id IS '内容编号'; +COMMENT ON COLUMN ${_prefix}cms_article_tag.tag_name IS '标签名称'; +COMMENT ON TABLE ${_prefix}cms_category IS '栏目表'; +COMMENT ON COLUMN ${_prefix}cms_category.category_code IS '栏目编码'; +COMMENT ON COLUMN ${_prefix}cms_category.parent_code IS '父级编号'; +COMMENT ON COLUMN ${_prefix}cms_category.parent_codes IS '所有父级编号'; +COMMENT ON COLUMN ${_prefix}cms_category.tree_sort IS '本级排序号(升序)'; +COMMENT ON COLUMN ${_prefix}cms_category.tree_sorts IS '所有级别排序号'; +COMMENT ON COLUMN ${_prefix}cms_category.tree_leaf IS '是否最末级'; +COMMENT ON COLUMN ${_prefix}cms_category.tree_level IS '层次级别'; +COMMENT ON COLUMN ${_prefix}cms_category.tree_names IS '全节点名'; +COMMENT ON COLUMN ${_prefix}cms_category.category_name IS '栏目名称'; +COMMENT ON COLUMN ${_prefix}cms_category.site_code IS '站点编码'; +COMMENT ON COLUMN ${_prefix}cms_category.module_type IS '模块类型'; +COMMENT ON COLUMN ${_prefix}cms_category.image IS '栏目图片'; +COMMENT ON COLUMN ${_prefix}cms_category.href IS '链接'; +COMMENT ON COLUMN ${_prefix}cms_category.target IS '目标'; +COMMENT ON COLUMN ${_prefix}cms_category.keywords IS '关键字'; +COMMENT ON COLUMN ${_prefix}cms_category.description IS '描述'; +COMMENT ON COLUMN ${_prefix}cms_category.in_menu IS '是否在导航中显示'; +COMMENT ON COLUMN ${_prefix}cms_category.in_list IS '是否在分类页中显示列表'; +COMMENT ON COLUMN ${_prefix}cms_category.show_modes IS '展现模式'; +COMMENT ON COLUMN ${_prefix}cms_category.is_need_audit IS '是否需要审核'; +COMMENT ON COLUMN ${_prefix}cms_category.is_can_comment IS '是否允许评论'; +COMMENT ON COLUMN ${_prefix}cms_category.custom_list_view IS '自定义列表视图'; +COMMENT ON COLUMN ${_prefix}cms_category.custom_content_view IS '自定义内容视图'; +COMMENT ON COLUMN ${_prefix}cms_category.view_config IS '视图配置'; +COMMENT ON COLUMN ${_prefix}cms_category.status IS '状态(0正常 1删除 2停用)'; +COMMENT ON COLUMN ${_prefix}cms_category.create_by IS '创建者'; +COMMENT ON COLUMN ${_prefix}cms_category.create_date IS '创建时间'; +COMMENT ON COLUMN ${_prefix}cms_category.update_by IS '更新者'; +COMMENT ON COLUMN ${_prefix}cms_category.update_date IS '更新时间'; +COMMENT ON COLUMN ${_prefix}cms_category.remarks IS '备注信息'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_s1 IS '扩展 String 1'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_s2 IS '扩展 String 2'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_s3 IS '扩展 String 3'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_s4 IS '扩展 String 4'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_s5 IS '扩展 String 5'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_s6 IS '扩展 String 6'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_s7 IS '扩展 String 7'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_s8 IS '扩展 String 8'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_i1 IS '扩展 Integer 1'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_i2 IS '扩展 Integer 2'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_i3 IS '扩展 Integer 3'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_i4 IS '扩展 Integer 4'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_f1 IS '扩展 Float 1'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_f2 IS '扩展 Float 2'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_f3 IS '扩展 Float 3'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_f4 IS '扩展 Float 4'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_d1 IS '扩展 Date 1'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_d2 IS '扩展 Date 2'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_d3 IS '扩展 Date 3'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_d4 IS '扩展 Date 4'; +COMMENT ON TABLE ${_prefix}cms_category_role IS '栏目与角色关联表'; +COMMENT ON COLUMN ${_prefix}cms_category_role.category_code IS '栏目编码'; +COMMENT ON COLUMN ${_prefix}cms_category_role.role_code IS '角色编码'; +COMMENT ON COLUMN ${_prefix}cms_category_role.ctrl_type IS '控制类型(view查看、edit编辑)'; +COMMENT ON TABLE ${_prefix}cms_comment IS '文章评论表'; +COMMENT ON COLUMN ${_prefix}cms_comment.id IS '编号'; +COMMENT ON COLUMN ${_prefix}cms_comment.category_code IS '栏目编码'; +COMMENT ON COLUMN ${_prefix}cms_comment.article_id IS '内容编号'; +COMMENT ON COLUMN ${_prefix}cms_comment.parent_id IS '父级评论'; +COMMENT ON COLUMN ${_prefix}cms_comment.article_title IS '内容标题'; +COMMENT ON COLUMN ${_prefix}cms_comment.content IS '评论内容'; +COMMENT ON COLUMN ${_prefix}cms_comment.name IS '评论姓名'; +COMMENT ON COLUMN ${_prefix}cms_comment.ip IS '评论IP'; +COMMENT ON COLUMN ${_prefix}cms_comment.create_by IS '创建者'; +COMMENT ON COLUMN ${_prefix}cms_comment.create_date IS '创建时间'; +COMMENT ON COLUMN ${_prefix}cms_comment.audit_user_code IS '审核人'; +COMMENT ON COLUMN ${_prefix}cms_comment.audit_date IS '审核时间'; +COMMENT ON COLUMN ${_prefix}cms_comment.audit_comment IS '审核意见'; +COMMENT ON COLUMN ${_prefix}cms_comment.hits_plus IS '支持数'; +COMMENT ON COLUMN ${_prefix}cms_comment.hits_minus IS '反对数'; +COMMENT ON COLUMN ${_prefix}cms_comment.status IS '状态(0正常 1删除 2停用)'; +COMMENT ON COLUMN ${_prefix}cms_comment.corp_code IS '租户代码'; +COMMENT ON COLUMN ${_prefix}cms_comment.corp_name IS '租户名称'; +COMMENT ON TABLE ${_prefix}cms_guestbook IS '留言板表'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.id IS '编号'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.type IS '留言分类'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.content IS '留言内容'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.name IS '姓名'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.email IS '邮箱'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.phone IS '电话'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.workunit IS '单位'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.ip IS 'IP'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.create_by IS '创建者'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.create_date IS '创建时间'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.re_user_code IS '回复人'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.re_date IS '回复时间'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.re_content IS '回复内容'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.status IS '状态(0正常 1删除 2停用)'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.corp_code IS '租户代码'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.corp_name IS '租户名称'; +COMMENT ON TABLE ${_prefix}cms_report IS '内容举报表'; +COMMENT ON COLUMN ${_prefix}cms_report.id IS '编号'; +COMMENT ON COLUMN ${_prefix}cms_report.report_source IS '举报来源(1文章、2评论)'; +COMMENT ON COLUMN ${_prefix}cms_report.report_content IS '举报内容(文章标题 评论内容)'; +COMMENT ON COLUMN ${_prefix}cms_report.report_url IS '举报的URL'; +COMMENT ON COLUMN ${_prefix}cms_report.report_type IS '举报类型(色情 政治...)'; +COMMENT ON COLUMN ${_prefix}cms_report.report_cause IS '举报原因'; +COMMENT ON TABLE ${_prefix}cms_site IS '站点表'; +COMMENT ON COLUMN ${_prefix}cms_site.site_code IS '站点编码'; +COMMENT ON COLUMN ${_prefix}cms_site.site_name IS '站点名称'; +COMMENT ON COLUMN ${_prefix}cms_site.site_sort IS '站点排序号'; +COMMENT ON COLUMN ${_prefix}cms_site.title IS '站点标题'; +COMMENT ON COLUMN ${_prefix}cms_site.logo IS '站点Logo'; +COMMENT ON COLUMN ${_prefix}cms_site.domain IS '站点域名'; +COMMENT ON COLUMN ${_prefix}cms_site.keywords IS '关键字'; +COMMENT ON COLUMN ${_prefix}cms_site.description IS '描述'; +COMMENT ON COLUMN ${_prefix}cms_site.theme IS '主题'; +COMMENT ON COLUMN ${_prefix}cms_site.copyright IS '版权信息'; +COMMENT ON COLUMN ${_prefix}cms_site.custom_index_view IS '自定义站点首页视图'; +COMMENT ON COLUMN ${_prefix}cms_site.status IS '状态(0正常 1删除 2停用)'; +COMMENT ON COLUMN ${_prefix}cms_site.create_by IS '创建者'; +COMMENT ON COLUMN ${_prefix}cms_site.create_date IS '创建时间'; +COMMENT ON COLUMN ${_prefix}cms_site.update_by IS '更新者'; +COMMENT ON COLUMN ${_prefix}cms_site.update_date IS '更新时间'; +COMMENT ON COLUMN ${_prefix}cms_site.remarks IS '备注信息'; +COMMENT ON TABLE ${_prefix}cms_tag IS '内容标签'; +COMMENT ON COLUMN ${_prefix}cms_tag.tag_name IS '标签名称'; +COMMENT ON COLUMN ${_prefix}cms_tag.clicknum IS '点击次数'; +COMMENT ON TABLE ${_prefix}cms_visit_log IS '访问日志表'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.id IS '编号'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.request_url IS '请求的URL地址'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.request_url_host IS '受访域名'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.source_referer IS '来源页面/上一个页面'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.source_referer_host IS '来源域名'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.source_type IS '访问来源类型(1直接访问 2搜索引擎 3外部链接 4内部访问)'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.search_engine IS '使用的搜索引擎'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.search_word IS '搜索的关键词'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.remote_addr IS '客户IP地址'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.user_agent IS '用户代理字符串'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.user_language IS '客户机语言'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.user_screen_size IS '客户机屏幕大小0x0'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.user_device IS '客户机设备类型(电脑、平板、手机、未知)'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.user_os_name IS '客户机操作系统'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.user_browser IS '客户机浏览器'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.user_browser_version IS '浏览器版本'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.unique_visit_id IS '唯一访问标识'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.visit_date IS '本次访问日期(年月日)'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.visit_time IS '本次访问时间'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.is_new_visit IS '是否新访问(30分内)'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.first_visit_time IS '首次访问时间戳(30分钟内)'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.prev_remain_time IS '上页面停留时间(秒)'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.total_remain_time IS '本次访问总停留时间(秒)'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.site_code IS '站点编码'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.site_name IS '站点名称'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.category_code IS '栏目编码'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.category_name IS '栏目名称'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.content_id IS '栏目内容编号'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.content_title IS '访问页面标题'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.visit_user_code IS '访问用户编码'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.visit_user_name IS '访问用户姓名'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.corp_code IS '租户代码'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.corp_name IS '租户名称'; + + + diff --git a/modules/cms/src/main/resources/db/create/postgresql/cms.sql b/modules/cms/src/main/resources/db/create/postgresql/cms.sql new file mode 100644 index 00000000..a0030212 --- /dev/null +++ b/modules/cms/src/main/resources/db/create/postgresql/cms.sql @@ -0,0 +1,537 @@ + + +/* Create Tables */ + +-- 文章表 +CREATE TABLE ${_prefix}cms_article +( + id varchar(64) NOT NULL, + category_code varchar(64) NOT NULL, + module_type varchar(50), + title varchar(255) NOT NULL, + href varchar(1000), + color varchar(50), + image varchar(1000), + keywords varchar(500), + description varchar(500), + weight decimal(10) DEFAULT 0, + weight_date timestamp, + source char(1), + copyfrom varchar(255), + hits decimal(20) DEFAULT 0, + hits_plus numeric(10), + hits_minus numeric(10), + word_count numeric(10), + custom_content_view varchar(255), + view_config varchar(1000), + status char(1) DEFAULT '0' NOT NULL, + create_by varchar(64) NOT NULL, + create_date timestamp NOT NULL, + update_by varchar(64) NOT NULL, + update_date timestamp NOT NULL, + remarks varchar(500), + corp_code varchar(64) DEFAULT '0' NOT NULL, + corp_name varchar(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +) WITHOUT OIDS; + + +-- 文章详情表 +CREATE TABLE ${_prefix}cms_article_data +( + id varchar(64) NOT NULL, + content text, + relation varchar(1000), + is_can_comment char(1), + extend_s1 varchar(500), + extend_s2 varchar(500), + extend_s3 varchar(500), + extend_s4 varchar(500), + extend_s5 varchar(500), + extend_s6 varchar(500), + extend_s7 varchar(500), + extend_s8 varchar(500), + extend_i1 decimal(19), + extend_i2 decimal(19), + extend_i3 decimal(19), + extend_i4 decimal(19), + extend_f1 decimal(19,4), + extend_f2 decimal(19,4), + extend_f3 decimal(19,4), + extend_f4 decimal(19,4), + extend_d1 timestamp, + extend_d2 timestamp, + extend_d3 timestamp, + extend_d4 timestamp, + PRIMARY KEY (id) +) WITHOUT OIDS; + + +-- 文章推荐位 +CREATE TABLE ${_prefix}cms_article_posid +( + article_id varchar(64) NOT NULL, + postid char(1) NOT NULL +) WITHOUT OIDS; + + +-- 文章与标签关系 +CREATE TABLE ${_prefix}cms_article_tag +( + article_id varchar(64) NOT NULL, + tag_name varchar(200) NOT NULL +) WITHOUT OIDS; + + +-- 栏目表 +CREATE TABLE ${_prefix}cms_category +( + category_code varchar(64) NOT NULL, + parent_code varchar(64) NOT NULL, + parent_codes varchar(1000) NOT NULL, + tree_sort decimal(10) NOT NULL, + tree_sorts varchar(1000) NOT NULL, + tree_leaf char(1) NOT NULL, + tree_level decimal(4) NOT NULL, + tree_names varchar(1000) NOT NULL, + category_name varchar(100) NOT NULL, + site_code varchar(64) NOT NULL, + module_type varchar(50), + image varchar(255), + href varchar(255), + target varchar(20), + keywords varchar(500), + description varchar(500), + in_menu char(1), + in_list char(1), + show_modes char(1), + is_need_audit char(1), + is_can_comment char(1), + custom_list_view varchar(255), + custom_content_view varchar(255), + view_config varchar(1000), + status char(1) DEFAULT '0' NOT NULL, + create_by varchar(64) NOT NULL, + create_date timestamp NOT NULL, + update_by varchar(64) NOT NULL, + update_date timestamp NOT NULL, + remarks varchar(500), + extend_s1 varchar(500), + extend_s2 varchar(500), + extend_s3 varchar(500), + extend_s4 varchar(500), + extend_s5 varchar(500), + extend_s6 varchar(500), + extend_s7 varchar(500), + extend_s8 varchar(500), + extend_i1 decimal(19), + extend_i2 decimal(19), + extend_i3 decimal(19), + extend_i4 decimal(19), + extend_f1 decimal(19,4), + extend_f2 decimal(19,4), + extend_f3 decimal(19,4), + extend_f4 decimal(19,4), + extend_d1 timestamp, + extend_d2 timestamp, + extend_d3 timestamp, + extend_d4 timestamp, + PRIMARY KEY (category_code) +) WITHOUT OIDS; + + +-- 栏目与角色关联表 +CREATE TABLE ${_prefix}cms_category_role +( + category_code varchar(64) NOT NULL, + role_code varchar(64) NOT NULL, + ctrl_type varchar(32), + PRIMARY KEY (category_code, role_code) +) WITHOUT OIDS; + + +-- 文章评论表 +CREATE TABLE ${_prefix}cms_comment +( + id varchar(64) NOT NULL, + category_code varchar(64) NOT NULL, + article_id varchar(64) NOT NULL, + parent_id varchar(64), + article_title varchar(255) NOT NULL, + content varchar(255) NOT NULL, + name varchar(50), + ip varchar(100), + create_by varchar(64), + create_date timestamp NOT NULL, + audit_user_code varchar(64), + audit_date timestamp, + audit_comment varchar(200), + hits_plus numeric(10), + hits_minus numeric(10), + status char(1) NOT NULL, + corp_code varchar(64) DEFAULT '0' NOT NULL, + corp_name varchar(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +) WITHOUT OIDS; + + +-- 留言板表 +CREATE TABLE ${_prefix}cms_guestbook +( + id varchar(64) NOT NULL, + type char(1) NOT NULL, + content varchar(255) NOT NULL, + name varchar(100) NOT NULL, + email varchar(100) NOT NULL, + phone varchar(100) NOT NULL, + workunit varchar(100) NOT NULL, + ip varchar(100) NOT NULL, + create_by varchar(64), + create_date timestamp, + re_user_code varchar(64), + re_date timestamp, + re_content varchar(100), + status char(1) NOT NULL, + corp_code varchar(64) DEFAULT '0' NOT NULL, + corp_name varchar(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +) WITHOUT OIDS; + + +-- 内容举报表 +CREATE TABLE ${_prefix}cms_report +( + id varchar(64) NOT NULL, + report_source char(1), + report_content varchar(500), + report_url varchar(1000), + report_type char(1), + report_cause varchar(500), + PRIMARY KEY (id) +) WITHOUT OIDS; + + +-- 站点表 +CREATE TABLE ${_prefix}cms_site +( + site_code varchar(64) NOT NULL, + site_name varchar(100) NOT NULL, + site_sort decimal(10), + title varchar(100) NOT NULL, + logo varchar(1000), + domain varchar(500), + keywords varchar(500), + description varchar(500), + theme varchar(500), + copyright varchar(1000), + custom_index_view varchar(500), + status char(1) DEFAULT '0' NOT NULL, + create_by varchar(64) NOT NULL, + create_date timestamp NOT NULL, + update_by varchar(64) NOT NULL, + update_date timestamp NOT NULL, + remarks varchar(500), + PRIMARY KEY (site_code) +) WITHOUT OIDS; + + +-- 内容标签 +CREATE TABLE ${_prefix}cms_tag +( + tag_name varchar(200) NOT NULL, + clicknum numeric(10) NOT NULL, + PRIMARY KEY (tag_name) +) WITHOUT OIDS; + + +-- 访问日志表 +CREATE TABLE ${_prefix}cms_visit_log +( + id varchar(64) NOT NULL, + request_url varchar(1000), + request_url_host varchar(128), + source_referer varchar(1000), + source_referer_host varchar(128), + source_type char(1), + search_engine varchar(200), + search_word varchar(200), + remote_addr varchar(50), + user_agent varchar(500), + user_language varchar(32), + user_screen_size varchar(32), + user_device varchar(32), + user_os_name varchar(32), + user_browser varchar(32), + user_browser_version varchar(16), + unique_visit_id varchar(64), + visit_date char(8), + visit_time timestamp, + is_new_visit char(1), + first_visit_time decimal(20), + prev_remain_time decimal(20), + total_remain_time decimal(20), + site_code varchar(64), + site_name varchar(100), + category_code varchar(64), + category_name varchar(100), + content_id varchar(64), + content_title varchar(255), + visit_user_code varchar(100), + visit_user_name varchar(100), + corp_code varchar(64) DEFAULT '0' NOT NULL, + corp_name varchar(100) DEFAULT 'JeeSite' NOT NULL, + PRIMARY KEY (id) +) WITHOUT OIDS; + + + +/* Create Indexes */ + +CREATE INDEX idx_cms_article_cb ON ${_prefix}cms_article (create_by); +CREATE INDEX idx_cms_article_cc ON ${_prefix}cms_article (category_code); +CREATE INDEX idx_cms_article_corp_code ON ${_prefix}cms_article (corp_code); +CREATE INDEX idx_cms_article_status ON ${_prefix}cms_article (status); +CREATE INDEX idx_cms_article_ud ON ${_prefix}cms_article (update_date); +CREATE INDEX idx_cms_article_weight ON ${_prefix}cms_article (weight); +CREATE INDEX idx_cms_category_pc ON ${_prefix}cms_category (parent_code); +CREATE INDEX idx_cms_category_ts ON ${_prefix}cms_category (tree_sort); +CREATE INDEX idx_cms_category_status ON ${_prefix}cms_category (status); +CREATE INDEX idx_cms_category_tss ON ${_prefix}cms_category (tree_sorts); +CREATE INDEX idx_cms_comment_catc ON ${_prefix}cms_comment (category_code); +CREATE INDEX idx_cms_comment_ai ON ${_prefix}cms_comment (article_id); +CREATE INDEX idx_cms_comment_cc ON ${_prefix}cms_comment (corp_code); +CREATE INDEX idx_cms_comment_status ON ${_prefix}cms_comment (status); +CREATE INDEX idx_cms_guestbook_cc ON ${_prefix}cms_guestbook (corp_code); +CREATE INDEX idx_cms_guestbook_status ON ${_prefix}cms_guestbook (status); +CREATE INDEX idx_cms_guestbook_type ON ${_prefix}cms_guestbook (type); +CREATE INDEX idx_cms_site_status ON ${_prefix}cms_site (status); +CREATE INDEX cms_visit_log_cc ON ${_prefix}cms_visit_log (category_code); +CREATE INDEX cms_visit_log_ci ON ${_prefix}cms_visit_log (content_id); +CREATE INDEX cms_visit_log_fvt ON ${_prefix}cms_visit_log (first_visit_time); +CREATE INDEX cms_visit_log_inv ON ${_prefix}cms_visit_log (is_new_visit); +CREATE INDEX cms_visit_log_ra ON ${_prefix}cms_visit_log (remote_addr); +CREATE INDEX cms_visit_log_sc ON ${_prefix}cms_visit_log (site_code); +CREATE INDEX cms_visit_log_uvid ON ${_prefix}cms_visit_log (unique_visit_id); +CREATE INDEX cms_visit_log_vd ON ${_prefix}cms_visit_log (visit_date); +CREATE INDEX cms_visit_log_vt ON ${_prefix}cms_visit_log (visit_time); +CREATE INDEX idx_cms_visit_log_corpc ON ${_prefix}cms_visit_log (corp_code); + + + +/* Comments */ + +COMMENT ON TABLE ${_prefix}cms_article IS '文章表'; +COMMENT ON COLUMN ${_prefix}cms_article.id IS '编号'; +COMMENT ON COLUMN ${_prefix}cms_article.category_code IS '栏目编码'; +COMMENT ON COLUMN ${_prefix}cms_article.module_type IS '模块类型'; +COMMENT ON COLUMN ${_prefix}cms_article.title IS '内容标题'; +COMMENT ON COLUMN ${_prefix}cms_article.href IS '外部链接'; +COMMENT ON COLUMN ${_prefix}cms_article.color IS '标题颜色'; +COMMENT ON COLUMN ${_prefix}cms_article.image IS '内容图片'; +COMMENT ON COLUMN ${_prefix}cms_article.keywords IS '关键字'; +COMMENT ON COLUMN ${_prefix}cms_article.description IS '描述'; +COMMENT ON COLUMN ${_prefix}cms_article.weight IS '权重,越大越靠前'; +COMMENT ON COLUMN ${_prefix}cms_article.weight_date IS '权重期限'; +COMMENT ON COLUMN ${_prefix}cms_article.source IS '来源(转载/原创)'; +COMMENT ON COLUMN ${_prefix}cms_article.copyfrom IS '文章来源出处'; +COMMENT ON COLUMN ${_prefix}cms_article.hits IS '点击数'; +COMMENT ON COLUMN ${_prefix}cms_article.hits_plus IS '支持数'; +COMMENT ON COLUMN ${_prefix}cms_article.hits_minus IS '反对数'; +COMMENT ON COLUMN ${_prefix}cms_article.word_count IS '字数(不包含html)'; +COMMENT ON COLUMN ${_prefix}cms_article.custom_content_view IS '自定义内容视图'; +COMMENT ON COLUMN ${_prefix}cms_article.view_config IS '视图配置'; +COMMENT ON COLUMN ${_prefix}cms_article.status IS '状态(0正常 1删除 2停用)'; +COMMENT ON COLUMN ${_prefix}cms_article.create_by IS '创建者'; +COMMENT ON COLUMN ${_prefix}cms_article.create_date IS '创建时间'; +COMMENT ON COLUMN ${_prefix}cms_article.update_by IS '更新者'; +COMMENT ON COLUMN ${_prefix}cms_article.update_date IS '更新时间'; +COMMENT ON COLUMN ${_prefix}cms_article.remarks IS '备注信息'; +COMMENT ON COLUMN ${_prefix}cms_article.corp_code IS '租户代码'; +COMMENT ON COLUMN ${_prefix}cms_article.corp_name IS '租户名称'; +COMMENT ON TABLE ${_prefix}cms_article_data IS '文章详情表'; +COMMENT ON COLUMN ${_prefix}cms_article_data.id IS '编号'; +COMMENT ON COLUMN ${_prefix}cms_article_data.content IS '文章内容'; +COMMENT ON COLUMN ${_prefix}cms_article_data.relation IS '相关文章'; +COMMENT ON COLUMN ${_prefix}cms_article_data.is_can_comment IS '是否允许评论'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_s1 IS '扩展 String 1'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_s2 IS '扩展 String 2'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_s3 IS '扩展 String 3'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_s4 IS '扩展 String 4'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_s5 IS '扩展 String 5'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_s6 IS '扩展 String 6'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_s7 IS '扩展 String 7'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_s8 IS '扩展 String 8'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_i1 IS '扩展 Integer 1'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_i2 IS '扩展 Integer 2'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_i3 IS '扩展 Integer 3'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_i4 IS '扩展 Integer 4'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_f1 IS '扩展 Float 1'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_f2 IS '扩展 Float 2'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_f3 IS '扩展 Float 3'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_f4 IS '扩展 Float 4'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_d1 IS '扩展 Date 1'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_d2 IS '扩展 Date 2'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_d3 IS '扩展 Date 3'; +COMMENT ON COLUMN ${_prefix}cms_article_data.extend_d4 IS '扩展 Date 4'; +COMMENT ON TABLE ${_prefix}cms_article_posid IS '文章推荐位'; +COMMENT ON COLUMN ${_prefix}cms_article_posid.article_id IS '内容编号'; +COMMENT ON COLUMN ${_prefix}cms_article_posid.postid IS '推荐位置(1轮播图 2首页推荐 3栏目页面)'; +COMMENT ON TABLE ${_prefix}cms_article_tag IS '文章与标签关系'; +COMMENT ON COLUMN ${_prefix}cms_article_tag.article_id IS '内容编号'; +COMMENT ON COLUMN ${_prefix}cms_article_tag.tag_name IS '标签名称'; +COMMENT ON TABLE ${_prefix}cms_category IS '栏目表'; +COMMENT ON COLUMN ${_prefix}cms_category.category_code IS '栏目编码'; +COMMENT ON COLUMN ${_prefix}cms_category.parent_code IS '父级编号'; +COMMENT ON COLUMN ${_prefix}cms_category.parent_codes IS '所有父级编号'; +COMMENT ON COLUMN ${_prefix}cms_category.tree_sort IS '本级排序号(升序)'; +COMMENT ON COLUMN ${_prefix}cms_category.tree_sorts IS '所有级别排序号'; +COMMENT ON COLUMN ${_prefix}cms_category.tree_leaf IS '是否最末级'; +COMMENT ON COLUMN ${_prefix}cms_category.tree_level IS '层次级别'; +COMMENT ON COLUMN ${_prefix}cms_category.tree_names IS '全节点名'; +COMMENT ON COLUMN ${_prefix}cms_category.category_name IS '栏目名称'; +COMMENT ON COLUMN ${_prefix}cms_category.site_code IS '站点编码'; +COMMENT ON COLUMN ${_prefix}cms_category.module_type IS '模块类型'; +COMMENT ON COLUMN ${_prefix}cms_category.image IS '栏目图片'; +COMMENT ON COLUMN ${_prefix}cms_category.href IS '链接'; +COMMENT ON COLUMN ${_prefix}cms_category.target IS '目标'; +COMMENT ON COLUMN ${_prefix}cms_category.keywords IS '关键字'; +COMMENT ON COLUMN ${_prefix}cms_category.description IS '描述'; +COMMENT ON COLUMN ${_prefix}cms_category.in_menu IS '是否在导航中显示'; +COMMENT ON COLUMN ${_prefix}cms_category.in_list IS '是否在分类页中显示列表'; +COMMENT ON COLUMN ${_prefix}cms_category.show_modes IS '展现模式'; +COMMENT ON COLUMN ${_prefix}cms_category.is_need_audit IS '是否需要审核'; +COMMENT ON COLUMN ${_prefix}cms_category.is_can_comment IS '是否允许评论'; +COMMENT ON COLUMN ${_prefix}cms_category.custom_list_view IS '自定义列表视图'; +COMMENT ON COLUMN ${_prefix}cms_category.custom_content_view IS '自定义内容视图'; +COMMENT ON COLUMN ${_prefix}cms_category.view_config IS '视图配置'; +COMMENT ON COLUMN ${_prefix}cms_category.status IS '状态(0正常 1删除 2停用)'; +COMMENT ON COLUMN ${_prefix}cms_category.create_by IS '创建者'; +COMMENT ON COLUMN ${_prefix}cms_category.create_date IS '创建时间'; +COMMENT ON COLUMN ${_prefix}cms_category.update_by IS '更新者'; +COMMENT ON COLUMN ${_prefix}cms_category.update_date IS '更新时间'; +COMMENT ON COLUMN ${_prefix}cms_category.remarks IS '备注信息'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_s1 IS '扩展 String 1'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_s2 IS '扩展 String 2'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_s3 IS '扩展 String 3'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_s4 IS '扩展 String 4'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_s5 IS '扩展 String 5'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_s6 IS '扩展 String 6'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_s7 IS '扩展 String 7'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_s8 IS '扩展 String 8'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_i1 IS '扩展 Integer 1'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_i2 IS '扩展 Integer 2'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_i3 IS '扩展 Integer 3'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_i4 IS '扩展 Integer 4'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_f1 IS '扩展 Float 1'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_f2 IS '扩展 Float 2'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_f3 IS '扩展 Float 3'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_f4 IS '扩展 Float 4'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_d1 IS '扩展 Date 1'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_d2 IS '扩展 Date 2'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_d3 IS '扩展 Date 3'; +COMMENT ON COLUMN ${_prefix}cms_category.extend_d4 IS '扩展 Date 4'; +COMMENT ON TABLE ${_prefix}cms_category_role IS '栏目与角色关联表'; +COMMENT ON COLUMN ${_prefix}cms_category_role.category_code IS '栏目编码'; +COMMENT ON COLUMN ${_prefix}cms_category_role.role_code IS '角色编码'; +COMMENT ON COLUMN ${_prefix}cms_category_role.ctrl_type IS '控制类型(view查看、edit编辑)'; +COMMENT ON TABLE ${_prefix}cms_comment IS '文章评论表'; +COMMENT ON COLUMN ${_prefix}cms_comment.id IS '编号'; +COMMENT ON COLUMN ${_prefix}cms_comment.category_code IS '栏目编码'; +COMMENT ON COLUMN ${_prefix}cms_comment.article_id IS '内容编号'; +COMMENT ON COLUMN ${_prefix}cms_comment.parent_id IS '父级评论'; +COMMENT ON COLUMN ${_prefix}cms_comment.article_title IS '内容标题'; +COMMENT ON COLUMN ${_prefix}cms_comment.content IS '评论内容'; +COMMENT ON COLUMN ${_prefix}cms_comment.name IS '评论姓名'; +COMMENT ON COLUMN ${_prefix}cms_comment.ip IS '评论IP'; +COMMENT ON COLUMN ${_prefix}cms_comment.create_by IS '创建者'; +COMMENT ON COLUMN ${_prefix}cms_comment.create_date IS '创建时间'; +COMMENT ON COLUMN ${_prefix}cms_comment.audit_user_code IS '审核人'; +COMMENT ON COLUMN ${_prefix}cms_comment.audit_date IS '审核时间'; +COMMENT ON COLUMN ${_prefix}cms_comment.audit_comment IS '审核意见'; +COMMENT ON COLUMN ${_prefix}cms_comment.hits_plus IS '支持数'; +COMMENT ON COLUMN ${_prefix}cms_comment.hits_minus IS '反对数'; +COMMENT ON COLUMN ${_prefix}cms_comment.status IS '状态(0正常 1删除 2停用)'; +COMMENT ON COLUMN ${_prefix}cms_comment.corp_code IS '租户代码'; +COMMENT ON COLUMN ${_prefix}cms_comment.corp_name IS '租户名称'; +COMMENT ON TABLE ${_prefix}cms_guestbook IS '留言板表'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.id IS '编号'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.type IS '留言分类'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.content IS '留言内容'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.name IS '姓名'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.email IS '邮箱'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.phone IS '电话'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.workunit IS '单位'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.ip IS 'IP'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.create_by IS '创建者'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.create_date IS '创建时间'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.re_user_code IS '回复人'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.re_date IS '回复时间'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.re_content IS '回复内容'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.status IS '状态(0正常 1删除 2停用)'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.corp_code IS '租户代码'; +COMMENT ON COLUMN ${_prefix}cms_guestbook.corp_name IS '租户名称'; +COMMENT ON TABLE ${_prefix}cms_report IS '内容举报表'; +COMMENT ON COLUMN ${_prefix}cms_report.id IS '编号'; +COMMENT ON COLUMN ${_prefix}cms_report.report_source IS '举报来源(1文章、2评论)'; +COMMENT ON COLUMN ${_prefix}cms_report.report_content IS '举报内容(文章标题 评论内容)'; +COMMENT ON COLUMN ${_prefix}cms_report.report_url IS '举报的URL'; +COMMENT ON COLUMN ${_prefix}cms_report.report_type IS '举报类型(色情 政治...)'; +COMMENT ON COLUMN ${_prefix}cms_report.report_cause IS '举报原因'; +COMMENT ON TABLE ${_prefix}cms_site IS '站点表'; +COMMENT ON COLUMN ${_prefix}cms_site.site_code IS '站点编码'; +COMMENT ON COLUMN ${_prefix}cms_site.site_name IS '站点名称'; +COMMENT ON COLUMN ${_prefix}cms_site.site_sort IS '站点排序号'; +COMMENT ON COLUMN ${_prefix}cms_site.title IS '站点标题'; +COMMENT ON COLUMN ${_prefix}cms_site.logo IS '站点Logo'; +COMMENT ON COLUMN ${_prefix}cms_site.domain IS '站点域名'; +COMMENT ON COLUMN ${_prefix}cms_site.keywords IS '关键字'; +COMMENT ON COLUMN ${_prefix}cms_site.description IS '描述'; +COMMENT ON COLUMN ${_prefix}cms_site.theme IS '主题'; +COMMENT ON COLUMN ${_prefix}cms_site.copyright IS '版权信息'; +COMMENT ON COLUMN ${_prefix}cms_site.custom_index_view IS '自定义站点首页视图'; +COMMENT ON COLUMN ${_prefix}cms_site.status IS '状态(0正常 1删除 2停用)'; +COMMENT ON COLUMN ${_prefix}cms_site.create_by IS '创建者'; +COMMENT ON COLUMN ${_prefix}cms_site.create_date IS '创建时间'; +COMMENT ON COLUMN ${_prefix}cms_site.update_by IS '更新者'; +COMMENT ON COLUMN ${_prefix}cms_site.update_date IS '更新时间'; +COMMENT ON COLUMN ${_prefix}cms_site.remarks IS '备注信息'; +COMMENT ON TABLE ${_prefix}cms_tag IS '内容标签'; +COMMENT ON COLUMN ${_prefix}cms_tag.tag_name IS '标签名称'; +COMMENT ON COLUMN ${_prefix}cms_tag.clicknum IS '点击次数'; +COMMENT ON TABLE ${_prefix}cms_visit_log IS '访问日志表'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.id IS '编号'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.request_url IS '请求的URL地址'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.request_url_host IS '受访域名'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.source_referer IS '来源页面/上一个页面'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.source_referer_host IS '来源域名'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.source_type IS '访问来源类型(1直接访问 2搜索引擎 3外部链接 4内部访问)'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.search_engine IS '使用的搜索引擎'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.search_word IS '搜索的关键词'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.remote_addr IS '客户IP地址'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.user_agent IS '用户代理字符串'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.user_language IS '客户机语言'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.user_screen_size IS '客户机屏幕大小0x0'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.user_device IS '客户机设备类型(电脑、平板、手机、未知)'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.user_os_name IS '客户机操作系统'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.user_browser IS '客户机浏览器'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.user_browser_version IS '浏览器版本'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.unique_visit_id IS '唯一访问标识'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.visit_date IS '本次访问日期(年月日)'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.visit_time IS '本次访问时间'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.is_new_visit IS '是否新访问(30分内)'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.first_visit_time IS '首次访问时间戳(30分钟内)'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.prev_remain_time IS '上页面停留时间(秒)'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.total_remain_time IS '本次访问总停留时间(秒)'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.site_code IS '站点编码'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.site_name IS '站点名称'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.category_code IS '栏目编码'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.category_name IS '栏目名称'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.content_id IS '栏目内容编号'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.content_title IS '访问页面标题'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.visit_user_code IS '访问用户编码'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.visit_user_name IS '访问用户姓名'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.corp_code IS '租户代码'; +COMMENT ON COLUMN ${_prefix}cms_visit_log.corp_name IS '租户名称'; + + + diff --git a/modules/cms/src/main/resources/db/upgrade/cms/mssql/mssql_4.2.0.sql b/modules/cms/src/main/resources/db/upgrade/cms/mssql/mssql_4.2.0.sql new file mode 100644 index 00000000..b128fb42 --- /dev/null +++ b/modules/cms/src/main/resources/db/upgrade/cms/mssql/mssql_4.2.0.sql @@ -0,0 +1,2 @@ + +ALTER TABLE ${_prefix}cms_site ADD site_sort decimal(10) NULL; diff --git a/modules/cms/src/main/resources/db/upgrade/cms/mssql/mssql_4.2.1.sql b/modules/cms/src/main/resources/db/upgrade/cms/mssql/mssql_4.2.1.sql new file mode 100644 index 00000000..c26bb2df --- /dev/null +++ b/modules/cms/src/main/resources/db/upgrade/cms/mssql/mssql_4.2.1.sql @@ -0,0 +1,2 @@ + +UPDATE ${_prefix}sys_module SET main_class_name='com.jeesite.modules.cms.web.ArticleController' WHERE module_code='cms'; diff --git a/modules/cms/src/main/resources/db/upgrade/cms/mysql/mysql_4.2.0.sql b/modules/cms/src/main/resources/db/upgrade/cms/mysql/mysql_4.2.0.sql new file mode 100644 index 00000000..67fbfeac --- /dev/null +++ b/modules/cms/src/main/resources/db/upgrade/cms/mysql/mysql_4.2.0.sql @@ -0,0 +1,3 @@ + +ALTER TABLE ${_prefix}cms_site +ADD COLUMN `site_sort` decimal(10,0) NULL COMMENT '站点排序' AFTER `site_name`; diff --git a/modules/cms/src/main/resources/db/upgrade/cms/mysql/mysql_4.2.1.sql b/modules/cms/src/main/resources/db/upgrade/cms/mysql/mysql_4.2.1.sql new file mode 100644 index 00000000..c26bb2df --- /dev/null +++ b/modules/cms/src/main/resources/db/upgrade/cms/mysql/mysql_4.2.1.sql @@ -0,0 +1,2 @@ + +UPDATE ${_prefix}sys_module SET main_class_name='com.jeesite.modules.cms.web.ArticleController' WHERE module_code='cms'; diff --git a/modules/cms/src/main/resources/db/upgrade/cms/oracle/oracle_4.2.0.sql b/modules/cms/src/main/resources/db/upgrade/cms/oracle/oracle_4.2.0.sql new file mode 100644 index 00000000..9cc71718 --- /dev/null +++ b/modules/cms/src/main/resources/db/upgrade/cms/oracle/oracle_4.2.0.sql @@ -0,0 +1,3 @@ + +ALTER TABLE ${_prefix}cms_site ADD site_sort NUMBER(10) NULL; +COMMENT ON COLUMN ${_prefix}cms_site.site_sort IS '站点排序'; diff --git a/modules/cms/src/main/resources/db/upgrade/cms/oracle/oracle_4.2.1.sql b/modules/cms/src/main/resources/db/upgrade/cms/oracle/oracle_4.2.1.sql new file mode 100644 index 00000000..c26bb2df --- /dev/null +++ b/modules/cms/src/main/resources/db/upgrade/cms/oracle/oracle_4.2.1.sql @@ -0,0 +1,2 @@ + +UPDATE ${_prefix}sys_module SET main_class_name='com.jeesite.modules.cms.web.ArticleController' WHERE module_code='cms'; diff --git a/modules/cms/src/main/resources/db/upgrade/cms/postgresql/postgresql_4.2.0.sql b/modules/cms/src/main/resources/db/upgrade/cms/postgresql/postgresql_4.2.0.sql new file mode 100644 index 00000000..ab4d966b --- /dev/null +++ b/modules/cms/src/main/resources/db/upgrade/cms/postgresql/postgresql_4.2.0.sql @@ -0,0 +1,3 @@ + +ALTER TABLE ${_prefix}cms_site ADD COLUMN site_sort decimal(10); +COMMENT ON COLUMN ${_prefix}cms_site.site_sort IS '站点排序'; diff --git a/modules/cms/src/main/resources/db/upgrade/cms/postgresql/postgresql_4.2.1.sql b/modules/cms/src/main/resources/db/upgrade/cms/postgresql/postgresql_4.2.1.sql new file mode 100644 index 00000000..c26bb2df --- /dev/null +++ b/modules/cms/src/main/resources/db/upgrade/cms/postgresql/postgresql_4.2.1.sql @@ -0,0 +1,2 @@ + +UPDATE ${_prefix}sys_module SET main_class_name='com.jeesite.modules.cms.web.ArticleController' WHERE module_code='cms'; diff --git a/modules/cms/src/main/resources/db/upgrade/cms/versions b/modules/cms/src/main/resources/db/upgrade/cms/versions new file mode 100644 index 00000000..254f2bea --- /dev/null +++ b/modules/cms/src/main/resources/db/upgrade/cms/versions @@ -0,0 +1,9 @@ +4.0.0 +4.1.6 +4.1.7 +4.1.8 +4.1.9 +4.2.0 +4.2.1 +4.2.2 +4.2.3 \ No newline at end of file diff --git a/modules/cms/src/main/resources/mappings/modules/cms/ArticleDao.xml b/modules/cms/src/main/resources/mappings/modules/cms/ArticleDao.xml new file mode 100644 index 00000000..1c2c1821 --- /dev/null +++ b/modules/cms/src/main/resources/mappings/modules/cms/ArticleDao.xml @@ -0,0 +1,26 @@ + + + + + + + + update ${_prefix}cms_article SET weight = 0 + WHERE weight > 0 AND weight_date < #{weightDate} + + + + update ${_prefix}cms_article set + hits = hits + 1 + WHERE id = #{id} + + + \ No newline at end of file diff --git a/modules/cms/src/main/resources/mappings/modules/cms/ArticleDataDao.xml b/modules/cms/src/main/resources/mappings/modules/cms/ArticleDataDao.xml new file mode 100644 index 00000000..c6938493 --- /dev/null +++ b/modules/cms/src/main/resources/mappings/modules/cms/ArticleDataDao.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/modules/cms/src/main/resources/mappings/modules/cms/ArticlePosidDao.xml b/modules/cms/src/main/resources/mappings/modules/cms/ArticlePosidDao.xml new file mode 100644 index 00000000..004a8232 --- /dev/null +++ b/modules/cms/src/main/resources/mappings/modules/cms/ArticlePosidDao.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/modules/cms/src/main/resources/mappings/modules/cms/ArticleTagDao.xml b/modules/cms/src/main/resources/mappings/modules/cms/ArticleTagDao.xml new file mode 100644 index 00000000..65cac5e9 --- /dev/null +++ b/modules/cms/src/main/resources/mappings/modules/cms/ArticleTagDao.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/modules/cms/src/main/resources/mappings/modules/cms/CategoryDao.xml b/modules/cms/src/main/resources/mappings/modules/cms/CategoryDao.xml new file mode 100644 index 00000000..104783a7 --- /dev/null +++ b/modules/cms/src/main/resources/mappings/modules/cms/CategoryDao.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/modules/cms/src/main/resources/mappings/modules/cms/CategoryRoleDao.xml b/modules/cms/src/main/resources/mappings/modules/cms/CategoryRoleDao.xml new file mode 100644 index 00000000..9b32bd93 --- /dev/null +++ b/modules/cms/src/main/resources/mappings/modules/cms/CategoryRoleDao.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/modules/cms/src/main/resources/mappings/modules/cms/CommentDao.xml b/modules/cms/src/main/resources/mappings/modules/cms/CommentDao.xml new file mode 100644 index 00000000..c232b39e --- /dev/null +++ b/modules/cms/src/main/resources/mappings/modules/cms/CommentDao.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/modules/cms/src/main/resources/mappings/modules/cms/ReportDao.xml b/modules/cms/src/main/resources/mappings/modules/cms/ReportDao.xml new file mode 100644 index 00000000..d3212902 --- /dev/null +++ b/modules/cms/src/main/resources/mappings/modules/cms/ReportDao.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/modules/cms/src/main/resources/mappings/modules/cms/SiteDao.xml b/modules/cms/src/main/resources/mappings/modules/cms/SiteDao.xml new file mode 100644 index 00000000..2fe2a2b0 --- /dev/null +++ b/modules/cms/src/main/resources/mappings/modules/cms/SiteDao.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/modules/cms/src/main/resources/mappings/modules/cms/TagDao.xml b/modules/cms/src/main/resources/mappings/modules/cms/TagDao.xml new file mode 100644 index 00000000..2b999ccd --- /dev/null +++ b/modules/cms/src/main/resources/mappings/modules/cms/TagDao.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/modules/cms/src/main/resources/mappings/modules/cms/VisitLogDao.xml b/modules/cms/src/main/resources/mappings/modules/cms/VisitLogDao.xml new file mode 100644 index 00000000..527bcf49 --- /dev/null +++ b/modules/cms/src/main/resources/mappings/modules/cms/VisitLogDao.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/modules/cms/src/main/resources/static/modules/cmsfront/themes/css/custom.css b/modules/cms/src/main/resources/static/modules/cmsfront/themes/css/custom.css new file mode 100644 index 00000000..8051f995 --- /dev/null +++ b/modules/cms/src/main/resources/static/modules/cmsfront/themes/css/custom.css @@ -0,0 +1,76 @@ +body{padding-top:50px;font-size:14px;} +body>.navbar{-webkit-transition:background-color .3s ease-in;transition:background-color .3s ease-in} +@media (min-width:768px){ + body>.navbar-transparent{background-color:transparent} + body>.navbar-transparent .navbar-nav>.open>a{background-color:transparent!important} +} +#home{padding-top:0} +#home .navbar-brand{padding:13.5px 15px 12.5px} +#home .navbar-brand>img{display:inline;margin:0 10px;height:100%} +#banner{min-height:300px;border-bottom:none} +.table-of-contents{margin-top:1em} +.page-header h1{font-size:4em} +.bs-docs-section{margin-top:6em} +.bs-docs-section h1{padding-top:100px} +.bs-component{position:relative} +.bs-component .modal{position:relative;top:auto;right:auto;left:auto;bottom:auto;z-index:1;display:block} +.bs-component .modal-dialog{width:90%} +.bs-component .popover{position:relative;display:inline-block;width:220px;margin:20px} +#source-button{position:absolute;top:0;right:0;z-index:100;font-weight:700} +.nav-tabs{margin-bottom:15px} +.progress{margin-bottom:10px} +footer{margin:1.5em 0} +footer li{float:left;margin-right:1.5em;margin-bottom:1.5em} +footer p{clear:left;margin-bottom:0} +.splash{padding:9em 0 2em;background-color:#141d27;background-image:url(../img/bg.jpg);background-size:cover;background-attachment:fixed;color:#fff;text-align:center} +.splash .logo{width:160px} +.splash h1{font-size:3em} +.splash #social{margin:2em 0} +.splash .alert{margin:2em 0} +.section-tout{padding:4em 0 3em;border-bottom:1px solid rgba(0,0,0,.05);background-color:#eaf1f1} +.section-tout .fa{margin-right:.5em} +.section-tout p{margin-bottom:3em} +.section-preview{padding:4em 0 4em} +.section-preview .preview{margin-bottom:4em;background-color:#eaf1f1} +.section-preview .preview .image{position:relative} +.section-preview .preview .image:before{box-shadow:inset 0 0 0 1px rgba(0,0,0,.1);position:absolute;top:0;left:0;width:100%;height:100%;content:"";pointer-events:none} +.section-preview .preview .options{padding:1em 2em 2em;border:1px solid rgba(0,0,0,.05);border-top:none;text-align:center} +.section-preview .preview .options p{margin-bottom:2em} +.section-preview .dropdown-menu{text-align:left} +.section-preview .lead{margin-bottom:2em} +@media (max-width:767px){ + .section-preview .image img{width:100%} +} +.sponsor #carbonads{max-width:240px;margin:0 auto} +.sponsor .carbon-text{display:block;margin-top:1em;font-size:12px} +.sponsor .carbon-poweredby{float:right;margin-top:1em;font-size:10px} +@media (max-width:767px){ + .splash{padding-top:4em} + .splash .logo{width:100px} + .splash h1{font-size:2em} + #banner{margin-bottom:2em;text-align:center} +} + +.jumbotron {background:#f1f1f1;margin:48px auto;} +.panel-title small .more {padding-top:4px;} + +.nav-search {margin-top:9px;} +.nav-search .form-control {height:30px;padding:5px;} +.nav-search .btn {height:31px;padding:5px 10px;} + +.article-list {padding:5px;margin:0;} +.article-list li {list-style:none;padding:8px 0;} + +.article-title {color:#555555;font-size:20px;text-align:center;border-bottom:1px solid #ddd;padding:15px 20px 20px 20px;margin-bottom:30px;} +.article-info {border-top:1px solid #ddd;padding:10px;margin:25px 0 0;} +.article-desc {padding:8px 10px 8px;margin:10px 20px 20px 35px;font-size:13px;} +.article-content {padding-top:10px;} + +.pagination {margin:8px 0;display:block;/* text-align:center; */font-size:13px;} /* .pagination .controls a{border:0;} */ +.pagination>li>a, .pagination>li>span {min-width:37px;text-align:center;padding:6px;border:1px solid #ddd;background:transparent;/* border-radius:3px; */} +.pagination>.active>a, .pagination>.active>a:focus, .pagination>.active>a:hover, +.pagination>.active>span, .pagination>.active>span:focus, .pagination>.active>span:hover {background:#eee;color:#333;border-color:#ddd} +.pagination>.disabled>span, .pagination>.disabled>span:hover, .pagination>.disabled>span:focus, +.pagination>.disabled>a, .pagination>.disabled>a:hover, .pagination>.disabled>a:focus {cursor:default!important;color:#ccc;} +.pagination .controls {float:left;border:0;padding:7px 0 0 15px;color:#777;} +.pagination .controls input{border:0;width:22px;padding:0;margin:-3px 0 0 0;text-align:center;font-size:13px;background:transparent;box-shadow:none;} diff --git a/modules/cms/src/main/resources/static/modules/cmsfront/themes/default/_bootswatch.scss b/modules/cms/src/main/resources/static/modules/cmsfront/themes/default/_bootswatch.scss new file mode 100644 index 00000000..5f04a929 --- /dev/null +++ b/modules/cms/src/main/resources/static/modules/cmsfront/themes/default/_bootswatch.scss @@ -0,0 +1,262 @@ +// Cosmo 3.4.1 +// Bootswatch +// ----------------------------------------------------- + +$web-font-path: "https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,700" !default; +@import url($web-font-path); + +// Navbar ===================================================================== + +.navbar { + + &-inverse { + + .badge { + background-color: #fff; + color: $brand-primary; + } + } +} + +// Buttons ==================================================================== + +// Typography ================================================================= + +body { + -webkit-font-smoothing: antialiased; +} + +.text-primary, +.text-primary:hover { + color: $brand-primary; +} + +.text-success, +.text-success:hover { + color: $brand-success; +} + +.text-danger, +.text-danger:hover { + color: $brand-danger; +} + +.text-warning, +.text-warning:hover { + color: $brand-warning; +} + +.text-info, +.text-info:hover { + color: $brand-info; +} + +// Tables ===================================================================== + +table, +.table { + + a:not(.btn) { + text-decoration: underline; + } + + .dropdown-menu a { + text-decoration: none; + } + + .success, + .warning, + .danger, + .info { + color: #fff; + + a { + color: #fff; + } + } +} + +// Forms ====================================================================== + + +.has-warning { + .help-block, + .control-label, + .radio, + .checkbox, + .radio-inline, + .checkbox-inline, + &.radio label, + &.checkbox label, + &.radio-inline label, + &.checkbox-inline label, + .form-control-feedback { + color: $brand-warning; + } + + .form-control, + .form-control:focus, + .input-group-addon { + border: 1px solid $brand-warning; + } +} + +.has-error { + .help-block, + .control-label, + .radio, + .checkbox, + .radio-inline, + .checkbox-inline, + &.radio label, + &.checkbox label, + &.radio-inline label, + &.checkbox-inline label, + .form-control-feedback { + color: $brand-danger; + } + + .form-control, + .form-control:focus, + .input-group-addon { + border: 1px solid $brand-danger; + } +} + +.has-success { + .help-block, + .control-label, + .radio, + .checkbox, + .radio-inline, + .checkbox-inline, + &.radio label, + &.checkbox label, + &.radio-inline label, + &.checkbox-inline label, + .form-control-feedback { + color: $brand-success; + } + + .form-control, + .form-control:focus, + .input-group-addon { + border: 1px solid $brand-success; + } +} + +// Navs ======================================================================= + +.nav-pills { + + & > li > a { + border-radius: 0; + } +} + +.dropdown-menu { + + & > li > a:hover, + & > li > a:focus { + background-image: none; + } +} + +// Indicators ================================================================= + +.close { + text-decoration: none; + text-shadow: none; + opacity: 0.4; + + &:hover, + &:focus { + opacity: 1; + } +} + +.alert { + border: none; + + .alert-link { + text-decoration: underline; + color: #fff; + } +} + +.label { + border-radius: 0; +} + +// Progress bars ============================================================== + +.progress { + height: 8px; + @include box-shadow(none); + .progress-bar { + font-size: 8px; + line-height: 8px; + } +} + +// Containers ================================================================= + +.panel { + &-heading, + &-footer { + border-top-right-radius: 0; + border-top-left-radius: 0; + } + + &-default { + .close { + color: $text-color; + } + } +} + +a.list-group-item { + + &-success { + &.active { + background-color: $state-success-bg; + } + + &.active:hover, + &.active:focus { + background-color: darken($state-success-bg, 5%); + } + } + + &-warning { + &.active { + background-color: $state-warning-bg; + } + + &.active:hover, + &.active:focus { + background-color: darken($state-warning-bg, 5%); + } + } + + &-danger { + &.active { + background-color: $state-danger-bg; + } + + &.active:hover, + &.active:focus { + background-color: darken($state-danger-bg, 5%); + } + } +} + +.modal { + .close { + color: $text-color; + } +} + +.popover { + color: $text-color; +} diff --git a/modules/cms/src/main/resources/static/modules/cmsfront/themes/default/_variables.scss b/modules/cms/src/main/resources/static/modules/cmsfront/themes/default/_variables.scss new file mode 100644 index 00000000..af73c2d6 --- /dev/null +++ b/modules/cms/src/main/resources/static/modules/cmsfront/themes/default/_variables.scss @@ -0,0 +1,870 @@ +$bootstrap-sass-asset-helper: false !default; +// Cosmo 3.4.1 +// Variables +// -------------------------------------------------- + + +//== Colors +// +//## Gray and brand colors for use across Bootstrap. + +$gray-base: #000 !default; +$gray-darker: lighten($gray-base, 13.5%) !default; // #222 +$gray-dark: lighten($gray-base, 20%) !default; // #333 +$gray: lighten($gray-base, 33.5%) !default; // #555 +$gray-light: lighten($gray-base, 60%) !default; // #999 +$gray-lighter: lighten($gray-base, 90%) !default; // #eee + +$brand-primary: #2780E3 !default; +$brand-success: #3FB618 !default; +$brand-info: #9954BB !default; +$brand-warning: #FF7518 !default; +$brand-danger: #FF0039 !default; + + +//== Scaffolding +// +//## Settings for some of the most global styles. + +//** Background color for ``. +$body-bg: #fff !default; +//** Global text color on ``. +$text-color: $gray-dark !default; + +//** Global textual link color. +$link-color: $brand-primary !default; +//** Link hover color set via `darken()` function. +$link-hover-color: darken($link-color, 15%) !default; +//** Link hover decoration. +$link-hover-decoration: underline !default; + + +//== Typography +// +//## Font, line-height, and color for body text, headings, and more. + +$font-family-sans-serif: "Source Sans Pro", Calibri, Candara, Arial, sans-serif !default; +$font-family-serif: Georgia, "Times New Roman", Times, serif !default; +//** Default monospace fonts for ``, ``, and `
`.
+$font-family-monospace:   Menlo, Monaco, Consolas, "Courier New", monospace !default;
+$font-family-base:        $font-family-sans-serif !default;
+
+$font-size-base:          15px !default;
+$font-size-large:         ceil(($font-size-base * 1.25)) !default; // ~18px
+$font-size-small:         ceil(($font-size-base * 0.85)) !default; // ~12px
+
+$font-size-h1:            floor(($font-size-base * 2.6)) !default; // ~36px
+$font-size-h2:            floor(($font-size-base * 2.15)) !default; // ~30px
+$font-size-h3:            ceil(($font-size-base * 1.7)) !default; // ~24px
+$font-size-h4:            ceil(($font-size-base * 1.25)) !default; // ~18px
+$font-size-h5:            $font-size-base !default;
+$font-size-h6:            ceil(($font-size-base * 0.85)) !default; // ~12px
+
+//** Unit-less `line-height` for use in components like buttons.
+$line-height-base:        1.428571429 !default; // 20/14
+//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
+$line-height-computed:    floor(($font-size-base * $line-height-base)) !default; // ~20px
+
+//** By default, this inherits from the ``.
+$headings-font-family:    $font-family-base !default;
+$headings-font-weight:    300 !default;
+$headings-line-height:    1.1 !default;
+$headings-color:          inherit !default;
+
+
+//== Iconography
+//
+//## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower.
+
+//** Load fonts from this directory.
+$icon-font-path: if($bootstrap-sass-asset-helper, "bootstrap/", "../fonts/bootstrap/") !default;
+//** File name for all font files.
+$icon-font-name:          "glyphicons-halflings-regular" !default;
+//** Element ID within SVG icon file.
+$icon-font-svg-id:        "glyphicons_halflingsregular" !default;
+
+
+//== Components
+//
+//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
+
+$padding-base-vertical:     10px !default;
+$padding-base-horizontal:   18px !default;
+
+$padding-large-vertical:    18px !default;
+$padding-large-horizontal:  30px !default;
+
+$padding-small-vertical:    5px !default;
+$padding-small-horizontal:  10px !default;
+
+$padding-xs-vertical:       1px !default;
+$padding-xs-horizontal:     5px !default;
+
+$line-height-large:         1.3333333 !default; // extra decimals for Win 8.1 Chrome
+$line-height-small:         1.5 !default;
+
+$border-radius-base:        0 !default;
+$border-radius-large:       0 !default;
+$border-radius-small:       0 !default;
+
+//** Global color for active items (e.g., navs or dropdowns).
+$component-active-color:    #fff !default;
+//** Global background color for active items (e.g., navs or dropdowns).
+$component-active-bg:       $brand-primary !default;
+
+//** Width of the `border` for generating carets that indicate dropdowns.
+$caret-width-base:          4px !default;
+//** Carets increase slightly in size for larger components.
+$caret-width-large:         5px !default;
+
+
+//== Tables
+//
+//## Customizes the `.table` component with basic values, each used across all table variations.
+
+//** Padding for ``s and ``s.
+$table-cell-padding:            8px !default;
+//** Padding for cells in `.table-condensed`.
+$table-condensed-cell-padding:  5px !default;
+
+//** Default background color used for all tables.
+$table-bg:                      transparent !default;
+//** Background color used for `.table-striped`.
+$table-bg-accent:               #f9f9f9 !default;
+//** Background color used for `.table-hover`.
+$table-bg-hover:                #f5f5f5 !default;
+$table-bg-active:               $table-bg-hover !default;
+
+//** Border color for table and cell borders.
+$table-border-color:            #ddd !default;
+
+
+//== Buttons
+//
+//## For each of Bootstrap's buttons, define text, background and border color.
+
+$btn-font-weight:                normal !default;
+
+$btn-default-color:              #fff !default;
+$btn-default-bg:                 $gray-darker !default;
+$btn-default-border:             $btn-default-bg !default;
+
+$btn-primary-color:              $btn-default-color !default;
+$btn-primary-bg:                 $brand-primary !default;
+$btn-primary-border:             $btn-primary-bg !default;
+
+$btn-success-color:              $btn-default-color !default;
+$btn-success-bg:                 $brand-success !default;
+$btn-success-border:             $btn-success-bg !default;
+
+$btn-info-color:                 $btn-default-color !default;
+$btn-info-bg:                    $brand-info !default;
+$btn-info-border:                $btn-info-bg !default;
+
+$btn-warning-color:              $btn-default-color !default;
+$btn-warning-bg:                 $brand-warning !default;
+$btn-warning-border:             $btn-warning-bg !default;
+
+$btn-danger-color:               $btn-default-color !default;
+$btn-danger-bg:                  $brand-danger !default;
+$btn-danger-border:              $btn-danger-bg !default;
+
+$btn-link-disabled-color:        $gray-light !default;
+
+// Allows for customizing button radius independently from global border radius
+$btn-border-radius-base:         $border-radius-base !default;
+$btn-border-radius-large:        $border-radius-large !default;
+$btn-border-radius-small:        $border-radius-small !default;
+
+
+//== Forms
+//
+//##
+
+//** `` background color
+$input-bg:                       #fff !default;
+//** `` background color
+$input-bg-disabled:              $gray-lighter !default;
+
+//** Text color for ``s
+$input-color:                    $text-color !default;
+//** `` border color
+$input-border:                   #ccc !default;
+
+// TODO: Rename `$input-border-radius` to `$input-border-radius-base` in v4
+//** Default `.form-control` border radius
+// This has no effect on ``s in CSS.
+$input-border-radius:            $border-radius-base !default;
+//** Large `.form-control` border radius
+$input-border-radius-large:      $border-radius-large !default;
+//** Small `.form-control` border radius
+$input-border-radius-small:      $border-radius-small !default;
+
+//** Border color for inputs on focus
+$input-border-focus:             #66afe9 !default;
+
+//** Placeholder text color
+$input-color-placeholder:        $gray-light !default;
+
+//** Default `.form-control` height
+$input-height-base:              ($line-height-computed + ($padding-base-vertical * 2) + 2) !default;
+//** Large `.form-control` height
+$input-height-large:             (ceil($font-size-large * $line-height-large) + ($padding-large-vertical * 2) + 2) !default;
+//** Small `.form-control` height
+$input-height-small:             (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2) !default;
+
+//** `.form-group` margin
+$form-group-margin-bottom:       15px !default;
+
+$legend-color:                   $text-color !default;
+$legend-border-color:            #e5e5e5 !default;
+
+//** Background color for textual input addons
+$input-group-addon-bg:           $gray-lighter !default;
+//** Border color for textual input addons
+$input-group-addon-border-color: $input-border !default;
+
+//** Disabled cursor for form controls and buttons.
+$cursor-disabled:                not-allowed !default;
+
+
+//== Dropdowns
+//
+//## Dropdown menu container and contents.
+
+//** Background for the dropdown menu.
+$dropdown-bg:                    #fff !default;
+//** Dropdown menu `border-color`.
+$dropdown-border:                rgba(0,0,0,.15) !default;
+//** Dropdown menu `border-color` **for IE8**.
+$dropdown-fallback-border:       #ccc !default;
+//** Divider color for between dropdown items.
+$dropdown-divider-bg:            #e5e5e5 !default;
+
+//** Dropdown link text color.
+$dropdown-link-color:            $gray-dark !default;
+//** Hover color for dropdown links.
+$dropdown-link-hover-color:      #fff !default;
+//** Hover background for dropdown links.
+$dropdown-link-hover-bg:         $component-active-bg !default;
+
+//** Active dropdown menu item text color.
+$dropdown-link-active-color:     #fff !default;
+//** Active dropdown menu item background color.
+$dropdown-link-active-bg:        $component-active-bg !default;
+
+//** Disabled dropdown menu item background color.
+$dropdown-link-disabled-color:   $gray-light !default;
+
+//** Text color for headers within dropdown menus.
+$dropdown-header-color:          $gray-light !default;
+
+//** Deprecated `$dropdown-caret-color` as of v3.1.0
+$dropdown-caret-color:           #000 !default;
+
+
+//-- Z-index master list
+//
+// Warning: Avoid customizing these values. They're used for a bird's eye view
+// of components dependent on the z-axis and are designed to all work together.
+//
+// Note: These variables are not generated into the Customizer.
+
+$zindex-navbar:            1000 !default;
+$zindex-dropdown:          1000 !default;
+$zindex-popover:           1060 !default;
+$zindex-tooltip:           1070 !default;
+$zindex-navbar-fixed:      1030 !default;
+$zindex-modal-background:  1040 !default;
+$zindex-modal:             1050 !default;
+
+
+//== Media queries breakpoints
+//
+//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
+
+// Extra small screen / phone
+//** Deprecated `$screen-xs` as of v3.0.1
+$screen-xs:                  480px !default;
+//** Deprecated `$screen-xs-min` as of v3.2.0
+$screen-xs-min:              $screen-xs !default;
+//** Deprecated `$screen-phone` as of v3.0.1
+$screen-phone:               $screen-xs-min !default;
+
+// Small screen / tablet
+//** Deprecated `$screen-sm` as of v3.0.1
+$screen-sm:                  768px !default;
+$screen-sm-min:              $screen-sm !default;
+//** Deprecated `$screen-tablet` as of v3.0.1
+$screen-tablet:              $screen-sm-min !default;
+
+// Medium screen / desktop
+//** Deprecated `$screen-md` as of v3.0.1
+$screen-md:                  992px !default;
+$screen-md-min:              $screen-md !default;
+//** Deprecated `$screen-desktop` as of v3.0.1
+$screen-desktop:             $screen-md-min !default;
+
+// Large screen / wide desktop
+//** Deprecated `$screen-lg` as of v3.0.1
+$screen-lg:                  1200px !default;
+$screen-lg-min:              $screen-lg !default;
+//** Deprecated `$screen-lg-desktop` as of v3.0.1
+$screen-lg-desktop:          $screen-lg-min !default;
+
+// So media queries don't overlap when required, provide a maximum
+$screen-xs-max:              ($screen-sm-min - 1) !default;
+$screen-sm-max:              ($screen-md-min - 1) !default;
+$screen-md-max:              ($screen-lg-min - 1) !default;
+
+
+//== Grid system
+//
+//## Define your custom responsive grid.
+
+//** Number of columns in the grid.
+$grid-columns:              12 !default;
+//** Padding between columns. Gets divided in half for the left and right.
+$grid-gutter-width:         30px !default;
+// Navbar collapse
+//** Point at which the navbar becomes uncollapsed.
+$grid-float-breakpoint:     $screen-sm-min !default;
+//** Point at which the navbar begins collapsing.
+$grid-float-breakpoint-max: ($grid-float-breakpoint - 1) !default;
+
+
+//== Container sizes
+//
+//## Define the maximum width of `.container` for different screen sizes.
+
+// Small screen / tablet
+$container-tablet:             (720px + $grid-gutter-width) !default;
+//** For `$screen-sm-min` and up.
+$container-sm:                 $container-tablet !default;
+
+// Medium screen / desktop
+$container-desktop:            (940px + $grid-gutter-width) !default;
+//** For `$screen-md-min` and up.
+$container-md:                 $container-desktop !default;
+
+// Large screen / wide desktop
+$container-large-desktop:      (1140px + $grid-gutter-width) !default;
+//** For `$screen-lg-min` and up.
+$container-lg:                 $container-large-desktop !default;
+
+
+//== Navbar
+//
+//##
+
+// Basics of a navbar
+$navbar-height:                    50px !default;
+$navbar-margin-bottom:             $line-height-computed !default;
+$navbar-border-radius:             $border-radius-base !default;
+$navbar-padding-horizontal:        floor(($grid-gutter-width / 2)) !default;
+$navbar-padding-vertical:          (($navbar-height - $line-height-computed) / 2) !default;
+$navbar-collapse-max-height:       340px !default;
+
+$navbar-default-color:             #fff !default;
+$navbar-default-bg:                $gray-darker !default;
+$navbar-default-border:            darken($navbar-default-bg, 6.5%) !default;
+
+// Navbar links
+$navbar-default-link-color:                #fff !default;
+$navbar-default-link-hover-color:          #fff !default;
+$navbar-default-link-hover-bg:             darken($navbar-default-bg, 10%) !default;
+$navbar-default-link-active-color:         $navbar-default-link-hover-color !default;
+$navbar-default-link-active-bg:            $navbar-default-link-hover-bg !default;
+$navbar-default-link-disabled-color:       #ccc !default;
+$navbar-default-link-disabled-bg:          transparent !default;
+
+// Navbar brand label
+$navbar-default-brand-color:               $navbar-default-link-color !default;
+$navbar-default-brand-hover-color:         #fff !default;
+$navbar-default-brand-hover-bg:            none !default;
+
+// Navbar toggle
+$navbar-default-toggle-hover-bg:           $navbar-default-link-hover-bg !default;
+$navbar-default-toggle-icon-bar-bg:        #fff !default;
+$navbar-default-toggle-border-color:       transparent !default;
+
+
+//=== Inverted navbar
+// Reset inverted navbar basics
+$navbar-inverse-color:                      #fff !default;
+$navbar-inverse-bg:                         $brand-primary !default;
+$navbar-inverse-border:                     darken($navbar-inverse-bg, 10%) !default;
+
+// Inverted navbar links
+$navbar-inverse-link-color:                 #fff !default;
+$navbar-inverse-link-hover-color:           #fff !default;
+$navbar-inverse-link-hover-bg:              darken($navbar-inverse-bg, 10%) !default;
+$navbar-inverse-link-active-color:          $navbar-inverse-link-hover-color !default;
+$navbar-inverse-link-active-bg:             $navbar-inverse-link-hover-bg !default;
+$navbar-inverse-link-disabled-color:        #fff !default;
+$navbar-inverse-link-disabled-bg:           transparent !default;
+
+// Inverted navbar brand label
+$navbar-inverse-brand-color:                $navbar-inverse-link-color !default;
+$navbar-inverse-brand-hover-color:          #fff !default;
+$navbar-inverse-brand-hover-bg:             none !default;
+
+// Inverted navbar toggle
+$navbar-inverse-toggle-hover-bg:            $navbar-inverse-link-hover-bg !default;
+$navbar-inverse-toggle-icon-bar-bg:         #fff !default;
+$navbar-inverse-toggle-border-color:        transparent !default;
+
+
+//== Navs
+//
+//##
+
+//=== Shared nav styles
+$nav-link-padding:                          10px 15px !default;
+$nav-link-hover-bg:                         $gray-lighter !default;
+
+$nav-disabled-link-color:                   $gray-light !default;
+$nav-disabled-link-hover-color:             $gray-light !default;
+
+//== Tabs
+$nav-tabs-border-color:                     #ddd !default;
+
+$nav-tabs-link-hover-border-color:          $gray-lighter !default;
+
+$nav-tabs-active-link-hover-bg:             $body-bg !default;
+$nav-tabs-active-link-hover-color:          $gray !default;
+$nav-tabs-active-link-hover-border-color:   #ddd !default;
+
+$nav-tabs-justified-link-border-color:            #ddd !default;
+$nav-tabs-justified-active-link-border-color:     $body-bg !default;
+
+//== Pills
+$nav-pills-border-radius:                   $border-radius-base !default;
+$nav-pills-active-link-hover-bg:            $component-active-bg !default;
+$nav-pills-active-link-hover-color:         $component-active-color !default;
+
+
+//== Pagination
+//
+//##
+
+$pagination-color:                     $link-color !default;
+$pagination-bg:                        #fff !default;
+$pagination-border:                    #ddd !default;
+
+$pagination-hover-color:               $link-hover-color !default;
+$pagination-hover-bg:                  $gray-lighter !default;
+$pagination-hover-border:              #ddd !default;
+
+$pagination-active-color:              $gray-light !default;
+$pagination-active-bg:                 #f5f5f5 !default;
+$pagination-active-border:             #ddd !default;
+
+$pagination-disabled-color:            $gray-light !default;
+$pagination-disabled-bg:               #fff !default;
+$pagination-disabled-border:           #ddd !default;
+
+
+//== Pager
+//
+//##
+
+$pager-bg:                             $pagination-bg !default;
+$pager-border:                         $pagination-border !default;
+$pager-border-radius:                  $border-radius-base !default;
+
+$pager-hover-bg:                       $pagination-hover-bg !default;
+
+$pager-active-bg:                      $pagination-active-bg !default;
+$pager-active-color:                   $pagination-active-color !default;
+
+$pager-disabled-color:                 $gray-light !default;
+
+
+//== Jumbotron
+//
+//##
+
+$jumbotron-padding:              30px !default;
+$jumbotron-color:                inherit !default;
+$jumbotron-bg:                   $gray-lighter !default;
+$jumbotron-heading-color:        inherit !default;
+$jumbotron-font-size:            ceil(($font-size-base * 1.5)) !default;
+$jumbotron-heading-font-size:    ceil(($font-size-base * 4.5)) !default;
+
+
+//== Form states and alerts
+//
+//## Define colors for form feedback states and, by default, alerts.
+
+$state-success-text:             #fff !default;
+$state-success-bg:               $brand-success !default;
+$state-success-border:           darken(adjust-hue($state-success-bg, -10), 5%) !default;
+
+$state-info-text:                #fff !default;
+$state-info-bg:                  $brand-info !default;
+$state-info-border:              darken(adjust-hue($state-info-bg, -10), 7%) !default;
+
+$state-warning-text:             #fff !default;
+$state-warning-bg:               $brand-warning !default;
+$state-warning-border:           darken(adjust-hue($state-warning-bg, -10), 3%) !default;
+
+$state-danger-text:              #fff !default;
+$state-danger-bg:                $brand-danger !default;
+$state-danger-border:            darken(adjust-hue($state-danger-bg, -10), 3%) !default;
+
+
+//== Tooltips
+//
+//##
+
+//** Tooltip max width
+$tooltip-max-width:           200px !default;
+//** Tooltip text color
+$tooltip-color:               #fff !default;
+//** Tooltip background color
+$tooltip-bg:                  #000 !default;
+$tooltip-opacity:             .9 !default;
+
+//** Tooltip arrow width
+$tooltip-arrow-width:         5px !default;
+//** Tooltip arrow color
+$tooltip-arrow-color:         $tooltip-bg !default;
+
+
+//== Popovers
+//
+//##
+
+//** Popover body background color
+$popover-bg:                          #fff !default;
+//** Popover maximum width
+$popover-max-width:                   276px !default;
+//** Popover border color
+$popover-border-color:                rgba(0,0,0,.2) !default;
+//** Popover fallback border color
+$popover-fallback-border-color:       #ccc !default;
+
+//** Popover title background color
+$popover-title-bg:                    darken($popover-bg, 3%) !default;
+
+//** Popover arrow width
+$popover-arrow-width:                 10px !default;
+//** Popover arrow color
+$popover-arrow-color:                 $popover-bg !default;
+
+//** Popover outer arrow width
+$popover-arrow-outer-width:           ($popover-arrow-width + 1) !default;
+//** Popover outer arrow color
+$popover-arrow-outer-color:           fadein($popover-border-color, 5%) !default;
+//** Popover outer arrow fallback color
+$popover-arrow-outer-fallback-color:  darken($popover-fallback-border-color, 20%) !default;
+
+
+//== Labels
+//
+//##
+
+//** Default label background color
+$label-default-bg:            $btn-default-bg !default;
+//** Primary label background color
+$label-primary-bg:            $brand-primary !default;
+//** Success label background color
+$label-success-bg:            $brand-success !default;
+//** Info label background color
+$label-info-bg:               $brand-info !default;
+//** Warning label background color
+$label-warning-bg:            $brand-warning !default;
+//** Danger label background color
+$label-danger-bg:             $brand-danger !default;
+
+//** Default label text color
+$label-color:                 #fff !default;
+//** Default text color of a linked label
+$label-link-hover-color:      #fff !default;
+
+
+//== Modals
+//
+//##
+
+//** Padding applied to the modal body
+$modal-inner-padding:         20px !default;
+
+//** Padding applied to the modal title
+$modal-title-padding:         15px !default;
+//** Modal title line-height
+$modal-title-line-height:     $line-height-base !default;
+
+//** Background color of modal content area
+$modal-content-bg:                             #fff !default;
+//** Modal content border color
+$modal-content-border-color:                   transparent !default;
+//** Modal content border color **for IE8**
+$modal-content-fallback-border-color:          #999 !default;
+
+//** Modal backdrop background color
+$modal-backdrop-bg:           #000 !default;
+//** Modal backdrop opacity
+$modal-backdrop-opacity:      .5 !default;
+//** Modal header border color
+$modal-header-border-color:   #e5e5e5 !default;
+//** Modal footer border color
+$modal-footer-border-color:   $modal-header-border-color !default;
+
+$modal-lg:                    900px !default;
+$modal-md:                    600px !default;
+$modal-sm:                    300px !default;
+
+
+//== Alerts
+//
+//## Define alert colors, border radius, and padding.
+
+$alert-padding:               15px !default;
+$alert-border-radius:         $border-radius-base !default;
+$alert-link-font-weight:      bold !default;
+
+$alert-success-bg:            $state-success-bg !default;
+$alert-success-text:          $state-success-text !default;
+$alert-success-border:        $state-success-border !default;
+
+$alert-info-bg:               $state-info-bg !default;
+$alert-info-text:             $state-info-text !default;
+$alert-info-border:           $state-info-border !default;
+
+$alert-warning-bg:            $state-warning-bg !default;
+$alert-warning-text:          $state-warning-text !default;
+$alert-warning-border:        $state-warning-border !default;
+
+$alert-danger-bg:             $state-danger-bg !default;
+$alert-danger-text:           $state-danger-text !default;
+$alert-danger-border:         $state-danger-border !default;
+
+
+//== Progress bars
+//
+//##
+
+//** Background color of the whole progress component
+$progress-bg:                 #ccc !default;
+//** Progress bar text color
+$progress-bar-color:          #fff !default;
+//** Variable for setting rounded corners on progress bar.
+$progress-border-radius:      $border-radius-base !default;
+
+//** Default progress bar color
+$progress-bar-bg:             $brand-primary !default;
+//** Success progress bar color
+$progress-bar-success-bg:     $brand-success !default;
+//** Warning progress bar color
+$progress-bar-warning-bg:     $brand-warning !default;
+//** Danger progress bar color
+$progress-bar-danger-bg:      $brand-danger !default;
+//** Info progress bar color
+$progress-bar-info-bg:        $brand-info !default;
+
+
+//== List group
+//
+//##
+
+//** Background color on `.list-group-item`
+$list-group-bg:                 #fff !default;
+//** `.list-group-item` border color
+$list-group-border:             #ddd !default;
+//** List group border radius
+$list-group-border-radius:      $border-radius-base !default;
+
+//** Background color of single list items on hover
+$list-group-hover-bg:           #f5f5f5 !default;
+//** Text color of active list items
+$list-group-active-color:       $component-active-color !default;
+//** Background color of active list items
+$list-group-active-bg:          $component-active-bg !default;
+//** Border color of active list elements
+$list-group-active-border:      $list-group-border !default;
+//** Text color for content within active list items
+$list-group-active-text-color:  lighten($list-group-active-bg, 40%) !default;
+
+//** Text color of disabled list items
+$list-group-disabled-color:      $gray-light !default;
+//** Background color of disabled list items
+$list-group-disabled-bg:         $gray-lighter !default;
+//** Text color for content within disabled list items
+$list-group-disabled-text-color: $list-group-disabled-color !default;
+
+$list-group-link-color:         #555 !default;
+$list-group-link-hover-color:   $list-group-link-color !default;
+$list-group-link-heading-color: #333 !default;
+
+
+//== Panels
+//
+//##
+
+$panel-bg:                    #fff !default;
+$panel-body-padding:          15px !default;
+$panel-heading-padding:       10px 15px !default;
+$panel-footer-padding:        $panel-heading-padding !default;
+$panel-border-radius:         $border-radius-base !default;
+
+//** Border color for elements within panels
+$panel-inner-border:          #ddd !default;
+$panel-footer-bg:             #f5f5f5 !default;
+
+$panel-default-text:          $gray-dark !default;
+$panel-default-border:        #ddd !default;
+$panel-default-heading-bg:    #f5f5f5 !default;
+
+$panel-primary-text:          #fff !default;
+$panel-primary-border:        $brand-primary !default;
+$panel-primary-heading-bg:    $brand-primary !default;
+
+$panel-success-text:          $state-success-text !default;
+$panel-success-border:        $state-success-border !default;
+$panel-success-heading-bg:    $state-success-bg !default;
+
+$panel-info-text:             $state-info-text !default;
+$panel-info-border:           $state-info-border !default;
+$panel-info-heading-bg:       $state-info-bg !default;
+
+$panel-warning-text:          $state-warning-text !default;
+$panel-warning-border:        $state-warning-border !default;
+$panel-warning-heading-bg:    $state-warning-bg !default;
+
+$panel-danger-text:           $state-danger-text !default;
+$panel-danger-border:         $state-danger-border !default;
+$panel-danger-heading-bg:     $state-danger-bg !default;
+
+
+//== Thumbnails
+//
+//##
+
+//** Padding around the thumbnail image
+$thumbnail-padding:           4px !default;
+//** Thumbnail background color
+$thumbnail-bg:                $body-bg !default;
+//** Thumbnail border color
+$thumbnail-border:            #ddd !default;
+//** Thumbnail border radius
+$thumbnail-border-radius:     $border-radius-base !default;
+
+//** Custom text color for thumbnail captions
+$thumbnail-caption-color:     $text-color !default;
+//** Padding around the thumbnail caption
+$thumbnail-caption-padding:   9px !default;
+
+
+//== Wells
+//
+//##
+
+$well-bg:                     #f5f5f5 !default;
+$well-border:                 darken($well-bg, 7%) !default;
+
+
+//== Badges
+//
+//##
+
+$badge-color:                 #fff !default;
+//** Linked badge text color on hover
+$badge-link-hover-color:      #fff !default;
+$badge-bg:                    $brand-primary !default;
+
+//** Badge text color in active nav link
+$badge-active-color:          $link-color !default;
+//** Badge background color in active nav link
+$badge-active-bg:             #fff !default;
+
+$badge-font-weight:           bold !default;
+$badge-line-height:           1 !default;
+$badge-border-radius:         10px !default;
+
+
+//== Breadcrumbs
+//
+//##
+
+$breadcrumb-padding-vertical:   8px !default;
+$breadcrumb-padding-horizontal: 15px !default;
+//** Breadcrumb background color
+$breadcrumb-bg:                 #f5f5f5 !default;
+//** Breadcrumb text color
+$breadcrumb-color:              #ccc !default;
+//** Text color of current page in the breadcrumb
+$breadcrumb-active-color:       $gray-light !default;
+//** Textual separator for between breadcrumb elements
+$breadcrumb-separator:          "/" !default;
+
+
+//== Carousel
+//
+//##
+
+$carousel-text-shadow:                        0 1px 2px rgba(0,0,0,.6) !default;
+
+$carousel-control-color:                      #fff !default;
+$carousel-control-width:                      15% !default;
+$carousel-control-opacity:                    .5 !default;
+$carousel-control-font-size:                  20px !default;
+
+$carousel-indicator-active-bg:                #fff !default;
+$carousel-indicator-border-color:             #fff !default;
+
+$carousel-caption-color:                      #fff !default;
+
+
+//== Close
+//
+//##
+
+$close-font-weight:           bold !default;
+$close-color:                 #fff !default;
+$close-text-shadow:           0 1px 0 #fff !default;
+
+
+//== Code
+//
+//##
+
+$code-color:                  #c7254e !default;
+$code-bg:                     #f9f2f4 !default;
+
+$kbd-color:                   #fff !default;
+$kbd-bg:                      #333 !default;
+
+$pre-bg:                      #f5f5f5 !default;
+$pre-color:                   $gray-dark !default;
+$pre-border-color:            #ccc !default;
+$pre-scrollable-max-height:   340px !default;
+
+
+//== Type
+//
+//##
+
+//** Horizontal offset for forms and lists.
+$component-offset-horizontal: 180px !default;
+//** Text muted color
+$text-muted:                  $gray-light !default;
+//** Abbreviations and acronyms border color
+$abbr-border-color:           $gray-light !default;
+//** Headings small color
+$headings-small-color:        $gray-light !default;
+//** Blockquote small color
+$blockquote-small-color:      $gray-light !default;
+//** Blockquote font size
+$blockquote-font-size:        ($font-size-base * 1.25) !default;
+//** Blockquote border color
+$blockquote-border-color:     $gray-lighter !default;
+//** Page header border color
+$page-header-border-color:    $gray-lighter !default;
+//** Width of horizontal description list titles
+$dl-horizontal-offset:        $component-offset-horizontal !default;
+//** Point at which .dl-horizontal becomes horizontal
+$dl-horizontal-breakpoint:    $grid-float-breakpoint !default;
+//** Horizontal line color.
+$hr-border:                   $gray-lighter !default;
diff --git a/modules/cms/src/main/resources/static/modules/cmsfront/themes/default/bootstrap.css b/modules/cms/src/main/resources/static/modules/cmsfront/themes/default/bootstrap.css
new file mode 100644
index 00000000..e2f12373
--- /dev/null
+++ b/modules/cms/src/main/resources/static/modules/cmsfront/themes/default/bootstrap.css
@@ -0,0 +1,6826 @@
+@import url("https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,700");
+/*!
+ * bootswatch v3.4.1
+ * Homepage: http://bootswatch.com
+ * Copyright 2012-2019 Thomas Park
+ * Licensed under MIT
+ * Based on Bootstrap
+*/
+/*!
+ * 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;
+  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 {
+  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"] {
+  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;
+  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;
+    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";
+}
+* {
+  box-sizing: border-box;
+}
+*:before,
+*:after {
+  box-sizing: border-box;
+}
+html {
+  font-size: 10px;
+  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}
+body {
+  font-family: "Source Sans Pro", Calibri, Candara, Arial, sans-serif;
+  font-size: 15px;
+  line-height: 1.42857143;
+  color: #333333;
+  background-color: #ffffff;
+}
+input,
+button,
+select,
+textarea {
+  font-family: inherit;
+  font-size: inherit;
+  line-height: inherit;
+}
+a {
+  color: #2780e3;
+  text-decoration: none;
+}
+a:hover,
+a:focus {
+  color: #165ba8;
+  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: 0;
+}
+.img-thumbnail {
+  padding: 4px;
+  line-height: 1.42857143;
+  background-color: #ffffff;
+  border: 1px solid #dddddd;
+  border-radius: 0;
+  transition: all 0.2s ease-in-out;
+  display: inline-block;
+  max-width: 100%;
+  height: auto;
+}
+.img-circle {
+  border-radius: 50%;
+}
+hr {
+  margin-top: 21px;
+  margin-bottom: 21px;
+  border: 0;
+  border-top: 1px solid #e6e6e6;
+}
+.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: "Source Sans Pro", Calibri, Candara, Arial, sans-serif;
+  font-weight: 300;
+  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: #999999;
+}
+h1,
+.h1,
+h2,
+.h2,
+h3,
+.h3 {
+  margin-top: 21px;
+  margin-bottom: 10.5px;
+}
+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: 10.5px;
+  margin-bottom: 10.5px;
+}
+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: 39px;
+}
+h2,
+.h2 {
+  font-size: 32px;
+}
+h3,
+.h3 {
+  font-size: 26px;
+}
+h4,
+.h4 {
+  font-size: 19px;
+}
+h5,
+.h5 {
+  font-size: 15px;
+}
+h6,
+.h6 {
+  font-size: 13px;
+}
+p {
+  margin: 0 0 10.5px;
+}
+.lead {
+  margin-bottom: 21px;
+  font-size: 17px;
+  font-weight: 300;
+  line-height: 1.4;
+}
+@media (min-width: 768px) {
+  .lead {
+    font-size: 22.5px;
+  }
+}
+small,
+.small {
+  font-size: 86%;
+}
+mark,
+.mark {
+  padding: .2em;
+  background-color: #ff7518;
+}
+.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: #999999;
+}
+.text-primary {
+  color: #2780e3;
+}
+a.text-primary:hover,
+a.text-primary:focus {
+  color: #1967be;
+}
+.text-success {
+  color: #ffffff;
+}
+a.text-success:hover,
+a.text-success:focus {
+  color: #e6e6e6;
+}
+.text-info {
+  color: #ffffff;
+}
+a.text-info:hover,
+a.text-info:focus {
+  color: #e6e6e6;
+}
+.text-warning {
+  color: #ffffff;
+}
+a.text-warning:hover,
+a.text-warning:focus {
+  color: #e6e6e6;
+}
+.text-danger {
+  color: #ffffff;
+}
+a.text-danger:hover,
+a.text-danger:focus {
+  color: #e6e6e6;
+}
+.bg-primary {
+  color: #fff;
+  background-color: #2780e3;
+}
+a.bg-primary:hover,
+a.bg-primary:focus {
+  background-color: #1967be;
+}
+.bg-success {
+  background-color: #3fb618;
+}
+a.bg-success:hover,
+a.bg-success:focus {
+  background-color: #2f8912;
+}
+.bg-info {
+  background-color: #9954bb;
+}
+a.bg-info:hover,
+a.bg-info:focus {
+  background-color: #7e3f9d;
+}
+.bg-warning {
+  background-color: #ff7518;
+}
+a.bg-warning:hover,
+a.bg-warning:focus {
+  background-color: #e45c00;
+}
+.bg-danger {
+  background-color: #ff0039;
+}
+a.bg-danger:hover,
+a.bg-danger:focus {
+  background-color: #cc002e;
+}
+.page-header {
+  padding-bottom: 9.5px;
+  margin: 42px 0 21px;
+  border-bottom: 1px solid #e6e6e6;
+}
+ul,
+ol {
+  margin-top: 0;
+  margin-bottom: 10.5px;
+}
+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: 21px;
+}
+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: 10.5px 21px;
+  margin: 0 0 21px;
+  font-size: 18.75px;
+  border-left: 5px solid #e6e6e6;
+}
+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: #999999;
+}
+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 #e6e6e6;
+  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: 21px;
+  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: 0;
+}
+kbd {
+  padding: 2px 4px;
+  font-size: 90%;
+  color: #ffffff;
+  background-color: #333333;
+  border-radius: 0;
+  box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);
+}
+kbd kbd {
+  padding: 0;
+  font-size: 100%;
+  font-weight: 700;
+  box-shadow: none;
+}
+pre {
+  display: block;
+  padding: 10px;
+  margin: 0 0 10.5px;
+  font-size: 14px;
+  line-height: 1.42857143;
+  color: #333333;
+  word-break: break-all;
+  word-wrap: break-word;
+  background-color: #f5f5f5;
+  border: 1px solid #cccccc;
+  border-radius: 0;
+}
+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: #999999;
+  text-align: left;
+}
+th {
+  text-align: left;
+}
+.table {
+  width: 100%;
+  max-width: 100%;
+  margin-bottom: 21px;
+}
+.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 #dddddd;
+}
+.table > thead > tr > th {
+  vertical-align: bottom;
+  border-bottom: 2px solid #dddddd;
+}
+.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 #dddddd;
+}
+.table .table {
+  background-color: #ffffff;
+}
+.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 #dddddd;
+}
+.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 #dddddd;
+}
+.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: #3fb618;
+}
+.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: #379f15;
+}
+.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: #9954bb;
+}
+.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: #8d46b0;
+}
+.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: #ff7518;
+}
+.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: #fe6600;
+}
+.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: #ff0039;
+}
+.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: #e60033;
+}
+.table-responsive {
+  min-height: .01%;
+  overflow-x: auto;
+}
+@media screen and (max-width: 767px) {
+  .table-responsive {
+    width: 100%;
+    margin-bottom: 15.75px;
+    overflow-y: hidden;
+    -ms-overflow-style: -ms-autohiding-scrollbar;
+    border: 1px solid #dddddd;
+  }
+  .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: 21px;
+  font-size: 22.5px;
+  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"] {
+  box-sizing: border-box;
+  -webkit-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: 11px;
+  font-size: 15px;
+  line-height: 1.42857143;
+  color: #333333;
+}
+.form-control {
+  display: block;
+  width: 100%;
+  height: 43px;
+  padding: 10px 18px;
+  font-size: 15px;
+  line-height: 1.42857143;
+  color: #333333;
+  background-color: #ffffff;
+  background-image: none;
+  border: 1px solid #cccccc;
+  border-radius: 0;
+  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+  transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+}
+.form-control:focus {
+  border-color: #66afe9;
+  outline: 0;
+  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: #999999;
+  opacity: 1;
+}
+.form-control:-ms-input-placeholder {
+  color: #999999;
+}
+.form-control::-webkit-input-placeholder {
+  color: #999999;
+}
+.form-control::-ms-expand {
+  background-color: transparent;
+  border: 0;
+}
+.form-control[disabled],
+.form-control[readonly],
+fieldset[disabled] .form-control {
+  background-color: #e6e6e6;
+  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: 43px;
+  }
+  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: 31px;
+  }
+  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: 64px;
+  }
+}
+.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: 21px;
+  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: 36px;
+  padding-top: 11px;
+  padding-bottom: 11px;
+  margin-bottom: 0;
+}
+.form-control-static.input-lg,
+.form-control-static.input-sm {
+  padding-right: 0;
+  padding-left: 0;
+}
+.input-sm {
+  height: 31px;
+  padding: 5px 10px;
+  font-size: 13px;
+  line-height: 1.5;
+  border-radius: 0;
+}
+select.input-sm {
+  height: 31px;
+  line-height: 31px;
+}
+textarea.input-sm,
+select[multiple].input-sm {
+  height: auto;
+}
+.form-group-sm .form-control {
+  height: 31px;
+  padding: 5px 10px;
+  font-size: 13px;
+  line-height: 1.5;
+  border-radius: 0;
+}
+.form-group-sm select.form-control {
+  height: 31px;
+  line-height: 31px;
+}
+.form-group-sm textarea.form-control,
+.form-group-sm select[multiple].form-control {
+  height: auto;
+}
+.form-group-sm .form-control-static {
+  height: 31px;
+  min-height: 34px;
+  padding: 6px 10px;
+  font-size: 13px;
+  line-height: 1.5;
+}
+.input-lg {
+  height: 64px;
+  padding: 18px 30px;
+  font-size: 19px;
+  line-height: 1.3333333;
+  border-radius: 0;
+}
+select.input-lg {
+  height: 64px;
+  line-height: 64px;
+}
+textarea.input-lg,
+select[multiple].input-lg {
+  height: auto;
+}
+.form-group-lg .form-control {
+  height: 64px;
+  padding: 18px 30px;
+  font-size: 19px;
+  line-height: 1.3333333;
+  border-radius: 0;
+}
+.form-group-lg select.form-control {
+  height: 64px;
+  line-height: 64px;
+}
+.form-group-lg textarea.form-control,
+.form-group-lg select[multiple].form-control {
+  height: auto;
+}
+.form-group-lg .form-control-static {
+  height: 64px;
+  min-height: 40px;
+  padding: 19px 30px;
+  font-size: 19px;
+  line-height: 1.3333333;
+}
+.has-feedback {
+  position: relative;
+}
+.has-feedback .form-control {
+  padding-right: 53.75px;
+}
+.form-control-feedback {
+  position: absolute;
+  top: 0;
+  right: 0;
+  z-index: 2;
+  display: block;
+  width: 43px;
+  height: 43px;
+  line-height: 43px;
+  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: 64px;
+  height: 64px;
+  line-height: 64px;
+}
+.input-sm + .form-control-feedback,
+.input-group-sm + .form-control-feedback,
+.form-group-sm .form-control + .form-control-feedback {
+  width: 31px;
+  height: 31px;
+  line-height: 31px;
+}
+.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: #ffffff;
+}
+.has-success .form-control {
+  border-color: #ffffff;
+  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+.has-success .form-control:focus {
+  border-color: #e6e6e6;
+  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff;
+}
+.has-success .input-group-addon {
+  color: #ffffff;
+  background-color: #3fb618;
+  border-color: #ffffff;
+}
+.has-success .form-control-feedback {
+  color: #ffffff;
+}
+.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: #ffffff;
+}
+.has-warning .form-control {
+  border-color: #ffffff;
+  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+.has-warning .form-control:focus {
+  border-color: #e6e6e6;
+  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff;
+}
+.has-warning .input-group-addon {
+  color: #ffffff;
+  background-color: #ff7518;
+  border-color: #ffffff;
+}
+.has-warning .form-control-feedback {
+  color: #ffffff;
+}
+.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: #ffffff;
+}
+.has-error .form-control {
+  border-color: #ffffff;
+  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+.has-error .form-control:focus {
+  border-color: #e6e6e6;
+  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff;
+}
+.has-error .input-group-addon {
+  color: #ffffff;
+  background-color: #ff0039;
+  border-color: #ffffff;
+}
+.has-error .form-control-feedback {
+  color: #ffffff;
+}
+.has-feedback label ~ .form-control-feedback {
+  top: 26px;
+}
+.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: 11px;
+  margin-top: 0;
+  margin-bottom: 0;
+}
+.form-horizontal .radio,
+.form-horizontal .checkbox {
+  min-height: 32px;
+}
+.form-horizontal .form-group {
+  margin-right: -15px;
+  margin-left: -15px;
+}
+@media (min-width: 768px) {
+  .form-horizontal .control-label {
+    padding-top: 11px;
+    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: 19px;
+    font-size: 19px;
+  }
+}
+@media (min-width: 768px) {
+  .form-horizontal .form-group-sm .control-label {
+    padding-top: 6px;
+    font-size: 13px;
+  }
+}
+.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: 10px 18px;
+  font-size: 15px;
+  line-height: 1.42857143;
+  border-radius: 0;
+  -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: #ffffff;
+  text-decoration: none;
+}
+.btn:active,
+.btn.active {
+  background-image: none;
+  outline: 0;
+  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;
+  box-shadow: none;
+}
+a.btn.disabled,
+fieldset[disabled] a.btn {
+  pointer-events: none;
+}
+.btn-default {
+  color: #ffffff;
+  background-color: #222222;
+  border-color: #222222;
+}
+.btn-default:focus,
+.btn-default.focus {
+  color: #ffffff;
+  background-color: #090909;
+  border-color: #000000;
+}
+.btn-default:hover {
+  color: #ffffff;
+  background-color: #090909;
+  border-color: #040404;
+}
+.btn-default:active,
+.btn-default.active,
+.open > .dropdown-toggle.btn-default {
+  color: #ffffff;
+  background-color: #090909;
+  background-image: none;
+  border-color: #040404;
+}
+.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: #ffffff;
+  background-color: #000000;
+  border-color: #000000;
+}
+.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: #222222;
+  border-color: #222222;
+}
+.btn-default .badge {
+  color: #222222;
+  background-color: #ffffff;
+}
+.btn-primary {
+  color: #ffffff;
+  background-color: #2780e3;
+  border-color: #2780e3;
+}
+.btn-primary:focus,
+.btn-primary.focus {
+  color: #ffffff;
+  background-color: #1967be;
+  border-color: #10427b;
+}
+.btn-primary:hover {
+  color: #ffffff;
+  background-color: #1967be;
+  border-color: #1862b5;
+}
+.btn-primary:active,
+.btn-primary.active,
+.open > .dropdown-toggle.btn-primary {
+  color: #ffffff;
+  background-color: #1967be;
+  background-image: none;
+  border-color: #1862b5;
+}
+.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: #ffffff;
+  background-color: #15569f;
+  border-color: #10427b;
+}
+.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: #2780e3;
+  border-color: #2780e3;
+}
+.btn-primary .badge {
+  color: #2780e3;
+  background-color: #ffffff;
+}
+.btn-success {
+  color: #ffffff;
+  background-color: #3fb618;
+  border-color: #3fb618;
+}
+.btn-success:focus,
+.btn-success.focus {
+  color: #ffffff;
+  background-color: #2f8912;
+  border-color: #184509;
+}
+.btn-success:hover {
+  color: #ffffff;
+  background-color: #2f8912;
+  border-color: #2c8011;
+}
+.btn-success:active,
+.btn-success.active,
+.open > .dropdown-toggle.btn-success {
+  color: #ffffff;
+  background-color: #2f8912;
+  background-image: none;
+  border-color: #2c8011;
+}
+.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: #ffffff;
+  background-color: #24690e;
+  border-color: #184509;
+}
+.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: #3fb618;
+  border-color: #3fb618;
+}
+.btn-success .badge {
+  color: #3fb618;
+  background-color: #ffffff;
+}
+.btn-info {
+  color: #ffffff;
+  background-color: #9954bb;
+  border-color: #9954bb;
+}
+.btn-info:focus,
+.btn-info.focus {
+  color: #ffffff;
+  background-color: #7e3f9d;
+  border-color: #522967;
+}
+.btn-info:hover {
+  color: #ffffff;
+  background-color: #7e3f9d;
+  border-color: #783c96;
+}
+.btn-info:active,
+.btn-info.active,
+.open > .dropdown-toggle.btn-info {
+  color: #ffffff;
+  background-color: #7e3f9d;
+  background-image: none;
+  border-color: #783c96;
+}
+.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: #ffffff;
+  background-color: #6a3484;
+  border-color: #522967;
+}
+.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: #9954bb;
+  border-color: #9954bb;
+}
+.btn-info .badge {
+  color: #9954bb;
+  background-color: #ffffff;
+}
+.btn-warning {
+  color: #ffffff;
+  background-color: #ff7518;
+  border-color: #ff7518;
+}
+.btn-warning:focus,
+.btn-warning.focus {
+  color: #ffffff;
+  background-color: #e45c00;
+  border-color: #983d00;
+}
+.btn-warning:hover {
+  color: #ffffff;
+  background-color: #e45c00;
+  border-color: #da5800;
+}
+.btn-warning:active,
+.btn-warning.active,
+.open > .dropdown-toggle.btn-warning {
+  color: #ffffff;
+  background-color: #e45c00;
+  background-image: none;
+  border-color: #da5800;
+}
+.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: #ffffff;
+  background-color: #c04d00;
+  border-color: #983d00;
+}
+.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: #ff7518;
+  border-color: #ff7518;
+}
+.btn-warning .badge {
+  color: #ff7518;
+  background-color: #ffffff;
+}
+.btn-danger {
+  color: #ffffff;
+  background-color: #ff0039;
+  border-color: #ff0039;
+}
+.btn-danger:focus,
+.btn-danger.focus {
+  color: #ffffff;
+  background-color: #cc002e;
+  border-color: #80001c;
+}
+.btn-danger:hover {
+  color: #ffffff;
+  background-color: #cc002e;
+  border-color: #c2002b;
+}
+.btn-danger:active,
+.btn-danger.active,
+.open > .dropdown-toggle.btn-danger {
+  color: #ffffff;
+  background-color: #cc002e;
+  background-image: none;
+  border-color: #c2002b;
+}
+.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: #ffffff;
+  background-color: #a80026;
+  border-color: #80001c;
+}
+.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: #ff0039;
+  border-color: #ff0039;
+}
+.btn-danger .badge {
+  color: #ff0039;
+  background-color: #ffffff;
+}
+.btn-link {
+  font-weight: 400;
+  color: #2780e3;
+  border-radius: 0;
+}
+.btn-link,
+.btn-link:active,
+.btn-link.active,
+.btn-link[disabled],
+fieldset[disabled] .btn-link {
+  background-color: transparent;
+  box-shadow: none;
+}
+.btn-link,
+.btn-link:hover,
+.btn-link:focus,
+.btn-link:active {
+  border-color: transparent;
+}
+.btn-link:hover,
+.btn-link:focus {
+  color: #165ba8;
+  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: #999999;
+  text-decoration: none;
+}
+.btn-lg,
+.btn-group-lg > .btn {
+  padding: 18px 30px;
+  font-size: 19px;
+  line-height: 1.3333333;
+  border-radius: 0;
+}
+.btn-sm,
+.btn-group-sm > .btn {
+  padding: 5px 10px;
+  font-size: 13px;
+  line-height: 1.5;
+  border-radius: 0;
+}
+.btn-xs,
+.btn-group-xs > .btn {
+  padding: 1px 5px;
+  font-size: 13px;
+  line-height: 1.5;
+  border-radius: 0;
+}
+.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;
+  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;
+  transition-property: height, visibility;
+  transition-duration: 0.35s;
+  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: 15px;
+  text-align: left;
+  list-style: none;
+  background-color: #ffffff;
+  background-clip: padding-box;
+  border: 1px solid #cccccc;
+  border: 1px solid rgba(0, 0, 0, 0.15);
+  border-radius: 0;
+  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: 9.5px 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: #ffffff;
+  text-decoration: none;
+  background-color: #2780e3;
+}
+.dropdown-menu > .active > a,
+.dropdown-menu > .active > a:hover,
+.dropdown-menu > .active > a:focus {
+  color: #ffffff;
+  text-decoration: none;
+  background-color: #2780e3;
+  outline: 0;
+}
+.dropdown-menu > .disabled > a,
+.dropdown-menu > .disabled > a:hover,
+.dropdown-menu > .disabled > a:focus {
+  color: #999999;
+}
+.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: 13px;
+  line-height: 1.42857143;
+  color: #999999;
+  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 {
+  box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+}
+.btn-group.open .dropdown-toggle.btn-link {
+  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: 0;
+  border-top-right-radius: 0;
+  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: 0;
+  border-bottom-left-radius: 0;
+}
+.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: 64px;
+  padding: 18px 30px;
+  font-size: 19px;
+  line-height: 1.3333333;
+  border-radius: 0;
+}
+select.input-group-lg > .form-control,
+select.input-group-lg > .input-group-addon,
+select.input-group-lg > .input-group-btn > .btn {
+  height: 64px;
+  line-height: 64px;
+}
+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: 31px;
+  padding: 5px 10px;
+  font-size: 13px;
+  line-height: 1.5;
+  border-radius: 0;
+}
+select.input-group-sm > .form-control,
+select.input-group-sm > .input-group-addon,
+select.input-group-sm > .input-group-btn > .btn {
+  height: 31px;
+  line-height: 31px;
+}
+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: 10px 18px;
+  font-size: 15px;
+  font-weight: 400;
+  line-height: 1;
+  color: #333333;
+  text-align: center;
+  background-color: #e6e6e6;
+  border: 1px solid #cccccc;
+  border-radius: 0;
+}
+.input-group-addon.input-sm {
+  padding: 5px 10px;
+  font-size: 13px;
+  border-radius: 0;
+}
+.input-group-addon.input-lg {
+  padding: 18px 30px;
+  font-size: 19px;
+  border-radius: 0;
+}
+.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: #e6e6e6;
+}
+.nav > li.disabled > a {
+  color: #999999;
+}
+.nav > li.disabled > a:hover,
+.nav > li.disabled > a:focus {
+  color: #999999;
+  text-decoration: none;
+  cursor: not-allowed;
+  background-color: transparent;
+}
+.nav .open > a,
+.nav .open > a:hover,
+.nav .open > a:focus {
+  background-color: #e6e6e6;
+  border-color: #2780e3;
+}
+.nav .nav-divider {
+  height: 1px;
+  margin: 9.5px 0;
+  overflow: hidden;
+  background-color: #e5e5e5;
+}
+.nav > li > a > img {
+  max-width: none;
+}
+.nav-tabs {
+  border-bottom: 1px solid #dddddd;
+}
+.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: 0 0 0 0;
+}
+.nav-tabs > li > a:hover {
+  border-color: #e6e6e6 #e6e6e6 #dddddd;
+}
+.nav-tabs > li.active > a,
+.nav-tabs > li.active > a:hover,
+.nav-tabs > li.active > a:focus {
+  color: #555555;
+  cursor: default;
+  background-color: #ffffff;
+  border: 1px solid #dddddd;
+  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: 0;
+}
+.nav-tabs.nav-justified > .active > a,
+.nav-tabs.nav-justified > .active > a:hover,
+.nav-tabs.nav-justified > .active > a:focus {
+  border: 1px solid #dddddd;
+}
+@media (min-width: 768px) {
+  .nav-tabs.nav-justified > li > a {
+    border-bottom: 1px solid #dddddd;
+    border-radius: 0 0 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: #ffffff;
+  }
+}
+.nav-pills > li {
+  float: left;
+}
+.nav-pills > li > a {
+  border-radius: 0;
+}
+.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: #ffffff;
+  background-color: #2780e3;
+}
+.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: 0;
+}
+.nav-tabs-justified > .active > a,
+.nav-tabs-justified > .active > a:hover,
+.nav-tabs-justified > .active > a:focus {
+  border: 1px solid #dddddd;
+}
+@media (min-width: 768px) {
+  .nav-tabs-justified > li > a {
+    border-bottom: 1px solid #dddddd;
+    border-radius: 0 0 0 0;
+  }
+  .nav-tabs-justified > .active > a,
+  .nav-tabs-justified > .active > a:hover,
+  .nav-tabs-justified > .active > a:focus {
+    border-bottom-color: #ffffff;
+  }
+}
+.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: 21px;
+  border: 1px solid transparent;
+}
+@media (min-width: 768px) {
+  .navbar {
+    border-radius: 0;
+  }
+}
+@media (min-width: 768px) {
+  .navbar-header {
+    float: left;
+  }
+}
+.navbar-collapse {
+  padding-right: 15px;
+  padding-left: 15px;
+  overflow-x: visible;
+  border-top: 1px solid transparent;
+  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;
+    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: 14.5px 15px;
+  font-size: 19px;
+  line-height: 21px;
+}
+.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: 0;
+}
+.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.25px -15px;
+}
+.navbar-nav > li > a {
+  padding-top: 10px;
+  padding-bottom: 10px;
+  line-height: 21px;
+}
+@media (max-width: 767px) {
+  .navbar-nav .open .dropdown-menu {
+    position: static;
+    float: none;
+    width: auto;
+    margin-top: 0;
+    background-color: transparent;
+    border: 0;
+    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: 21px;
+  }
+  .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: 14.5px;
+    padding-bottom: 14.5px;
+  }
+}
+.navbar-form {
+  padding: 10px 15px;
+  margin-right: -15px;
+  margin-left: -15px;
+  border-top: 1px solid transparent;
+  border-bottom: 1px solid transparent;
+  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
+  margin-top: 3.5px;
+  margin-bottom: 3.5px;
+}
+@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;
+    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: 0;
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+}
+.navbar-btn {
+  margin-top: 3.5px;
+  margin-bottom: 3.5px;
+}
+.navbar-btn.btn-sm {
+  margin-top: 9.5px;
+  margin-bottom: 9.5px;
+}
+.navbar-btn.btn-xs {
+  margin-top: 14px;
+  margin-bottom: 14px;
+}
+.navbar-text {
+  margin-top: 14.5px;
+  margin-bottom: 14.5px;
+}
+@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: #222222;
+  border-color: #121212;
+}
+.navbar-default .navbar-brand {
+  color: #ffffff;
+}
+.navbar-default .navbar-brand:hover,
+.navbar-default .navbar-brand:focus {
+  color: #ffffff;
+  background-color: none;
+}
+.navbar-default .navbar-text {
+  color: #ffffff;
+}
+.navbar-default .navbar-nav > li > a {
+  color: #ffffff;
+}
+.navbar-default .navbar-nav > li > a:hover,
+.navbar-default .navbar-nav > li > a:focus {
+  color: #ffffff;
+  background-color: #090909;
+}
+.navbar-default .navbar-nav > .active > a,
+.navbar-default .navbar-nav > .active > a:hover,
+.navbar-default .navbar-nav > .active > a:focus {
+  color: #ffffff;
+  background-color: #090909;
+}
+.navbar-default .navbar-nav > .disabled > a,
+.navbar-default .navbar-nav > .disabled > a:hover,
+.navbar-default .navbar-nav > .disabled > a:focus {
+  color: #cccccc;
+  background-color: transparent;
+}
+.navbar-default .navbar-nav > .open > a,
+.navbar-default .navbar-nav > .open > a:hover,
+.navbar-default .navbar-nav > .open > a:focus {
+  color: #ffffff;
+  background-color: #090909;
+}
+@media (max-width: 767px) {
+  .navbar-default .navbar-nav .open .dropdown-menu > li > a {
+    color: #ffffff;
+  }
+  .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,
+  .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {
+    color: #ffffff;
+    background-color: #090909;
+  }
+  .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: #ffffff;
+    background-color: #090909;
+  }
+  .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: #cccccc;
+    background-color: transparent;
+  }
+}
+.navbar-default .navbar-toggle {
+  border-color: transparent;
+}
+.navbar-default .navbar-toggle:hover,
+.navbar-default .navbar-toggle:focus {
+  background-color: #090909;
+}
+.navbar-default .navbar-toggle .icon-bar {
+  background-color: #ffffff;
+}
+.navbar-default .navbar-collapse,
+.navbar-default .navbar-form {
+  border-color: #121212;
+}
+.navbar-default .navbar-link {
+  color: #ffffff;
+}
+.navbar-default .navbar-link:hover {
+  color: #ffffff;
+}
+.navbar-default .btn-link {
+  color: #ffffff;
+}
+.navbar-default .btn-link:hover,
+.navbar-default .btn-link:focus {
+  color: #ffffff;
+}
+.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: #cccccc;
+}
+.navbar-inverse {
+  background-color: #2780e3;
+  border-color: #1967be;
+}
+.navbar-inverse .navbar-brand {
+  color: #ffffff;
+}
+.navbar-inverse .navbar-brand:hover,
+.navbar-inverse .navbar-brand:focus {
+  color: #ffffff;
+  background-color: none;
+}
+.navbar-inverse .navbar-text {
+  color: #ffffff;
+}
+.navbar-inverse .navbar-nav > li > a {
+  color: #ffffff;
+}
+.navbar-inverse .navbar-nav > li > a:hover,
+.navbar-inverse .navbar-nav > li > a:focus {
+  color: #ffffff;
+  background-color: #1967be;
+}
+.navbar-inverse .navbar-nav > .active > a,
+.navbar-inverse .navbar-nav > .active > a:hover,
+.navbar-inverse .navbar-nav > .active > a:focus {
+  color: #ffffff;
+  background-color: #1967be;
+}
+.navbar-inverse .navbar-nav > .disabled > a,
+.navbar-inverse .navbar-nav > .disabled > a:hover,
+.navbar-inverse .navbar-nav > .disabled > a:focus {
+  color: #ffffff;
+  background-color: transparent;
+}
+.navbar-inverse .navbar-nav > .open > a,
+.navbar-inverse .navbar-nav > .open > a:hover,
+.navbar-inverse .navbar-nav > .open > a:focus {
+  color: #ffffff;
+  background-color: #1967be;
+}
+@media (max-width: 767px) {
+  .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {
+    border-color: #1967be;
+  }
+  .navbar-inverse .navbar-nav .open .dropdown-menu .divider {
+    background-color: #1967be;
+  }
+  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {
+    color: #ffffff;
+  }
+  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,
+  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {
+    color: #ffffff;
+    background-color: #1967be;
+  }
+  .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: #ffffff;
+    background-color: #1967be;
+  }
+  .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: #ffffff;
+    background-color: transparent;
+  }
+}
+.navbar-inverse .navbar-toggle {
+  border-color: transparent;
+}
+.navbar-inverse .navbar-toggle:hover,
+.navbar-inverse .navbar-toggle:focus {
+  background-color: #1967be;
+}
+.navbar-inverse .navbar-toggle .icon-bar {
+  background-color: #ffffff;
+}
+.navbar-inverse .navbar-collapse,
+.navbar-inverse .navbar-form {
+  border-color: #1a6ecc;
+}
+.navbar-inverse .navbar-link {
+  color: #ffffff;
+}
+.navbar-inverse .navbar-link:hover {
+  color: #ffffff;
+}
+.navbar-inverse .btn-link {
+  color: #ffffff;
+}
+.navbar-inverse .btn-link:hover,
+.navbar-inverse .btn-link:focus {
+  color: #ffffff;
+}
+.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: #ffffff;
+}
+.breadcrumb {
+  padding: 8px 15px;
+  margin-bottom: 21px;
+  list-style: none;
+  background-color: #f5f5f5;
+  border-radius: 0;
+}
+.breadcrumb > li {
+  display: inline-block;
+}
+.breadcrumb > li + li:before {
+  padding: 0 5px;
+  color: #cccccc;
+  content: "/\00a0";
+}
+.breadcrumb > .active {
+  color: #999999;
+}
+.pagination {
+  display: inline-block;
+  padding-left: 0;
+  margin: 21px 0;
+  border-radius: 0;
+}
+.pagination > li {
+  display: inline;
+}
+.pagination > li > a,
+.pagination > li > span {
+  position: relative;
+  float: left;
+  padding: 10px 18px;
+  margin-left: -1px;
+  line-height: 1.42857143;
+  color: #2780e3;
+  text-decoration: none;
+  background-color: #ffffff;
+  border: 1px solid #dddddd;
+}
+.pagination > li > a:hover,
+.pagination > li > span:hover,
+.pagination > li > a:focus,
+.pagination > li > span:focus {
+  z-index: 2;
+  color: #165ba8;
+  background-color: #e6e6e6;
+  border-color: #dddddd;
+}
+.pagination > li:first-child > a,
+.pagination > li:first-child > span {
+  margin-left: 0;
+  border-top-left-radius: 0;
+  border-bottom-left-radius: 0;
+}
+.pagination > li:last-child > a,
+.pagination > li:last-child > span {
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 0;
+}
+.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: #999999;
+  cursor: default;
+  background-color: #f5f5f5;
+  border-color: #dddddd;
+}
+.pagination > .disabled > span,
+.pagination > .disabled > span:hover,
+.pagination > .disabled > span:focus,
+.pagination > .disabled > a,
+.pagination > .disabled > a:hover,
+.pagination > .disabled > a:focus {
+  color: #999999;
+  cursor: not-allowed;
+  background-color: #ffffff;
+  border-color: #dddddd;
+}
+.pagination-lg > li > a,
+.pagination-lg > li > span {
+  padding: 18px 30px;
+  font-size: 19px;
+  line-height: 1.3333333;
+}
+.pagination-lg > li:first-child > a,
+.pagination-lg > li:first-child > span {
+  border-top-left-radius: 0;
+  border-bottom-left-radius: 0;
+}
+.pagination-lg > li:last-child > a,
+.pagination-lg > li:last-child > span {
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 0;
+}
+.pagination-sm > li > a,
+.pagination-sm > li > span {
+  padding: 5px 10px;
+  font-size: 13px;
+  line-height: 1.5;
+}
+.pagination-sm > li:first-child > a,
+.pagination-sm > li:first-child > span {
+  border-top-left-radius: 0;
+  border-bottom-left-radius: 0;
+}
+.pagination-sm > li:last-child > a,
+.pagination-sm > li:last-child > span {
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 0;
+}
+.pager {
+  padding-left: 0;
+  margin: 21px 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: #ffffff;
+  border: 1px solid #dddddd;
+  border-radius: 0;
+}
+.pager li > a:hover,
+.pager li > a:focus {
+  text-decoration: none;
+  background-color: #e6e6e6;
+}
+.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: #999999;
+  cursor: not-allowed;
+  background-color: #ffffff;
+}
+.label {
+  display: inline;
+  padding: .2em .6em .3em;
+  font-size: 75%;
+  font-weight: 700;
+  line-height: 1;
+  color: #ffffff;
+  text-align: center;
+  white-space: nowrap;
+  vertical-align: baseline;
+  border-radius: .25em;
+}
+a.label:hover,
+a.label:focus {
+  color: #ffffff;
+  text-decoration: none;
+  cursor: pointer;
+}
+.label:empty {
+  display: none;
+}
+.btn .label {
+  position: relative;
+  top: -1px;
+}
+.label-default {
+  background-color: #222222;
+}
+.label-default[href]:hover,
+.label-default[href]:focus {
+  background-color: #090909;
+}
+.label-primary {
+  background-color: #2780e3;
+}
+.label-primary[href]:hover,
+.label-primary[href]:focus {
+  background-color: #1967be;
+}
+.label-success {
+  background-color: #3fb618;
+}
+.label-success[href]:hover,
+.label-success[href]:focus {
+  background-color: #2f8912;
+}
+.label-info {
+  background-color: #9954bb;
+}
+.label-info[href]:hover,
+.label-info[href]:focus {
+  background-color: #7e3f9d;
+}
+.label-warning {
+  background-color: #ff7518;
+}
+.label-warning[href]:hover,
+.label-warning[href]:focus {
+  background-color: #e45c00;
+}
+.label-danger {
+  background-color: #ff0039;
+}
+.label-danger[href]:hover,
+.label-danger[href]:focus {
+  background-color: #cc002e;
+}
+.badge {
+  display: inline-block;
+  min-width: 10px;
+  padding: 3px 7px;
+  font-size: 13px;
+  font-weight: bold;
+  line-height: 1;
+  color: #ffffff;
+  text-align: center;
+  white-space: nowrap;
+  vertical-align: middle;
+  background-color: #2780e3;
+  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: #ffffff;
+  text-decoration: none;
+  cursor: pointer;
+}
+.list-group-item.active > .badge,
+.nav-pills > .active > a > .badge {
+  color: #2780e3;
+  background-color: #ffffff;
+}
+.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: #e6e6e6;
+}
+.jumbotron h1,
+.jumbotron .h1 {
+  color: inherit;
+}
+.jumbotron p {
+  margin-bottom: 15px;
+  font-size: 23px;
+  font-weight: 200;
+}
+.jumbotron > hr {
+  border-top-color: #cccccc;
+}
+.container .jumbotron,
+.container-fluid .jumbotron {
+  padding-right: 15px;
+  padding-left: 15px;
+  border-radius: 0;
+}
+.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: 68px;
+  }
+}
+.thumbnail {
+  display: block;
+  padding: 4px;
+  margin-bottom: 21px;
+  line-height: 1.42857143;
+  background-color: #ffffff;
+  border: 1px solid #dddddd;
+  border-radius: 0;
+  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: #2780e3;
+}
+.thumbnail .caption {
+  padding: 9px;
+  color: #333333;
+}
+.alert {
+  padding: 15px;
+  margin-bottom: 21px;
+  border: 1px solid transparent;
+  border-radius: 0;
+}
+.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: #ffffff;
+  background-color: #3fb618;
+  border-color: #4e9f15;
+}
+.alert-success hr {
+  border-top-color: #438912;
+}
+.alert-success .alert-link {
+  color: #e6e6e6;
+}
+.alert-info {
+  color: #ffffff;
+  background-color: #9954bb;
+  border-color: #7643a8;
+}
+.alert-info hr {
+  border-top-color: #693c96;
+}
+.alert-info .alert-link {
+  color: #e6e6e6;
+}
+.alert-warning {
+  color: #ffffff;
+  background-color: #ff7518;
+  border-color: #ff4309;
+}
+.alert-warning hr {
+  border-top-color: #ee3800;
+}
+.alert-warning .alert-link {
+  color: #e6e6e6;
+}
+.alert-danger {
+  color: #ffffff;
+  background-color: #ff0039;
+  border-color: #f0005e;
+}
+.alert-danger hr {
+  border-top-color: #d60054;
+}
+.alert-danger .alert-link {
+  color: #e6e6e6;
+}
+@-webkit-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: 21px;
+  margin-bottom: 21px;
+  overflow: hidden;
+  background-color: #cccccc;
+  border-radius: 0;
+  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
+}
+.progress-bar {
+  float: left;
+  width: 0%;
+  height: 100%;
+  font-size: 13px;
+  line-height: 21px;
+  color: #ffffff;
+  text-align: center;
+  background-color: #2780e3;
+  box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+  transition: width 0.6s ease;
+}
+.progress-striped .progress-bar,
+.progress-bar-striped {
+  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);
+  background-size: 40px 40px;
+}
+.progress.active .progress-bar,
+.progress-bar.active {
+  -webkit-animation: progress-bar-stripes 2s linear infinite;
+  animation: progress-bar-stripes 2s linear infinite;
+}
+.progress-bar-success {
+  background-color: #3fb618;
+}
+.progress-striped .progress-bar-success {
+  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: #9954bb;
+}
+.progress-striped .progress-bar-info {
+  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: #ff7518;
+}
+.progress-striped .progress-bar-warning {
+  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: #ff0039;
+}
+.progress-striped .progress-bar-danger {
+  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: #ffffff;
+  border: 1px solid #dddddd;
+}
+.list-group-item:first-child {
+  border-top-left-radius: 0;
+  border-top-right-radius: 0;
+}
+.list-group-item:last-child {
+  margin-bottom: 0;
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+}
+.list-group-item.disabled,
+.list-group-item.disabled:hover,
+.list-group-item.disabled:focus {
+  color: #999999;
+  cursor: not-allowed;
+  background-color: #e6e6e6;
+}
+.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: #999999;
+}
+.list-group-item.active,
+.list-group-item.active:hover,
+.list-group-item.active:focus {
+  z-index: 2;
+  color: #ffffff;
+  background-color: #2780e3;
+  border-color: #dddddd;
+}
+.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: #dceafa;
+}
+a.list-group-item,
+button.list-group-item {
+  color: #555555;
+}
+a.list-group-item .list-group-item-heading,
+button.list-group-item .list-group-item-heading {
+  color: #333333;
+}
+a.list-group-item:hover,
+button.list-group-item:hover,
+a.list-group-item:focus,
+button.list-group-item:focus {
+  color: #555555;
+  text-decoration: none;
+  background-color: #f5f5f5;
+}
+button.list-group-item {
+  width: 100%;
+  text-align: left;
+}
+.list-group-item-success {
+  color: #ffffff;
+  background-color: #3fb618;
+}
+a.list-group-item-success,
+button.list-group-item-success {
+  color: #ffffff;
+}
+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: #ffffff;
+  background-color: #379f15;
+}
+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: #ffffff;
+  border-color: #ffffff;
+}
+.list-group-item-info {
+  color: #ffffff;
+  background-color: #9954bb;
+}
+a.list-group-item-info,
+button.list-group-item-info {
+  color: #ffffff;
+}
+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: #ffffff;
+  background-color: #8d46b0;
+}
+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: #ffffff;
+  border-color: #ffffff;
+}
+.list-group-item-warning {
+  color: #ffffff;
+  background-color: #ff7518;
+}
+a.list-group-item-warning,
+button.list-group-item-warning {
+  color: #ffffff;
+}
+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: #ffffff;
+  background-color: #fe6600;
+}
+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: #ffffff;
+  border-color: #ffffff;
+}
+.list-group-item-danger {
+  color: #ffffff;
+  background-color: #ff0039;
+}
+a.list-group-item-danger,
+button.list-group-item-danger {
+  color: #ffffff;
+}
+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: #ffffff;
+  background-color: #e60033;
+}
+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: #ffffff;
+  border-color: #ffffff;
+}
+.list-group-item-heading {
+  margin-top: 0;
+  margin-bottom: 5px;
+}
+.list-group-item-text {
+  margin-bottom: 0;
+  line-height: 1.3;
+}
+.panel {
+  margin-bottom: 21px;
+  background-color: #ffffff;
+  border: 1px solid transparent;
+  border-radius: 0;
+  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: -1;
+  border-top-right-radius: -1;
+}
+.panel-heading > .dropdown .dropdown-toggle {
+  color: inherit;
+}
+.panel-title {
+  margin-top: 0;
+  margin-bottom: 0;
+  font-size: 17px;
+  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 #dddddd;
+  border-bottom-right-radius: -1;
+  border-bottom-left-radius: -1;
+}
+.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: -1;
+  border-top-right-radius: -1;
+}
+.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: -1;
+  border-bottom-left-radius: -1;
+}
+.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: -1;
+  border-top-right-radius: -1;
+}
+.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: -1;
+  border-top-right-radius: -1;
+}
+.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: -1;
+}
+.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: -1;
+}
+.panel > .table:last-child,
+.panel > .table-responsive:last-child > .table:last-child {
+  border-bottom-right-radius: -1;
+  border-bottom-left-radius: -1;
+}
+.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: -1;
+  border-bottom-left-radius: -1;
+}
+.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: -1;
+}
+.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: -1;
+}
+.panel > .panel-body + .table,
+.panel > .panel-body + .table-responsive,
+.panel > .table + .panel-body,
+.panel > .table-responsive + .panel-body {
+  border-top: 1px solid #dddddd;
+}
+.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: 21px;
+}
+.panel-group .panel {
+  margin-bottom: 0;
+  border-radius: 0;
+}
+.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 #dddddd;
+}
+.panel-group .panel-footer {
+  border-top: 0;
+}
+.panel-group .panel-footer + .panel-collapse .panel-body {
+  border-bottom: 1px solid #dddddd;
+}
+.panel-default {
+  border-color: #dddddd;
+}
+.panel-default > .panel-heading {
+  color: #333333;
+  background-color: #f5f5f5;
+  border-color: #dddddd;
+}
+.panel-default > .panel-heading + .panel-collapse > .panel-body {
+  border-top-color: #dddddd;
+}
+.panel-default > .panel-heading .badge {
+  color: #f5f5f5;
+  background-color: #333333;
+}
+.panel-default > .panel-footer + .panel-collapse > .panel-body {
+  border-bottom-color: #dddddd;
+}
+.panel-primary {
+  border-color: #2780e3;
+}
+.panel-primary > .panel-heading {
+  color: #ffffff;
+  background-color: #2780e3;
+  border-color: #2780e3;
+}
+.panel-primary > .panel-heading + .panel-collapse > .panel-body {
+  border-top-color: #2780e3;
+}
+.panel-primary > .panel-heading .badge {
+  color: #2780e3;
+  background-color: #ffffff;
+}
+.panel-primary > .panel-footer + .panel-collapse > .panel-body {
+  border-bottom-color: #2780e3;
+}
+.panel-success {
+  border-color: #4e9f15;
+}
+.panel-success > .panel-heading {
+  color: #ffffff;
+  background-color: #3fb618;
+  border-color: #4e9f15;
+}
+.panel-success > .panel-heading + .panel-collapse > .panel-body {
+  border-top-color: #4e9f15;
+}
+.panel-success > .panel-heading .badge {
+  color: #3fb618;
+  background-color: #ffffff;
+}
+.panel-success > .panel-footer + .panel-collapse > .panel-body {
+  border-bottom-color: #4e9f15;
+}
+.panel-info {
+  border-color: #7643a8;
+}
+.panel-info > .panel-heading {
+  color: #ffffff;
+  background-color: #9954bb;
+  border-color: #7643a8;
+}
+.panel-info > .panel-heading + .panel-collapse > .panel-body {
+  border-top-color: #7643a8;
+}
+.panel-info > .panel-heading .badge {
+  color: #9954bb;
+  background-color: #ffffff;
+}
+.panel-info > .panel-footer + .panel-collapse > .panel-body {
+  border-bottom-color: #7643a8;
+}
+.panel-warning {
+  border-color: #ff4309;
+}
+.panel-warning > .panel-heading {
+  color: #ffffff;
+  background-color: #ff7518;
+  border-color: #ff4309;
+}
+.panel-warning > .panel-heading + .panel-collapse > .panel-body {
+  border-top-color: #ff4309;
+}
+.panel-warning > .panel-heading .badge {
+  color: #ff7518;
+  background-color: #ffffff;
+}
+.panel-warning > .panel-footer + .panel-collapse > .panel-body {
+  border-bottom-color: #ff4309;
+}
+.panel-danger {
+  border-color: #f0005e;
+}
+.panel-danger > .panel-heading {
+  color: #ffffff;
+  background-color: #ff0039;
+  border-color: #f0005e;
+}
+.panel-danger > .panel-heading + .panel-collapse > .panel-body {
+  border-top-color: #f0005e;
+}
+.panel-danger > .panel-heading .badge {
+  color: #ff0039;
+  background-color: #ffffff;
+}
+.panel-danger > .panel-footer + .panel-collapse > .panel-body {
+  border-bottom-color: #f0005e;
+}
+.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: 0;
+  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: 0;
+}
+.well-sm {
+  padding: 9px;
+  border-radius: 0;
+}
+.close {
+  float: right;
+  font-size: 22.5px;
+  font-weight: bold;
+  line-height: 1;
+  color: #ffffff;
+  text-shadow: 0 1px 0 #ffffff;
+  filter: alpha(opacity=20);
+  opacity: 0.2;
+}
+.close:hover,
+.close:focus {
+  color: #ffffff;
+  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;
+  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%);
+  transform: translate(0, -25%);
+  transition: -webkit-transform 0.3s ease-out;
+  transition: transform 0.3s ease-out;
+}
+.modal.in .modal-dialog {
+  -webkit-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: #ffffff;
+  background-clip: padding-box;
+  border: 1px solid #999999;
+  border: 1px solid transparent;
+  border-radius: 0;
+  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: #000000;
+}
+.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: 20px;
+}
+.modal-footer {
+  padding: 20px;
+  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 {
+    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: "Source Sans Pro", Calibri, Candara, 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: 13px;
+  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: #000000;
+}
+.tooltip.top-left .tooltip-arrow {
+  right: 5px;
+  bottom: 0;
+  margin-bottom: -5px;
+  border-width: 5px 5px 0;
+  border-top-color: #000000;
+}
+.tooltip.top-right .tooltip-arrow {
+  bottom: 0;
+  left: 5px;
+  margin-bottom: -5px;
+  border-width: 5px 5px 0;
+  border-top-color: #000000;
+}
+.tooltip.right .tooltip-arrow {
+  top: 50%;
+  left: 0;
+  margin-top: -5px;
+  border-width: 5px 5px 5px 0;
+  border-right-color: #000000;
+}
+.tooltip.left .tooltip-arrow {
+  top: 50%;
+  right: 0;
+  margin-top: -5px;
+  border-width: 5px 0 5px 5px;
+  border-left-color: #000000;
+}
+.tooltip.bottom .tooltip-arrow {
+  top: 0;
+  left: 50%;
+  margin-left: -5px;
+  border-width: 0 5px 5px;
+  border-bottom-color: #000000;
+}
+.tooltip.bottom-left .tooltip-arrow {
+  top: 0;
+  right: 5px;
+  margin-top: -5px;
+  border-width: 0 5px 5px;
+  border-bottom-color: #000000;
+}
+.tooltip.bottom-right .tooltip-arrow {
+  top: 0;
+  left: 5px;
+  margin-top: -5px;
+  border-width: 0 5px 5px;
+  border-bottom-color: #000000;
+}
+.tooltip-inner {
+  max-width: 200px;
+  padding: 3px 8px;
+  color: #ffffff;
+  text-align: center;
+  background-color: #000000;
+  border-radius: 0;
+}
+.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: "Source Sans Pro", Calibri, Candara, 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: 15px;
+  background-color: #ffffff;
+  background-clip: padding-box;
+  border: 1px solid #cccccc;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  border-radius: 0;
+  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: #ffffff;
+  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: #ffffff;
+  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: #ffffff;
+}
+.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: #ffffff;
+}
+.popover-title {
+  padding: 8px 14px;
+  margin: 0;
+  font-size: 15px;
+  background-color: #f7f7f7;
+  border-bottom: 1px solid #ebebeb;
+  border-radius: -1 -1 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;
+  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 {
+    transition: -webkit-transform 0.6s ease-in-out;
+    transition: 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: #ffffff;
+  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: 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: 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: #ffffff;
+  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 #ffffff;
+  border-radius: 10px;
+}
+.carousel-indicators .active {
+  width: 12px;
+  height: 12px;
+  margin: 0;
+  background-color: #ffffff;
+}
+.carousel-caption {
+  position: absolute;
+  right: 15%;
+  bottom: 20px;
+  left: 15%;
+  z-index: 10;
+  padding-top: 20px;
+  padding-bottom: 20px;
+  color: #ffffff;
+  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;
+  }
+}
+.navbar-inverse .badge {
+  background-color: #fff;
+  color: #2780e3;
+}
+body {
+  -webkit-font-smoothing: antialiased;
+}
+.text-primary,
+.text-primary:hover {
+  color: #2780e3;
+}
+.text-success,
+.text-success:hover {
+  color: #3fb618;
+}
+.text-danger,
+.text-danger:hover {
+  color: #ff0039;
+}
+.text-warning,
+.text-warning:hover {
+  color: #ff7518;
+}
+.text-info,
+.text-info:hover {
+  color: #9954bb;
+}
+table a:not(.btn),
+.table a:not(.btn) {
+  text-decoration: underline;
+}
+table .dropdown-menu a,
+.table .dropdown-menu a {
+  text-decoration: none;
+}
+table .success,
+.table .success,
+table .warning,
+.table .warning,
+table .danger,
+.table .danger,
+table .info,
+.table .info {
+  color: #fff;
+}
+table .success a,
+.table .success a,
+table .warning a,
+.table .warning a,
+table .danger a,
+.table .danger a,
+table .info a,
+.table .info a {
+  color: #fff;
+}
+.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,
+.has-warning .form-control-feedback {
+  color: #ff7518;
+}
+.has-warning .form-control,
+.has-warning .form-control:focus,
+.has-warning .input-group-addon {
+  border: 1px solid #ff7518;
+}
+.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,
+.has-error .form-control-feedback {
+  color: #ff0039;
+}
+.has-error .form-control,
+.has-error .form-control:focus,
+.has-error .input-group-addon {
+  border: 1px solid #ff0039;
+}
+.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,
+.has-success .form-control-feedback {
+  color: #3fb618;
+}
+.has-success .form-control,
+.has-success .form-control:focus,
+.has-success .input-group-addon {
+  border: 1px solid #3fb618;
+}
+.nav-pills > li > a {
+  border-radius: 0;
+}
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus {
+  background-image: none;
+}
+.close {
+  text-decoration: none;
+  text-shadow: none;
+  opacity: 0.4;
+}
+.close:hover,
+.close:focus {
+  opacity: 1;
+}
+.alert {
+  border: none;
+}
+.alert .alert-link {
+  text-decoration: underline;
+  color: #fff;
+}
+.label {
+  border-radius: 0;
+}
+.progress {
+  height: 8px;
+  box-shadow: none;
+}
+.progress .progress-bar {
+  font-size: 8px;
+  line-height: 8px;
+}
+.panel-heading,
+.panel-footer {
+  border-top-right-radius: 0;
+  border-top-left-radius: 0;
+}
+.panel-default .close {
+  color: #333333;
+}
+a.list-group-item-success.active {
+  background-color: #3fb618;
+}
+a.list-group-item-success.active:hover,
+a.list-group-item-success.active:focus {
+  background-color: #379f15;
+}
+a.list-group-item-warning.active {
+  background-color: #ff7518;
+}
+a.list-group-item-warning.active:hover,
+a.list-group-item-warning.active:focus {
+  background-color: #fe6600;
+}
+a.list-group-item-danger.active {
+  background-color: #ff0039;
+}
+a.list-group-item-danger.active:hover,
+a.list-group-item-danger.active:focus {
+  background-color: #e60033;
+}
+.modal .close {
+  color: #333333;
+}
+.popover {
+  color: #333333;
+}
diff --git a/modules/cms/src/main/resources/static/modules/cmsfront/themes/default/bootstrap.min.css b/modules/cms/src/main/resources/static/modules/cmsfront/themes/default/bootstrap.min.css
new file mode 100644
index 00000000..86e72743
--- /dev/null
+++ b/modules/cms/src/main/resources/static/modules/cmsfront/themes/default/bootstrap.min.css
@@ -0,0 +1,11 @@
+@import url("https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,700");/*!
+ * bootswatch v3.4.1
+ * Homepage: http://bootswatch.com
+ * Copyright 2012-2019 Thomas Park
+ * Licensed under MIT
+ * Based on Bootstrap
+*//*!
+ * 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;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{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"]{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;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;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"}*{box-sizing:border-box}*:before,*:after{box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Source Sans Pro",Calibri,Candara,Arial,sans-serif;font-size:15px;line-height:1.42857143;color:#333333;background-color:#ffffff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#2780e3;text-decoration:none}a:hover,a:focus{color:#165ba8;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:0}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#ffffff;border:1px solid #dddddd;border-radius:0;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:21px;margin-bottom:21px;border:0;border-top:1px solid #e6e6e6}.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:"Source Sans Pro",Calibri,Candara,Arial,sans-serif;font-weight:300;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:#999999}h1,.h1,h2,.h2,h3,.h3{margin-top:21px;margin-bottom:10.5px}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:10.5px;margin-bottom:10.5px}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:39px}h2,.h2{font-size:32px}h3,.h3{font-size:26px}h4,.h4{font-size:19px}h5,.h5{font-size:15px}h6,.h6{font-size:13px}p{margin:0 0 10.5px}.lead{margin-bottom:21px;font-size:17px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:22.5px}}small,.small{font-size:86%}mark,.mark{padding:.2em;background-color:#ff7518}.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:#999999}.text-primary{color:#2780e3}a.text-primary:hover,a.text-primary:focus{color:#1967be}.text-success{color:#ffffff}a.text-success:hover,a.text-success:focus{color:#e6e6e6}.text-info{color:#ffffff}a.text-info:hover,a.text-info:focus{color:#e6e6e6}.text-warning{color:#ffffff}a.text-warning:hover,a.text-warning:focus{color:#e6e6e6}.text-danger{color:#ffffff}a.text-danger:hover,a.text-danger:focus{color:#e6e6e6}.bg-primary{color:#fff;background-color:#2780e3}a.bg-primary:hover,a.bg-primary:focus{background-color:#1967be}.bg-success{background-color:#3fb618}a.bg-success:hover,a.bg-success:focus{background-color:#2f8912}.bg-info{background-color:#9954bb}a.bg-info:hover,a.bg-info:focus{background-color:#7e3f9d}.bg-warning{background-color:#ff7518}a.bg-warning:hover,a.bg-warning:focus{background-color:#e45c00}.bg-danger{background-color:#ff0039}a.bg-danger:hover,a.bg-danger:focus{background-color:#cc002e}.page-header{padding-bottom:9.5px;margin:42px 0 21px;border-bottom:1px solid #e6e6e6}ul,ol{margin-top:0;margin-bottom:10.5px}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:21px}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:10.5px 21px;margin:0 0 21px;font-size:18.75px;border-left:5px solid #e6e6e6}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:#999999}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 #e6e6e6;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:21px;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:0}kbd{padding:2px 4px;font-size:90%;color:#ffffff;background-color:#333333;border-radius:0;box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;box-shadow:none}pre{display:block;padding:10px;margin:0 0 10.5px;font-size:14px;line-height:1.42857143;color:#333333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #cccccc;border-radius:0}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:#999999;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:21px}.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 #dddddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #dddddd}.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 #dddddd}.table .table{background-color:#ffffff}.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 #dddddd}.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 #dddddd}.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:#3fb618}.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:#379f15}.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:#9954bb}.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:#8d46b0}.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:#ff7518}.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:#fe6600}.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:#ff0039}.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:#e60033}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15.75px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #dddddd}.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:21px;font-size:22.5px;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"]{box-sizing:border-box;-webkit-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:11px;font-size:15px;line-height:1.42857143;color:#333333}.form-control{display:block;width:100%;height:43px;padding:10px 18px;font-size:15px;line-height:1.42857143;color:#333333;background-color:#ffffff;background-image:none;border:1px solid #cccccc;border-radius:0;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.form-control::-moz-placeholder{color:#999999;opacity:1}.form-control:-ms-input-placeholder{color:#999999}.form-control::-webkit-input-placeholder{color:#999999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#e6e6e6;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:43px}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:31px}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:64px}}.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:21px;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:36px;padding-top:11px;padding-bottom:11px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:31px;padding:5px 10px;font-size:13px;line-height:1.5;border-radius:0}select.input-sm{height:31px;line-height:31px}textarea.input-sm,select[multiple].input-sm{height:auto}.form-group-sm .form-control{height:31px;padding:5px 10px;font-size:13px;line-height:1.5;border-radius:0}.form-group-sm select.form-control{height:31px;line-height:31px}.form-group-sm textarea.form-control,.form-group-sm select[multiple].form-control{height:auto}.form-group-sm .form-control-static{height:31px;min-height:34px;padding:6px 10px;font-size:13px;line-height:1.5}.input-lg{height:64px;padding:18px 30px;font-size:19px;line-height:1.3333333;border-radius:0}select.input-lg{height:64px;line-height:64px}textarea.input-lg,select[multiple].input-lg{height:auto}.form-group-lg .form-control{height:64px;padding:18px 30px;font-size:19px;line-height:1.3333333;border-radius:0}.form-group-lg select.form-control{height:64px;line-height:64px}.form-group-lg textarea.form-control,.form-group-lg select[multiple].form-control{height:auto}.form-group-lg .form-control-static{height:64px;min-height:40px;padding:19px 30px;font-size:19px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:53.75px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:43px;height:43px;line-height:43px;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:64px;height:64px;line-height:64px}.input-sm+.form-control-feedback,.input-group-sm+.form-control-feedback,.form-group-sm .form-control+.form-control-feedback{width:31px;height:31px;line-height:31px}.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:#ffffff}.has-success .form-control{border-color:#ffffff;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#e6e6e6;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #fff}.has-success .input-group-addon{color:#ffffff;background-color:#3fb618;border-color:#ffffff}.has-success .form-control-feedback{color:#ffffff}.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:#ffffff}.has-warning .form-control{border-color:#ffffff;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#e6e6e6;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #fff}.has-warning .input-group-addon{color:#ffffff;background-color:#ff7518;border-color:#ffffff}.has-warning .form-control-feedback{color:#ffffff}.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:#ffffff}.has-error .form-control{border-color:#ffffff;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#e6e6e6;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #fff}.has-error .input-group-addon{color:#ffffff;background-color:#ff0039;border-color:#ffffff}.has-error .form-control-feedback{color:#ffffff}.has-feedback label~.form-control-feedback{top:26px}.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:11px;margin-top:0;margin-bottom:0}.form-horizontal .radio,.form-horizontal .checkbox{min-height:32px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:11px;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:19px;font-size:19px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:13px}}.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:10px 18px;font-size:15px;line-height:1.42857143;border-radius:0;-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:#ffffff;text-decoration:none}.btn:active,.btn.active{background-image:none;outline:0;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;box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#ffffff;background-color:#222222;border-color:#222222}.btn-default:focus,.btn-default.focus{color:#ffffff;background-color:#090909;border-color:#000000}.btn-default:hover{color:#ffffff;background-color:#090909;border-color:#040404}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#ffffff;background-color:#090909;background-image:none;border-color:#040404}.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:#ffffff;background-color:#000000;border-color:#000000}.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:#222222;border-color:#222222}.btn-default .badge{color:#222222;background-color:#ffffff}.btn-primary{color:#ffffff;background-color:#2780e3;border-color:#2780e3}.btn-primary:focus,.btn-primary.focus{color:#ffffff;background-color:#1967be;border-color:#10427b}.btn-primary:hover{color:#ffffff;background-color:#1967be;border-color:#1862b5}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#ffffff;background-color:#1967be;background-image:none;border-color:#1862b5}.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:#ffffff;background-color:#15569f;border-color:#10427b}.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:#2780e3;border-color:#2780e3}.btn-primary .badge{color:#2780e3;background-color:#ffffff}.btn-success{color:#ffffff;background-color:#3fb618;border-color:#3fb618}.btn-success:focus,.btn-success.focus{color:#ffffff;background-color:#2f8912;border-color:#184509}.btn-success:hover{color:#ffffff;background-color:#2f8912;border-color:#2c8011}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#ffffff;background-color:#2f8912;background-image:none;border-color:#2c8011}.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:#ffffff;background-color:#24690e;border-color:#184509}.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:#3fb618;border-color:#3fb618}.btn-success .badge{color:#3fb618;background-color:#ffffff}.btn-info{color:#ffffff;background-color:#9954bb;border-color:#9954bb}.btn-info:focus,.btn-info.focus{color:#ffffff;background-color:#7e3f9d;border-color:#522967}.btn-info:hover{color:#ffffff;background-color:#7e3f9d;border-color:#783c96}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#ffffff;background-color:#7e3f9d;background-image:none;border-color:#783c96}.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:#ffffff;background-color:#6a3484;border-color:#522967}.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:#9954bb;border-color:#9954bb}.btn-info .badge{color:#9954bb;background-color:#ffffff}.btn-warning{color:#ffffff;background-color:#ff7518;border-color:#ff7518}.btn-warning:focus,.btn-warning.focus{color:#ffffff;background-color:#e45c00;border-color:#983d00}.btn-warning:hover{color:#ffffff;background-color:#e45c00;border-color:#da5800}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#ffffff;background-color:#e45c00;background-image:none;border-color:#da5800}.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:#ffffff;background-color:#c04d00;border-color:#983d00}.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:#ff7518;border-color:#ff7518}.btn-warning .badge{color:#ff7518;background-color:#ffffff}.btn-danger{color:#ffffff;background-color:#ff0039;border-color:#ff0039}.btn-danger:focus,.btn-danger.focus{color:#ffffff;background-color:#cc002e;border-color:#80001c}.btn-danger:hover{color:#ffffff;background-color:#cc002e;border-color:#c2002b}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#ffffff;background-color:#cc002e;background-image:none;border-color:#c2002b}.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:#ffffff;background-color:#a80026;border-color:#80001c}.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:#ff0039;border-color:#ff0039}.btn-danger .badge{color:#ff0039;background-color:#ffffff}.btn-link{font-weight:400;color:#2780e3;border-radius:0}.btn-link,.btn-link:active,.btn-link.active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#165ba8;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:#999999;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:18px 30px;font-size:19px;line-height:1.3333333;border-radius:0}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:13px;line-height:1.5;border-radius:0}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:13px;line-height:1.5;border-radius:0}.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;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;transition-property:height, visibility;transition-duration:0.35s;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:15px;text-align:left;list-style:none;background-color:#ffffff;background-clip:padding-box;border:1px solid #cccccc;border:1px solid rgba(0,0,0,0.15);border-radius:0;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:9.5px 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:#ffffff;text-decoration:none;background-color:#2780e3}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#ffffff;text-decoration:none;background-color:#2780e3;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999999}.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:13px;line-height:1.42857143;color:#999999;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{box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-group.open .dropdown-toggle.btn-link{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:0;border-top-right-radius:0;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:0;border-bottom-left-radius:0}.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:64px;padding:18px 30px;font-size:19px;line-height:1.3333333;border-radius:0}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:64px;line-height:64px}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:31px;padding:5px 10px;font-size:13px;line-height:1.5;border-radius:0}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:31px;line-height:31px}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:10px 18px;font-size:15px;font-weight:400;line-height:1;color:#333333;text-align:center;background-color:#e6e6e6;border:1px solid #cccccc;border-radius:0}.input-group-addon.input-sm{padding:5px 10px;font-size:13px;border-radius:0}.input-group-addon.input-lg{padding:18px 30px;font-size:19px;border-radius:0}.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:#e6e6e6}.nav>li.disabled>a{color:#999999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999999;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#e6e6e6;border-color:#2780e3}.nav .nav-divider{height:1px;margin:9.5px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #dddddd}.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:0 0 0 0}.nav-tabs>li>a:hover{border-color:#e6e6e6 #e6e6e6 #dddddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555555;cursor:default;background-color:#ffffff;border:1px solid #dddddd;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:0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #dddddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #dddddd;border-radius:0 0 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:#ffffff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:0}.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:#ffffff;background-color:#2780e3}.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:0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #dddddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #dddddd;border-radius:0 0 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#ffffff}}.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:21px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:0}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;border-top:1px solid transparent;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;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:14.5px 15px;font-size:19px;line-height:21px}.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:0}.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.25px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:21px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;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:21px}.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:14.5px;padding-bottom:14.5px}}.navbar-form{padding:10px 15px;margin-right:-15px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);margin-top:3.5px;margin-bottom:3.5px}@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;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:0;border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:3.5px;margin-bottom:3.5px}.navbar-btn.btn-sm{margin-top:9.5px;margin-bottom:9.5px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:14.5px;margin-bottom:14.5px}@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:#222222;border-color:#121212}.navbar-default .navbar-brand{color:#ffffff}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#ffffff;background-color:none}.navbar-default .navbar-text{color:#ffffff}.navbar-default .navbar-nav>li>a{color:#ffffff}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#ffffff;background-color:#090909}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#ffffff;background-color:#090909}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#cccccc;background-color:transparent}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{color:#ffffff;background-color:#090909}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#ffffff}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#ffffff;background-color:#090909}.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:#ffffff;background-color:#090909}.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:#cccccc;background-color:transparent}}.navbar-default .navbar-toggle{border-color:transparent}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#090909}.navbar-default .navbar-toggle .icon-bar{background-color:#ffffff}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#121212}.navbar-default .navbar-link{color:#ffffff}.navbar-default .navbar-link:hover{color:#ffffff}.navbar-default .btn-link{color:#ffffff}.navbar-default .btn-link:hover,.navbar-default .btn-link:focus{color:#ffffff}.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:#cccccc}.navbar-inverse{background-color:#2780e3;border-color:#1967be}.navbar-inverse .navbar-brand{color:#ffffff}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#ffffff;background-color:none}.navbar-inverse .navbar-text{color:#ffffff}.navbar-inverse .navbar-nav>li>a{color:#ffffff}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#ffffff;background-color:#1967be}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#ffffff;background-color:#1967be}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#ffffff;background-color:transparent}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{color:#ffffff;background-color:#1967be}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#1967be}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#1967be}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#ffffff}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#ffffff;background-color:#1967be}.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:#ffffff;background-color:#1967be}.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:#ffffff;background-color:transparent}}.navbar-inverse .navbar-toggle{border-color:transparent}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#1967be}.navbar-inverse .navbar-toggle .icon-bar{background-color:#ffffff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#1a6ecc}.navbar-inverse .navbar-link{color:#ffffff}.navbar-inverse .navbar-link:hover{color:#ffffff}.navbar-inverse .btn-link{color:#ffffff}.navbar-inverse .btn-link:hover,.navbar-inverse .btn-link:focus{color:#ffffff}.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:#ffffff}.breadcrumb{padding:8px 15px;margin-bottom:21px;list-style:none;background-color:#f5f5f5;border-radius:0}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#cccccc;content:"/\00a0"}.breadcrumb>.active{color:#999999}.pagination{display:inline-block;padding-left:0;margin:21px 0;border-radius:0}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:10px 18px;margin-left:-1px;line-height:1.42857143;color:#2780e3;text-decoration:none;background-color:#ffffff;border:1px solid #dddddd}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{z-index:2;color:#165ba8;background-color:#e6e6e6;border-color:#dddddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:0;border-bottom-left-radius:0}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:0;border-bottom-right-radius:0}.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:#999999;cursor:default;background-color:#f5f5f5;border-color:#dddddd}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999999;cursor:not-allowed;background-color:#ffffff;border-color:#dddddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:18px 30px;font-size:19px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:0;border-bottom-left-radius:0}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:0;border-bottom-right-radius:0}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:13px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:0;border-bottom-left-radius:0}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:0;border-bottom-right-radius:0}.pager{padding-left:0;margin:21px 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:#ffffff;border:1px solid #dddddd;border-radius:0}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#e6e6e6}.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:#999999;cursor:not-allowed;background-color:#ffffff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#ffffff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:hover,a.label:focus{color:#ffffff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#222222}.label-default[href]:hover,.label-default[href]:focus{background-color:#090909}.label-primary{background-color:#2780e3}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#1967be}.label-success{background-color:#3fb618}.label-success[href]:hover,.label-success[href]:focus{background-color:#2f8912}.label-info{background-color:#9954bb}.label-info[href]:hover,.label-info[href]:focus{background-color:#7e3f9d}.label-warning{background-color:#ff7518}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#e45c00}.label-danger{background-color:#ff0039}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#cc002e}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:13px;font-weight:bold;line-height:1;color:#ffffff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#2780e3;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:#ffffff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#2780e3;background-color:#ffffff}.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:#e6e6e6}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:23px;font-weight:200}.jumbotron>hr{border-top-color:#cccccc}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:0}.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:68px}}.thumbnail{display:block;padding:4px;margin-bottom:21px;line-height:1.42857143;background-color:#ffffff;border:1px solid #dddddd;border-radius:0;transition:border .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:#2780e3}.thumbnail .caption{padding:9px;color:#333333}.alert{padding:15px;margin-bottom:21px;border:1px solid transparent;border-radius:0}.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:#ffffff;background-color:#3fb618;border-color:#4e9f15}.alert-success hr{border-top-color:#438912}.alert-success .alert-link{color:#e6e6e6}.alert-info{color:#ffffff;background-color:#9954bb;border-color:#7643a8}.alert-info hr{border-top-color:#693c96}.alert-info .alert-link{color:#e6e6e6}.alert-warning{color:#ffffff;background-color:#ff7518;border-color:#ff4309}.alert-warning hr{border-top-color:#ee3800}.alert-warning .alert-link{color:#e6e6e6}.alert-danger{color:#ffffff;background-color:#ff0039;border-color:#f0005e}.alert-danger hr{border-top-color:#d60054}.alert-danger .alert-link{color:#e6e6e6}@-webkit-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:21px;margin-bottom:21px;overflow:hidden;background-color:#cccccc;border-radius:0;box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0%;height:100%;font-size:13px;line-height:21px;color:#ffffff;text-align:center;background-color:#2780e3;box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);transition:width 0.6s ease}.progress-striped .progress-bar,.progress-bar-striped{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);background-size:40px 40px}.progress.active .progress-bar,.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#3fb618}.progress-striped .progress-bar-success{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:#9954bb}.progress-striped .progress-bar-info{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:#ff7518}.progress-striped .progress-bar-warning{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:#ff0039}.progress-striped .progress-bar-danger{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:#ffffff;border:1px solid #dddddd}.list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.list-group-item.disabled,.list-group-item.disabled:hover,.list-group-item.disabled:focus{color:#999999;cursor:not-allowed;background-color:#e6e6e6}.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:#999999}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#ffffff;background-color:#2780e3;border-color:#dddddd}.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:#dceafa}a.list-group-item,button.list-group-item{color:#555555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333333}a.list-group-item:hover,button.list-group-item:hover,a.list-group-item:focus,button.list-group-item:focus{color:#555555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item-success{color:#ffffff;background-color:#3fb618}a.list-group-item-success,button.list-group-item-success{color:#ffffff}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:#ffffff;background-color:#379f15}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:#ffffff;border-color:#ffffff}.list-group-item-info{color:#ffffff;background-color:#9954bb}a.list-group-item-info,button.list-group-item-info{color:#ffffff}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:#ffffff;background-color:#8d46b0}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:#ffffff;border-color:#ffffff}.list-group-item-warning{color:#ffffff;background-color:#ff7518}a.list-group-item-warning,button.list-group-item-warning{color:#ffffff}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:#ffffff;background-color:#fe6600}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:#ffffff;border-color:#ffffff}.list-group-item-danger{color:#ffffff;background-color:#ff0039}a.list-group-item-danger,button.list-group-item-danger{color:#ffffff}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:#ffffff;background-color:#e60033}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:#ffffff;border-color:#ffffff}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:21px;background-color:#ffffff;border:1px solid transparent;border-radius:0;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:-1;border-top-right-radius:-1}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:17px;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 #dddddd;border-bottom-right-radius:-1;border-bottom-left-radius:-1}.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:-1;border-top-right-radius:-1}.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:-1;border-bottom-left-radius:-1}.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:-1;border-top-right-radius:-1}.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:-1;border-top-right-radius:-1}.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:-1}.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:-1}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:-1;border-bottom-left-radius:-1}.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:-1;border-bottom-left-radius:-1}.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:-1}.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:-1}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #dddddd}.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:21px}.panel-group .panel{margin-bottom:0;border-radius:0}.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 #dddddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #dddddd}.panel-default{border-color:#dddddd}.panel-default>.panel-heading{color:#333333;background-color:#f5f5f5;border-color:#dddddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#dddddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#dddddd}.panel-primary{border-color:#2780e3}.panel-primary>.panel-heading{color:#ffffff;background-color:#2780e3;border-color:#2780e3}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#2780e3}.panel-primary>.panel-heading .badge{color:#2780e3;background-color:#ffffff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#2780e3}.panel-success{border-color:#4e9f15}.panel-success>.panel-heading{color:#ffffff;background-color:#3fb618;border-color:#4e9f15}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#4e9f15}.panel-success>.panel-heading .badge{color:#3fb618;background-color:#ffffff}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#4e9f15}.panel-info{border-color:#7643a8}.panel-info>.panel-heading{color:#ffffff;background-color:#9954bb;border-color:#7643a8}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#7643a8}.panel-info>.panel-heading .badge{color:#9954bb;background-color:#ffffff}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#7643a8}.panel-warning{border-color:#ff4309}.panel-warning>.panel-heading{color:#ffffff;background-color:#ff7518;border-color:#ff4309}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ff4309}.panel-warning>.panel-heading .badge{color:#ff7518;background-color:#ffffff}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ff4309}.panel-danger{border-color:#f0005e}.panel-danger>.panel-heading{color:#ffffff;background-color:#ff0039;border-color:#f0005e}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#f0005e}.panel-danger>.panel-heading .badge{color:#ff0039;background-color:#ffffff}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#f0005e}.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:0;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:0}.well-sm{padding:9px;border-radius:0}.close{float:right;font-size:22.5px;font-weight:bold;line-height:1;color:#ffffff;text-shadow:0 1px 0 #ffffff;filter:alpha(opacity=20);opacity:0.2}.close:hover,.close:focus{color:#ffffff;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;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%);transform:translate(0, -25%);transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-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:#ffffff;background-clip:padding-box;border:1px solid #999999;border:1px solid transparent;border-radius:0;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:#000000}.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:20px}.modal-footer{padding:20px;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{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:"Source Sans Pro",Calibri,Candara,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:13px;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:#000000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000000}.tooltip-inner{max-width:200px;padding:3px 8px;color:#ffffff;text-align:center;background-color:#000000;border-radius:0}.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:"Source Sans Pro",Calibri,Candara,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:15px;background-color:#ffffff;background-clip:padding-box;border:1px solid #cccccc;border:1px solid rgba(0,0,0,0.2);border-radius:0;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:#ffffff;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:#ffffff;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:#ffffff}.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:#ffffff}.popover-title{padding:8px 14px;margin:0;font-size:15px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:-1 -1 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;transition:.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{transition:-webkit-transform .6s ease-in-out;transition:transform .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:#ffffff;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: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: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:#ffffff;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 #ffffff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#ffffff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#ffffff;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}}.navbar-inverse .badge{background-color:#fff;color:#2780e3}body{-webkit-font-smoothing:antialiased}.text-primary,.text-primary:hover{color:#2780e3}.text-success,.text-success:hover{color:#3fb618}.text-danger,.text-danger:hover{color:#ff0039}.text-warning,.text-warning:hover{color:#ff7518}.text-info,.text-info:hover{color:#9954bb}table a:not(.btn),.table a:not(.btn){text-decoration:underline}table .dropdown-menu a,.table .dropdown-menu a{text-decoration:none}table .success,.table .success,table .warning,.table .warning,table .danger,.table .danger,table .info,.table .info{color:#fff}table .success a,.table .success a,table .warning a,.table .warning a,table .danger a,.table .danger a,table .info a,.table .info a{color:#fff}.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,.has-warning .form-control-feedback{color:#ff7518}.has-warning .form-control,.has-warning .form-control:focus,.has-warning .input-group-addon{border:1px solid #ff7518}.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,.has-error .form-control-feedback{color:#ff0039}.has-error .form-control,.has-error .form-control:focus,.has-error .input-group-addon{border:1px solid #ff0039}.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,.has-success .form-control-feedback{color:#3fb618}.has-success .form-control,.has-success .form-control:focus,.has-success .input-group-addon{border:1px solid #3fb618}.nav-pills>li>a{border-radius:0}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-image:none}.close{text-decoration:none;text-shadow:none;opacity:0.4}.close:hover,.close:focus{opacity:1}.alert{border:none}.alert .alert-link{text-decoration:underline;color:#fff}.label{border-radius:0}.progress{height:8px;box-shadow:none}.progress .progress-bar{font-size:8px;line-height:8px}.panel-heading,.panel-footer{border-top-right-radius:0;border-top-left-radius:0}.panel-default .close{color:#333333}a.list-group-item-success.active{background-color:#3fb618}a.list-group-item-success.active:hover,a.list-group-item-success.active:focus{background-color:#379f15}a.list-group-item-warning.active{background-color:#ff7518}a.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus{background-color:#fe6600}a.list-group-item-danger.active{background-color:#ff0039}a.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus{background-color:#e60033}.modal .close{color:#333333}.popover{color:#333333}
\ No newline at end of file
diff --git a/modules/cms/src/main/resources/static/modules/cmsfront/themes/default/bootswatch.less b/modules/cms/src/main/resources/static/modules/cmsfront/themes/default/bootswatch.less
new file mode 100644
index 00000000..f484615e
--- /dev/null
+++ b/modules/cms/src/main/resources/static/modules/cmsfront/themes/default/bootswatch.less
@@ -0,0 +1,266 @@
+// Cosmo 3.4.1
+// Bootswatch
+// -----------------------------------------------------
+
+@web-font-path: "https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,700";
+
+.web-font(@path) {
+  @import (css) url("@{path}");
+}
+.web-font(@web-font-path);
+
+// Navbar =====================================================================
+
+.navbar {
+
+  &-inverse {
+
+    .badge {
+      background-color: #fff;
+      color: @brand-primary;
+    }
+  }
+}
+
+// Buttons ====================================================================
+
+// Typography =================================================================
+
+body {
+  -webkit-font-smoothing: antialiased;
+}
+
+.text-primary,
+.text-primary:hover {
+  color: @brand-primary;
+}
+
+.text-success,
+.text-success:hover {
+  color: @brand-success;
+}
+
+.text-danger,
+.text-danger:hover {
+  color: @brand-danger;
+}
+
+.text-warning,
+.text-warning:hover {
+  color: @brand-warning;
+}
+
+.text-info,
+.text-info:hover {
+  color: @brand-info;
+}
+
+// Tables =====================================================================
+
+table,
+.table {
+
+  a:not(.btn) {
+    text-decoration: underline;
+  }
+
+  .dropdown-menu a {
+    text-decoration: none;
+  }
+
+  .success,
+  .warning,
+  .danger,
+  .info {
+    color: #fff;
+
+    a {
+      color: #fff;
+    }
+  }
+}
+
+// Forms ======================================================================
+
+
+.has-warning {
+  .help-block,
+  .control-label,
+  .radio,
+  .checkbox,
+  .radio-inline,
+  .checkbox-inline,
+  &.radio label,
+  &.checkbox label,
+  &.radio-inline label,
+  &.checkbox-inline label,
+  .form-control-feedback {
+    color: @brand-warning;
+  }
+
+  .form-control,
+  .form-control:focus,
+  .input-group-addon {
+    border: 1px solid @brand-warning;
+  }
+}
+
+.has-error {
+  .help-block,
+  .control-label,
+  .radio,
+  .checkbox,
+  .radio-inline,
+  .checkbox-inline,
+  &.radio label,
+  &.checkbox label,
+  &.radio-inline label,
+  &.checkbox-inline label,
+  .form-control-feedback {
+    color: @brand-danger;
+  }
+
+  .form-control,
+  .form-control:focus,
+  .input-group-addon {
+    border: 1px solid @brand-danger;
+  }
+}
+
+.has-success {
+  .help-block,
+  .control-label,
+  .radio,
+  .checkbox,
+  .radio-inline,
+  .checkbox-inline,
+  &.radio label,
+  &.checkbox label,
+  &.radio-inline label,
+  &.checkbox-inline label,
+  .form-control-feedback {
+    color: @brand-success;
+  }
+
+  .form-control,
+  .form-control:focus,
+  .input-group-addon {
+    border: 1px solid @brand-success;
+  }
+}
+
+// Navs =======================================================================
+
+.nav-pills {
+
+  & > li > a {
+    border-radius: 0;
+  }
+}
+
+.dropdown-menu {
+
+  & > li > a:hover,
+  & > li > a:focus {
+    background-image: none;
+  }
+}
+
+// Indicators =================================================================
+
+.close {
+  text-decoration: none;
+  text-shadow: none;
+  opacity: 0.4;
+
+  &:hover,
+  &:focus {
+    opacity: 1;
+  }
+}
+
+.alert {
+  border: none;
+
+  .alert-link {
+    text-decoration: underline;
+    color: #fff;
+  }
+}
+
+.label {
+  border-radius: 0;
+}
+
+// Progress bars ==============================================================
+
+.progress {
+  height: 8px;
+  .box-shadow(none);
+  .progress-bar {
+    font-size: 8px;
+    line-height: 8px;
+  }
+}
+
+// Containers =================================================================
+
+.panel {
+  &-heading,
+  &-footer {
+    border-top-right-radius: 0;
+    border-top-left-radius: 0;
+  }
+
+  &-default {
+    .close {
+      color: @text-color;
+    }
+  }
+}
+
+a.list-group-item {
+
+  &-success {
+    &.active {
+      background-color: @state-success-bg;
+    }
+
+    &.active:hover,
+    &.active:focus {
+      background-color: darken(@state-success-bg, 5%);
+    }
+  }
+
+  &-warning {
+    &.active {
+      background-color: @state-warning-bg;
+    }
+    
+    &.active:hover,
+    &.active:focus {
+      background-color: darken(@state-warning-bg, 5%);
+    }
+  }
+
+  &-danger {
+    &.active {
+      background-color: @state-danger-bg;
+    }
+    
+    &.active:hover,
+    &.active:focus {
+      background-color: darken(@state-danger-bg, 5%);
+    }
+  }
+}
+
+.modal {
+  .close {
+    color: @text-color;
+  }
+}
+
+.popover {
+  color: @text-color;
+}
diff --git a/modules/cms/src/main/resources/static/modules/cmsfront/themes/default/index.html b/modules/cms/src/main/resources/static/modules/cmsfront/themes/default/index.html
new file mode 100644
index 00000000..aa3f697a
--- /dev/null
+++ b/modules/cms/src/main/resources/static/modules/cmsfront/themes/default/index.html
@@ -0,0 +1,1298 @@
+
+
+  
+    
+    Bootswatch: Cosmo
+    
+    
+    
+    
+    
+    
+  
+  
+    
+
+
+    
+ + + + +
+
+
+ + +
+ +
+ +
+ +
+ +
+
+
+ + + +
+ + + +
+ + +
+
+
+ +
+
+ + + +
+
+
+

Heading 1

+

Heading 2

+

Heading 3

+

Heading 4

+
Heading 5
+
Heading 6
+

Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.

+
+
+
+
+

Example body text

+

Nullam quis risus eget urna mollis ornare vel eu leo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nullam id dolor id nibh ultricies vehicula.

+

This line of text is meant to be treated as fine print.

+

The following snippet of text is rendered as bold text.

+

The following snippet of text is rendered as italicized text.

+

An abbreviation of the word attribute is attr.

+
+ +
+
+
+

Emphasis classes

+

Fusce dapibus, tellus ac cursus commodo, tortor mauris nibh.

+

Nullam id dolor id nibh ultricies vehicula ut id elit.

+

Etiam porta sem malesuada magna mollis euismod.

+

Donec ullamcorper nulla non metus auctor fringilla.

+

Duis mollis, est non commodo luctus, nisi erat porttitor ligula.

+

Maecenas sed diam eget risus varius blandit sit amet non magna.

+
+ +
+
+ + + +
+
+

Blockquotes

+
+
+
+
+
+
+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.

+ Someone famous in Source Title +
+
+
+
+
+
+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.

+ Someone famous in Source Title +
+
+
+
+
+ + +
+ +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#Column headingColumn headingColumn heading
1Column contentColumn contentColumn content
2Column contentColumn contentColumn content
3Column contentColumn contentColumn content
4Column contentColumn contentColumn content
5Column contentColumn contentColumn content
6Column contentColumn contentColumn content
7Column contentColumn contentColumn content
+
+
+
+
+ + +
+
+
+ +
+
+ +
+
+
+
+
+ Legend +
+ +
+ +
+
+
+ +
+ +
+ +
+
+
+
+ +
+ + A longer block of help text that breaks onto a new line and may extend beyond one line. +
+
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+ +
+ +
+
+
+
+ + +
+
+
+
+
+
+
+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ $ + + + + +
+
+
+ +
+
+
+ + +
+ +
+
+ +
+
+ +
+
+ +
+ +
+
+

Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui.

+
+
+

Food truck fixie locavore, accusamus mcsweeney's marfa nulla single-origin coffee squid. Exercitation +1 labore velit, blog sartorial PBR leggings next level wes anderson artisan four loko farm-to-table craft beer twee. Qui photo booth letterpress, commodo enim craft beer mlkshk aliquip jean shorts ullamco ad vinyl cillum PBR. Homo nostrud organic, assumenda labore aesthetic magna delectus mollit.

+
+ + +
+
+
+ +
+ +
+ + + + + +
+ +
+
+ + +
+
+

Pagination

+
+ + + + + +
+
+
+

Pager

+
+ + + +
+
+
+ +
+
+
+ + +
+ +
+
+ +
+
+ +
+
+

Alerts

+
+
+ +

Warning!

+

Best check yo self, you're not looking too good. Nulla vitae elit libero, a pharetra augue. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.

+
+
+
+
+
+
+
+
+ + Oh snap! Change a few things up and try submitting again. +
+
+
+
+
+
+ + Well done! You successfully read this important alert message. +
+
+
+
+
+
+ + Heads up! This alert needs your attention, but it's not super important. +
+
+
+
+
+
+

Labels

+
+ Default + Primary + Success + Warning + Danger + Info +
+
+
+

Badges

+ +
+
+
+ + +
+ +
+
+ + +

Basic

+
+
+
+
+
+ +

Contextual alternatives

+
+
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+
+ +

Striped

+
+
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+
+ +

Animated

+
+
+
+
+
+ +

Stacked

+
+
+
+
+
+
+
+
+
+
+ + +
+ +
+
+ +
+
+

Jumbotron

+

This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.

+

Learn more

+
+
+
+
+ + +
+
+

List groups

+
+
+ + + +
+
+

Panels

+
+
+
+
+
+
+
+ Basic panel +
+
+ +
+
Panel heading
+
+ Panel content +
+
+ +
+
+ Panel content +
+ +
+
+
+
+
+
+
+

Panel primary

+
+
+ Panel content +
+
+ +
+
+

Panel success

+
+
+ Panel content +
+
+ +
+
+

Panel warning

+
+
+ Panel content +
+
+
+
+
+
+
+
+

Panel danger

+
+
+ Panel content +
+
+ +
+
+

Panel info

+
+
+ Panel content +
+
+
+
+
+ +
+
+

Wells

+
+
+
+
+
+
+ Look, I'm in a well! +
+
+
+
+
+
+ Look, I'm in a small well! +
+
+
+
+
+
+ Look, I'm in a large well! +
+
+
+
+
+ + +
+ +
+
+ +
+
+
+
+

Modals

+
+ +
+
+
+

Popovers

+
+ + + + + + + +
+

Tooltips

+
+ + + + + + + +
+
+
+
+ + + + + + +
+ + + + + + + diff --git a/modules/cms/src/main/resources/static/modules/cmsfront/themes/default/thumbnail.png b/modules/cms/src/main/resources/static/modules/cmsfront/themes/default/thumbnail.png new file mode 100644 index 00000000..0380d95b Binary files /dev/null and b/modules/cms/src/main/resources/static/modules/cmsfront/themes/default/thumbnail.png differ diff --git a/modules/cms/src/main/resources/static/modules/cmsfront/themes/default/variables.less b/modules/cms/src/main/resources/static/modules/cmsfront/themes/default/variables.less new file mode 100644 index 00000000..155bb363 --- /dev/null +++ b/modules/cms/src/main/resources/static/modules/cmsfront/themes/default/variables.less @@ -0,0 +1,869 @@ +// Cosmo 3.4.1 +// Variables +// -------------------------------------------------- + + +//== Colors +// +//## Gray and brand colors for use across Bootstrap. + +@gray-base: #000; +@gray-darker: lighten(@gray-base, 13.5%); // #222 +@gray-dark: lighten(@gray-base, 20%); // #333 +@gray: lighten(@gray-base, 33.5%); // #555 +@gray-light: lighten(@gray-base, 60%); // #999 +@gray-lighter: lighten(@gray-base, 90%); // #eee + +@brand-primary: #2780E3; +@brand-success: #3FB618; +@brand-info: #9954BB; +@brand-warning: #FF7518; +@brand-danger: #FF0039; + + +//== Scaffolding +// +//## Settings for some of the most global styles. + +//** Background color for ``. +@body-bg: #fff; +//** Global text color on ``. +@text-color: @gray-dark; + +//** Global textual link color. +@link-color: @brand-primary; +//** Link hover color set via `darken()` function. +@link-hover-color: darken(@link-color, 15%); +//** Link hover decoration. +@link-hover-decoration: underline; + + +//== Typography +// +//## Font, line-height, and color for body text, headings, and more. + +@font-family-sans-serif: "Source Sans Pro", Calibri, Candara, Arial, sans-serif; +@font-family-serif: Georgia, "Times New Roman", Times, serif; +//** Default monospace fonts for ``, ``, and `
`.
+@font-family-monospace:   Menlo, Monaco, Consolas, "Courier New", monospace;
+@font-family-base:        @font-family-sans-serif;
+
+@font-size-base:          15px;
+@font-size-large:         ceil((@font-size-base * 1.25)); // ~18px
+@font-size-small:         ceil((@font-size-base * 0.85)); // ~12px
+
+@font-size-h1:            floor((@font-size-base * 2.6)); // ~36px
+@font-size-h2:            floor((@font-size-base * 2.15)); // ~30px
+@font-size-h3:            ceil((@font-size-base * 1.7)); // ~24px
+@font-size-h4:            ceil((@font-size-base * 1.25)); // ~18px
+@font-size-h5:            @font-size-base;
+@font-size-h6:            ceil((@font-size-base * 0.85)); // ~12px
+
+//** Unit-less `line-height` for use in components like buttons.
+@line-height-base:        1.428571429; // 20/14
+//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
+@line-height-computed:    floor((@font-size-base * @line-height-base)); // ~20px
+
+//** By default, this inherits from the ``.
+@headings-font-family:    @font-family-base;
+@headings-font-weight:    300;
+@headings-line-height:    1.1;
+@headings-color:          inherit;
+
+
+//== Iconography
+//
+//## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower.
+
+//** Load fonts from this directory.
+@icon-font-path:          "../fonts/";
+//** File name for all font files.
+@icon-font-name:          "glyphicons-halflings-regular";
+//** Element ID within SVG icon file.
+@icon-font-svg-id:        "glyphicons_halflingsregular";
+
+
+//== Components
+//
+//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
+
+@padding-base-vertical:     10px;
+@padding-base-horizontal:   18px;
+
+@padding-large-vertical:    18px;
+@padding-large-horizontal:  30px;
+
+@padding-small-vertical:    5px;
+@padding-small-horizontal:  10px;
+
+@padding-xs-vertical:       1px;
+@padding-xs-horizontal:     5px;
+
+@line-height-large:         1.3333333; // extra decimals for Win 8.1 Chrome
+@line-height-small:         1.5;
+
+@border-radius-base:        0;
+@border-radius-large:       0;
+@border-radius-small:       0;
+
+//** Global color for active items (e.g., navs or dropdowns).
+@component-active-color:    #fff;
+//** Global background color for active items (e.g., navs or dropdowns).
+@component-active-bg:       @brand-primary;
+
+//** Width of the `border` for generating carets that indicate dropdowns.
+@caret-width-base:          4px;
+//** Carets increase slightly in size for larger components.
+@caret-width-large:         5px;
+
+
+//== Tables
+//
+//## Customizes the `.table` component with basic values, each used across all table variations.
+
+//** Padding for ``s and ``s.
+@table-cell-padding:            8px;
+//** Padding for cells in `.table-condensed`.
+@table-condensed-cell-padding:  5px;
+
+//** Default background color used for all tables.
+@table-bg:                      transparent;
+//** Background color used for `.table-striped`.
+@table-bg-accent:               #f9f9f9;
+//** Background color used for `.table-hover`.
+@table-bg-hover:                #f5f5f5;
+@table-bg-active:               @table-bg-hover;
+
+//** Border color for table and cell borders.
+@table-border-color:            #ddd;
+
+
+//== Buttons
+//
+//## For each of Bootstrap's buttons, define text, background and border color.
+
+@btn-font-weight:                normal;
+
+@btn-default-color:              #fff;
+@btn-default-bg:                 @gray-darker;
+@btn-default-border:             @btn-default-bg;
+
+@btn-primary-color:              @btn-default-color;
+@btn-primary-bg:                 @brand-primary;
+@btn-primary-border:             @btn-primary-bg;
+
+@btn-success-color:              @btn-default-color;
+@btn-success-bg:                 @brand-success;
+@btn-success-border:             @btn-success-bg;
+
+@btn-info-color:                 @btn-default-color;
+@btn-info-bg:                    @brand-info;
+@btn-info-border:                @btn-info-bg;
+
+@btn-warning-color:              @btn-default-color;
+@btn-warning-bg:                 @brand-warning;
+@btn-warning-border:             @btn-warning-bg;
+
+@btn-danger-color:               @btn-default-color;
+@btn-danger-bg:                  @brand-danger;
+@btn-danger-border:              @btn-danger-bg;
+
+@btn-link-disabled-color:        @gray-light;
+
+// Allows for customizing button radius independently from global border radius
+@btn-border-radius-base:         @border-radius-base;
+@btn-border-radius-large:        @border-radius-large;
+@btn-border-radius-small:        @border-radius-small;
+
+
+//== Forms
+//
+//##
+
+//** `` background color
+@input-bg:                       #fff;
+//** `` background color
+@input-bg-disabled:              @gray-lighter;
+
+//** Text color for ``s
+@input-color:                    @text-color;
+//** `` border color
+@input-border:                   #ccc;
+
+// TODO: Rename `@input-border-radius` to `@input-border-radius-base` in v4
+//** Default `.form-control` border radius
+// This has no effect on ``s in CSS.
+@input-border-radius:            @border-radius-base;
+//** Large `.form-control` border radius
+@input-border-radius-large:      @border-radius-large;
+//** Small `.form-control` border radius
+@input-border-radius-small:      @border-radius-small;
+
+//** Border color for inputs on focus
+@input-border-focus:             #66afe9;
+
+//** Placeholder text color
+@input-color-placeholder:        @gray-light;
+
+//** Default `.form-control` height
+@input-height-base:              (@line-height-computed + (@padding-base-vertical * 2) + 2);
+//** Large `.form-control` height
+@input-height-large:             (ceil(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2);
+//** Small `.form-control` height
+@input-height-small:             (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2);
+
+//** `.form-group` margin
+@form-group-margin-bottom:       15px;
+
+@legend-color:                   @text-color;
+@legend-border-color:            #e5e5e5;
+
+//** Background color for textual input addons
+@input-group-addon-bg:           @gray-lighter;
+//** Border color for textual input addons
+@input-group-addon-border-color: @input-border;
+
+//** Disabled cursor for form controls and buttons.
+@cursor-disabled:                not-allowed;
+
+
+//== Dropdowns
+//
+//## Dropdown menu container and contents.
+
+//** Background for the dropdown menu.
+@dropdown-bg:                    #fff;
+//** Dropdown menu `border-color`.
+@dropdown-border:                rgba(0,0,0,.15);
+//** Dropdown menu `border-color` **for IE8**.
+@dropdown-fallback-border:       #ccc;
+//** Divider color for between dropdown items.
+@dropdown-divider-bg:            #e5e5e5;
+
+//** Dropdown link text color.
+@dropdown-link-color:            @gray-dark;
+//** Hover color for dropdown links.
+@dropdown-link-hover-color:      #fff;
+//** Hover background for dropdown links.
+@dropdown-link-hover-bg:         @component-active-bg;
+
+//** Active dropdown menu item text color.
+@dropdown-link-active-color:     #fff;
+//** Active dropdown menu item background color.
+@dropdown-link-active-bg:        @component-active-bg;
+
+//** Disabled dropdown menu item background color.
+@dropdown-link-disabled-color:   @gray-light;
+
+//** Text color for headers within dropdown menus.
+@dropdown-header-color:          @gray-light;
+
+//** Deprecated `@dropdown-caret-color` as of v3.1.0
+@dropdown-caret-color:           #000;
+
+
+//-- Z-index master list
+//
+// Warning: Avoid customizing these values. They're used for a bird's eye view
+// of components dependent on the z-axis and are designed to all work together.
+//
+// Note: These variables are not generated into the Customizer.
+
+@zindex-navbar:            1000;
+@zindex-dropdown:          1000;
+@zindex-popover:           1060;
+@zindex-tooltip:           1070;
+@zindex-navbar-fixed:      1030;
+@zindex-modal-background:  1040;
+@zindex-modal:             1050;
+
+
+//== Media queries breakpoints
+//
+//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
+
+// Extra small screen / phone
+//** Deprecated `@screen-xs` as of v3.0.1
+@screen-xs:                  480px;
+//** Deprecated `@screen-xs-min` as of v3.2.0
+@screen-xs-min:              @screen-xs;
+//** Deprecated `@screen-phone` as of v3.0.1
+@screen-phone:               @screen-xs-min;
+
+// Small screen / tablet
+//** Deprecated `@screen-sm` as of v3.0.1
+@screen-sm:                  768px;
+@screen-sm-min:              @screen-sm;
+//** Deprecated `@screen-tablet` as of v3.0.1
+@screen-tablet:              @screen-sm-min;
+
+// Medium screen / desktop
+//** Deprecated `@screen-md` as of v3.0.1
+@screen-md:                  992px;
+@screen-md-min:              @screen-md;
+//** Deprecated `@screen-desktop` as of v3.0.1
+@screen-desktop:             @screen-md-min;
+
+// Large screen / wide desktop
+//** Deprecated `@screen-lg` as of v3.0.1
+@screen-lg:                  1200px;
+@screen-lg-min:              @screen-lg;
+//** Deprecated `@screen-lg-desktop` as of v3.0.1
+@screen-lg-desktop:          @screen-lg-min;
+
+// So media queries don't overlap when required, provide a maximum
+@screen-xs-max:              (@screen-sm-min - 1);
+@screen-sm-max:              (@screen-md-min - 1);
+@screen-md-max:              (@screen-lg-min - 1);
+
+
+//== Grid system
+//
+//## Define your custom responsive grid.
+
+//** Number of columns in the grid.
+@grid-columns:              12;
+//** Padding between columns. Gets divided in half for the left and right.
+@grid-gutter-width:         30px;
+// Navbar collapse
+//** Point at which the navbar becomes uncollapsed.
+@grid-float-breakpoint:     @screen-sm-min;
+//** Point at which the navbar begins collapsing.
+@grid-float-breakpoint-max: (@grid-float-breakpoint - 1);
+
+
+//== Container sizes
+//
+//## Define the maximum width of `.container` for different screen sizes.
+
+// Small screen / tablet
+@container-tablet:             (720px + @grid-gutter-width);
+//** For `@screen-sm-min` and up.
+@container-sm:                 @container-tablet;
+
+// Medium screen / desktop
+@container-desktop:            (940px + @grid-gutter-width);
+//** For `@screen-md-min` and up.
+@container-md:                 @container-desktop;
+
+// Large screen / wide desktop
+@container-large-desktop:      (1140px + @grid-gutter-width);
+//** For `@screen-lg-min` and up.
+@container-lg:                 @container-large-desktop;
+
+
+//== Navbar
+//
+//##
+
+// Basics of a navbar
+@navbar-height:                    50px;
+@navbar-margin-bottom:             @line-height-computed;
+@navbar-border-radius:             @border-radius-base;
+@navbar-padding-horizontal:        floor((@grid-gutter-width / 2));
+@navbar-padding-vertical:          ((@navbar-height - @line-height-computed) / 2);
+@navbar-collapse-max-height:       340px;
+
+@navbar-default-color:             #fff;
+@navbar-default-bg:                @gray-darker;
+@navbar-default-border:            darken(@navbar-default-bg, 6.5%);
+
+// Navbar links
+@navbar-default-link-color:                #fff;
+@navbar-default-link-hover-color:          #fff;
+@navbar-default-link-hover-bg:             darken(@navbar-default-bg, 10%);
+@navbar-default-link-active-color:         @navbar-default-link-hover-color;
+@navbar-default-link-active-bg:            @navbar-default-link-hover-bg;
+@navbar-default-link-disabled-color:       #ccc;
+@navbar-default-link-disabled-bg:          transparent;
+
+// Navbar brand label
+@navbar-default-brand-color:               @navbar-default-link-color;
+@navbar-default-brand-hover-color:         #fff;
+@navbar-default-brand-hover-bg:            none;
+
+// Navbar toggle
+@navbar-default-toggle-hover-bg:           @navbar-default-link-hover-bg;
+@navbar-default-toggle-icon-bar-bg:        #fff;
+@navbar-default-toggle-border-color:       transparent;
+
+
+//=== Inverted navbar
+// Reset inverted navbar basics
+@navbar-inverse-color:                      #fff;
+@navbar-inverse-bg:                         @brand-primary;
+@navbar-inverse-border:                     darken(@navbar-inverse-bg, 10%);
+
+// Inverted navbar links
+@navbar-inverse-link-color:                 #fff;
+@navbar-inverse-link-hover-color:           #fff;
+@navbar-inverse-link-hover-bg:              darken(@navbar-inverse-bg, 10%);
+@navbar-inverse-link-active-color:          @navbar-inverse-link-hover-color;
+@navbar-inverse-link-active-bg:             @navbar-inverse-link-hover-bg;
+@navbar-inverse-link-disabled-color:        #fff;
+@navbar-inverse-link-disabled-bg:           transparent;
+
+// Inverted navbar brand label
+@navbar-inverse-brand-color:                @navbar-inverse-link-color;
+@navbar-inverse-brand-hover-color:          #fff;
+@navbar-inverse-brand-hover-bg:             none;
+
+// Inverted navbar toggle
+@navbar-inverse-toggle-hover-bg:            @navbar-inverse-link-hover-bg;
+@navbar-inverse-toggle-icon-bar-bg:         #fff;
+@navbar-inverse-toggle-border-color:        transparent;
+
+
+//== Navs
+//
+//##
+
+//=== Shared nav styles
+@nav-link-padding:                          10px 15px;
+@nav-link-hover-bg:                         @gray-lighter;
+
+@nav-disabled-link-color:                   @gray-light;
+@nav-disabled-link-hover-color:             @gray-light;
+
+//== Tabs
+@nav-tabs-border-color:                     #ddd;
+
+@nav-tabs-link-hover-border-color:          @gray-lighter;
+
+@nav-tabs-active-link-hover-bg:             @body-bg;
+@nav-tabs-active-link-hover-color:          @gray;
+@nav-tabs-active-link-hover-border-color:   #ddd;
+
+@nav-tabs-justified-link-border-color:            #ddd;
+@nav-tabs-justified-active-link-border-color:     @body-bg;
+
+//== Pills
+@nav-pills-border-radius:                   @border-radius-base;
+@nav-pills-active-link-hover-bg:            @component-active-bg;
+@nav-pills-active-link-hover-color:         @component-active-color;
+
+
+//== Pagination
+//
+//##
+
+@pagination-color:                     @link-color;
+@pagination-bg:                        #fff;
+@pagination-border:                    #ddd;
+
+@pagination-hover-color:               @link-hover-color;
+@pagination-hover-bg:                  @gray-lighter;
+@pagination-hover-border:              #ddd;
+
+@pagination-active-color:              @gray-light;
+@pagination-active-bg:                 #f5f5f5;
+@pagination-active-border:             #ddd;
+
+@pagination-disabled-color:            @gray-light;
+@pagination-disabled-bg:               #fff;
+@pagination-disabled-border:           #ddd;
+
+
+//== Pager
+//
+//##
+
+@pager-bg:                             @pagination-bg;
+@pager-border:                         @pagination-border;
+@pager-border-radius:                  @border-radius-base;
+
+@pager-hover-bg:                       @pagination-hover-bg;
+
+@pager-active-bg:                      @pagination-active-bg;
+@pager-active-color:                   @pagination-active-color;
+
+@pager-disabled-color:                 @gray-light;
+
+
+//== Jumbotron
+//
+//##
+
+@jumbotron-padding:              30px;
+@jumbotron-color:                inherit;
+@jumbotron-bg:                   @gray-lighter;
+@jumbotron-heading-color:        inherit;
+@jumbotron-font-size:            ceil((@font-size-base * 1.5));
+@jumbotron-heading-font-size:    ceil((@font-size-base * 4.5));
+
+
+//== Form states and alerts
+//
+//## Define colors for form feedback states and, by default, alerts.
+
+@state-success-text:             #fff;
+@state-success-bg:               @brand-success;
+@state-success-border:           darken(spin(@state-success-bg, -10), 5%);
+
+@state-info-text:                #fff;
+@state-info-bg:                  @brand-info;
+@state-info-border:              darken(spin(@state-info-bg, -10), 7%);
+
+@state-warning-text:             #fff;
+@state-warning-bg:               @brand-warning;
+@state-warning-border:           darken(spin(@state-warning-bg, -10), 3%);
+
+@state-danger-text:              #fff;
+@state-danger-bg:                @brand-danger;
+@state-danger-border:            darken(spin(@state-danger-bg, -10), 3%);
+
+
+//== Tooltips
+//
+//##
+
+//** Tooltip max width
+@tooltip-max-width:           200px;
+//** Tooltip text color
+@tooltip-color:               #fff;
+//** Tooltip background color
+@tooltip-bg:                  #000;
+@tooltip-opacity:             .9;
+
+//** Tooltip arrow width
+@tooltip-arrow-width:         5px;
+//** Tooltip arrow color
+@tooltip-arrow-color:         @tooltip-bg;
+
+
+//== Popovers
+//
+//##
+
+//** Popover body background color
+@popover-bg:                          #fff;
+//** Popover maximum width
+@popover-max-width:                   276px;
+//** Popover border color
+@popover-border-color:                rgba(0,0,0,.2);
+//** Popover fallback border color
+@popover-fallback-border-color:       #ccc;
+
+//** Popover title background color
+@popover-title-bg:                    darken(@popover-bg, 3%);
+
+//** Popover arrow width
+@popover-arrow-width:                 10px;
+//** Popover arrow color
+@popover-arrow-color:                 @popover-bg;
+
+//** Popover outer arrow width
+@popover-arrow-outer-width:           (@popover-arrow-width + 1);
+//** Popover outer arrow color
+@popover-arrow-outer-color:           fadein(@popover-border-color, 5%);
+//** Popover outer arrow fallback color
+@popover-arrow-outer-fallback-color:  darken(@popover-fallback-border-color, 20%);
+
+
+//== Labels
+//
+//##
+
+//** Default label background color
+@label-default-bg:            @btn-default-bg;
+//** Primary label background color
+@label-primary-bg:            @brand-primary;
+//** Success label background color
+@label-success-bg:            @brand-success;
+//** Info label background color
+@label-info-bg:               @brand-info;
+//** Warning label background color
+@label-warning-bg:            @brand-warning;
+//** Danger label background color
+@label-danger-bg:             @brand-danger;
+
+//** Default label text color
+@label-color:                 #fff;
+//** Default text color of a linked label
+@label-link-hover-color:      #fff;
+
+
+//== Modals
+//
+//##
+
+//** Padding applied to the modal body
+@modal-inner-padding:         20px;
+
+//** Padding applied to the modal title
+@modal-title-padding:         15px;
+//** Modal title line-height
+@modal-title-line-height:     @line-height-base;
+
+//** Background color of modal content area
+@modal-content-bg:                             #fff;
+//** Modal content border color
+@modal-content-border-color:                   transparent;
+//** Modal content border color **for IE8**
+@modal-content-fallback-border-color:          #999;
+
+//** Modal backdrop background color
+@modal-backdrop-bg:           #000;
+//** Modal backdrop opacity
+@modal-backdrop-opacity:      .5;
+//** Modal header border color
+@modal-header-border-color:   #e5e5e5;
+//** Modal footer border color
+@modal-footer-border-color:   @modal-header-border-color;
+
+@modal-lg:                    900px;
+@modal-md:                    600px;
+@modal-sm:                    300px;
+
+
+//== Alerts
+//
+//## Define alert colors, border radius, and padding.
+
+@alert-padding:               15px;
+@alert-border-radius:         @border-radius-base;
+@alert-link-font-weight:      bold;
+
+@alert-success-bg:            @state-success-bg;
+@alert-success-text:          @state-success-text;
+@alert-success-border:        @state-success-border;
+
+@alert-info-bg:               @state-info-bg;
+@alert-info-text:             @state-info-text;
+@alert-info-border:           @state-info-border;
+
+@alert-warning-bg:            @state-warning-bg;
+@alert-warning-text:          @state-warning-text;
+@alert-warning-border:        @state-warning-border;
+
+@alert-danger-bg:             @state-danger-bg;
+@alert-danger-text:           @state-danger-text;
+@alert-danger-border:         @state-danger-border;
+
+
+//== Progress bars
+//
+//##
+
+//** Background color of the whole progress component
+@progress-bg:                 #ccc;
+//** Progress bar text color
+@progress-bar-color:          #fff;
+//** Variable for setting rounded corners on progress bar.
+@progress-border-radius:      @border-radius-base;
+
+//** Default progress bar color
+@progress-bar-bg:             @brand-primary;
+//** Success progress bar color
+@progress-bar-success-bg:     @brand-success;
+//** Warning progress bar color
+@progress-bar-warning-bg:     @brand-warning;
+//** Danger progress bar color
+@progress-bar-danger-bg:      @brand-danger;
+//** Info progress bar color
+@progress-bar-info-bg:        @brand-info;
+
+
+//== List group
+//
+//##
+
+//** Background color on `.list-group-item`
+@list-group-bg:                 #fff;
+//** `.list-group-item` border color
+@list-group-border:             #ddd;
+//** List group border radius
+@list-group-border-radius:      @border-radius-base;
+
+//** Background color of single list items on hover
+@list-group-hover-bg:           #f5f5f5;
+//** Text color of active list items
+@list-group-active-color:       @component-active-color;
+//** Background color of active list items
+@list-group-active-bg:          @component-active-bg;
+//** Border color of active list elements
+@list-group-active-border:      @list-group-border;
+//** Text color for content within active list items
+@list-group-active-text-color:  lighten(@list-group-active-bg, 40%);
+
+//** Text color of disabled list items
+@list-group-disabled-color:      @gray-light;
+//** Background color of disabled list items
+@list-group-disabled-bg:         @gray-lighter;
+//** Text color for content within disabled list items
+@list-group-disabled-text-color: @list-group-disabled-color;
+
+@list-group-link-color:         #555;
+@list-group-link-hover-color:   @list-group-link-color;
+@list-group-link-heading-color: #333;
+
+
+//== Panels
+//
+//##
+
+@panel-bg:                    #fff;
+@panel-body-padding:          15px;
+@panel-heading-padding:       10px 15px;
+@panel-footer-padding:        @panel-heading-padding;
+@panel-border-radius:         @border-radius-base;
+
+//** Border color for elements within panels
+@panel-inner-border:          #ddd;
+@panel-footer-bg:             #f5f5f5;
+
+@panel-default-text:          @gray-dark;
+@panel-default-border:        #ddd;
+@panel-default-heading-bg:    #f5f5f5;
+
+@panel-primary-text:          #fff;
+@panel-primary-border:        @brand-primary;
+@panel-primary-heading-bg:    @brand-primary;
+
+@panel-success-text:          @state-success-text;
+@panel-success-border:        @state-success-border;
+@panel-success-heading-bg:    @state-success-bg;
+
+@panel-info-text:             @state-info-text;
+@panel-info-border:           @state-info-border;
+@panel-info-heading-bg:       @state-info-bg;
+
+@panel-warning-text:          @state-warning-text;
+@panel-warning-border:        @state-warning-border;
+@panel-warning-heading-bg:    @state-warning-bg;
+
+@panel-danger-text:           @state-danger-text;
+@panel-danger-border:         @state-danger-border;
+@panel-danger-heading-bg:     @state-danger-bg;
+
+
+//== Thumbnails
+//
+//##
+
+//** Padding around the thumbnail image
+@thumbnail-padding:           4px;
+//** Thumbnail background color
+@thumbnail-bg:                @body-bg;
+//** Thumbnail border color
+@thumbnail-border:            #ddd;
+//** Thumbnail border radius
+@thumbnail-border-radius:     @border-radius-base;
+
+//** Custom text color for thumbnail captions
+@thumbnail-caption-color:     @text-color;
+//** Padding around the thumbnail caption
+@thumbnail-caption-padding:   9px;
+
+
+//== Wells
+//
+//##
+
+@well-bg:                     #f5f5f5;
+@well-border:                 darken(@well-bg, 7%);
+
+
+//== Badges
+//
+//##
+
+@badge-color:                 #fff;
+//** Linked badge text color on hover
+@badge-link-hover-color:      #fff;
+@badge-bg:                    @brand-primary;
+
+//** Badge text color in active nav link
+@badge-active-color:          @link-color;
+//** Badge background color in active nav link
+@badge-active-bg:             #fff;
+
+@badge-font-weight:           bold;
+@badge-line-height:           1;
+@badge-border-radius:         10px;
+
+
+//== Breadcrumbs
+//
+//##
+
+@breadcrumb-padding-vertical:   8px;
+@breadcrumb-padding-horizontal: 15px;
+//** Breadcrumb background color
+@breadcrumb-bg:                 #f5f5f5;
+//** Breadcrumb text color
+@breadcrumb-color:              #ccc;
+//** Text color of current page in the breadcrumb
+@breadcrumb-active-color:       @gray-light;
+//** Textual separator for between breadcrumb elements
+@breadcrumb-separator:          "/";
+
+
+//== Carousel
+//
+//##
+
+@carousel-text-shadow:                        0 1px 2px rgba(0,0,0,.6);
+
+@carousel-control-color:                      #fff;
+@carousel-control-width:                      15%;
+@carousel-control-opacity:                    .5;
+@carousel-control-font-size:                  20px;
+
+@carousel-indicator-active-bg:                #fff;
+@carousel-indicator-border-color:             #fff;
+
+@carousel-caption-color:                      #fff;
+
+
+//== Close
+//
+//##
+
+@close-font-weight:           bold;
+@close-color:                 #fff;
+@close-text-shadow:           0 1px 0 #fff;
+
+
+//== Code
+//
+//##
+
+@code-color:                  #c7254e;
+@code-bg:                     #f9f2f4;
+
+@kbd-color:                   #fff;
+@kbd-bg:                      #333;
+
+@pre-bg:                      #f5f5f5;
+@pre-color:                   @gray-dark;
+@pre-border-color:            #ccc;
+@pre-scrollable-max-height:   340px;
+
+
+//== Type
+//
+//##
+
+//** Horizontal offset for forms and lists.
+@component-offset-horizontal: 180px;
+//** Text muted color
+@text-muted:                  @gray-light;
+//** Abbreviations and acronyms border color
+@abbr-border-color:           @gray-light;
+//** Headings small color
+@headings-small-color:        @gray-light;
+//** Blockquote small color
+@blockquote-small-color:      @gray-light;
+//** Blockquote font size
+@blockquote-font-size:        (@font-size-base * 1.25);
+//** Blockquote border color
+@blockquote-border-color:     @gray-lighter;
+//** Page header border color
+@page-header-border-color:    @gray-lighter;
+//** Width of horizontal description list titles
+@dl-horizontal-offset:        @component-offset-horizontal;
+//** Point at which .dl-horizontal becomes horizontal
+@dl-horizontal-breakpoint:    @grid-float-breakpoint;
+//** Horizontal line color.
+@hr-border:                   @gray-lighter;
diff --git a/modules/cms/src/main/resources/static/modules/cmsfront/themes/fonts/glyphicons-halflings-regular.eot b/modules/cms/src/main/resources/static/modules/cmsfront/themes/fonts/glyphicons-halflings-regular.eot
new file mode 100644
index 00000000..b93a4953
Binary files /dev/null and b/modules/cms/src/main/resources/static/modules/cmsfront/themes/fonts/glyphicons-halflings-regular.eot differ
diff --git a/modules/cms/src/main/resources/static/modules/cmsfront/themes/fonts/glyphicons-halflings-regular.svg b/modules/cms/src/main/resources/static/modules/cmsfront/themes/fonts/glyphicons-halflings-regular.svg
new file mode 100644
index 00000000..94fb5490
--- /dev/null
+++ b/modules/cms/src/main/resources/static/modules/cmsfront/themes/fonts/glyphicons-halflings-regular.svg
@@ -0,0 +1,288 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 
\ No newline at end of file
diff --git a/modules/cms/src/main/resources/static/modules/cmsfront/themes/fonts/glyphicons-halflings-regular.ttf b/modules/cms/src/main/resources/static/modules/cmsfront/themes/fonts/glyphicons-halflings-regular.ttf
new file mode 100644
index 00000000..1413fc60
Binary files /dev/null and b/modules/cms/src/main/resources/static/modules/cmsfront/themes/fonts/glyphicons-halflings-regular.ttf differ
diff --git a/modules/cms/src/main/resources/static/modules/cmsfront/themes/fonts/glyphicons-halflings-regular.woff b/modules/cms/src/main/resources/static/modules/cmsfront/themes/fonts/glyphicons-halflings-regular.woff
new file mode 100644
index 00000000..9e612858
Binary files /dev/null and b/modules/cms/src/main/resources/static/modules/cmsfront/themes/fonts/glyphicons-halflings-regular.woff differ
diff --git a/modules/cms/src/main/resources/static/modules/cmsfront/themes/fonts/glyphicons-halflings-regular.woff2 b/modules/cms/src/main/resources/static/modules/cmsfront/themes/fonts/glyphicons-halflings-regular.woff2
new file mode 100644
index 00000000..64539b54
Binary files /dev/null and b/modules/cms/src/main/resources/static/modules/cmsfront/themes/fonts/glyphicons-halflings-regular.woff2 differ
diff --git a/modules/cms/src/main/resources/static/modules/cmsfront/themes/js/bootstrap.js b/modules/cms/src/main/resources/static/modules/cmsfront/themes/js/bootstrap.js
new file mode 100644
index 00000000..170bd608
--- /dev/null
+++ b/modules/cms/src/main/resources/static/modules/cmsfront/themes/js/bootstrap.js
@@ -0,0 +1,2580 @@
+/*!
+ * Bootstrap v3.4.1 (https://getbootstrap.com/)
+ * Copyright 2011-2019 Twitter, Inc.
+ * Licensed under the MIT license
+ */
+
+if (typeof jQuery === 'undefined') {
+  throw new Error('Bootstrap\'s JavaScript requires jQuery')
+}
+
++function ($) {
+  'use strict';
+  var version = $.fn.jquery.split(' ')[0].split('.')
+  if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
+    throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
+  }
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: transition.js v3.4.1
+ * https://getbootstrap.com/docs/3.4/javascript/#transitions
+ * ========================================================================
+ * Copyright 2011-2019 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // CSS TRANSITION SUPPORT (Shoutout: https://modernizr.com/)
+  // ============================================================
+
+  function transitionEnd() {
+    var el = document.createElement('bootstrap')
+
+    var transEndEventNames = {
+      WebkitTransition : 'webkitTransitionEnd',
+      MozTransition    : 'transitionend',
+      OTransition      : 'oTransitionEnd otransitionend',
+      transition       : 'transitionend'
+    }
+
+    for (var name in transEndEventNames) {
+      if (el.style[name] !== undefined) {
+        return { end: transEndEventNames[name] }
+      }
+    }
+
+    return false // explicit for ie8 (  ._.)
+  }
+
+  // https://blog.alexmaccaw.com/css-transitions
+  $.fn.emulateTransitionEnd = function (duration) {
+    var called = false
+    var $el = this
+    $(this).one('bsTransitionEnd', function () { called = true })
+    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
+    setTimeout(callback, duration)
+    return this
+  }
+
+  $(function () {
+    $.support.transition = transitionEnd()
+
+    if (!$.support.transition) return
+
+    $.event.special.bsTransitionEnd = {
+      bindType: $.support.transition.end,
+      delegateType: $.support.transition.end,
+      handle: function (e) {
+        if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
+      }
+    }
+  })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: alert.js v3.4.1
+ * https://getbootstrap.com/docs/3.4/javascript/#alerts
+ * ========================================================================
+ * Copyright 2011-2019 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // ALERT CLASS DEFINITION
+  // ======================
+
+  var dismiss = '[data-dismiss="alert"]'
+  var Alert   = function (el) {
+    $(el).on('click', dismiss, this.close)
+  }
+
+  Alert.VERSION = '3.4.1'
+
+  Alert.TRANSITION_DURATION = 150
+
+  Alert.prototype.close = function (e) {
+    var $this    = $(this)
+    var selector = $this.attr('data-target')
+
+    if (!selector) {
+      selector = $this.attr('href')
+      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
+    }
+
+    selector    = selector === '#' ? [] : selector
+    var $parent = $(document).find(selector)
+
+    if (e) e.preventDefault()
+
+    if (!$parent.length) {
+      $parent = $this.closest('.alert')
+    }
+
+    $parent.trigger(e = $.Event('close.bs.alert'))
+
+    if (e.isDefaultPrevented()) return
+
+    $parent.removeClass('in')
+
+    function removeElement() {
+      // detach from parent, fire event then clean up data
+      $parent.detach().trigger('closed.bs.alert').remove()
+    }
+
+    $.support.transition && $parent.hasClass('fade') ?
+      $parent
+        .one('bsTransitionEnd', removeElement)
+        .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
+      removeElement()
+  }
+
+
+  // ALERT PLUGIN DEFINITION
+  // =======================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this = $(this)
+      var data  = $this.data('bs.alert')
+
+      if (!data) $this.data('bs.alert', (data = new Alert(this)))
+      if (typeof option == 'string') data[option].call($this)
+    })
+  }
+
+  var old = $.fn.alert
+
+  $.fn.alert             = Plugin
+  $.fn.alert.Constructor = Alert
+
+
+  // ALERT NO CONFLICT
+  // =================
+
+  $.fn.alert.noConflict = function () {
+    $.fn.alert = old
+    return this
+  }
+
+
+  // ALERT DATA-API
+  // ==============
+
+  $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: button.js v3.4.1
+ * https://getbootstrap.com/docs/3.4/javascript/#buttons
+ * ========================================================================
+ * Copyright 2011-2019 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // BUTTON PUBLIC CLASS DEFINITION
+  // ==============================
+
+  var Button = function (element, options) {
+    this.$element  = $(element)
+    this.options   = $.extend({}, Button.DEFAULTS, options)
+    this.isLoading = false
+  }
+
+  Button.VERSION  = '3.4.1'
+
+  Button.DEFAULTS = {
+    loadingText: 'loading...'
+  }
+
+  Button.prototype.setState = function (state) {
+    var d    = 'disabled'
+    var $el  = this.$element
+    var val  = $el.is('input') ? 'val' : 'html'
+    var data = $el.data()
+
+    state += 'Text'
+
+    if (data.resetText == null) $el.data('resetText', $el[val]())
+
+    // push to event loop to allow forms to submit
+    setTimeout($.proxy(function () {
+      $el[val](data[state] == null ? this.options[state] : data[state])
+
+      if (state == 'loadingText') {
+        this.isLoading = true
+        $el.addClass(d).attr(d, d).prop(d, true)
+      } else if (this.isLoading) {
+        this.isLoading = false
+        $el.removeClass(d).removeAttr(d).prop(d, false)
+      }
+    }, this), 0)
+  }
+
+  Button.prototype.toggle = function () {
+    var changed = true
+    var $parent = this.$element.closest('[data-toggle="buttons"]')
+
+    if ($parent.length) {
+      var $input = this.$element.find('input')
+      if ($input.prop('type') == 'radio') {
+        if ($input.prop('checked')) changed = false
+        $parent.find('.active').removeClass('active')
+        this.$element.addClass('active')
+      } else if ($input.prop('type') == 'checkbox') {
+        if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false
+        this.$element.toggleClass('active')
+      }
+      $input.prop('checked', this.$element.hasClass('active'))
+      if (changed) $input.trigger('change')
+    } else {
+      this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
+      this.$element.toggleClass('active')
+    }
+  }
+
+
+  // BUTTON PLUGIN DEFINITION
+  // ========================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this   = $(this)
+      var data    = $this.data('bs.button')
+      var options = typeof option == 'object' && option
+
+      if (!data) $this.data('bs.button', (data = new Button(this, options)))
+
+      if (option == 'toggle') data.toggle()
+      else if (option) data.setState(option)
+    })
+  }
+
+  var old = $.fn.button
+
+  $.fn.button             = Plugin
+  $.fn.button.Constructor = Button
+
+
+  // BUTTON NO CONFLICT
+  // ==================
+
+  $.fn.button.noConflict = function () {
+    $.fn.button = old
+    return this
+  }
+
+
+  // BUTTON DATA-API
+  // ===============
+
+  $(document)
+    .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
+      var $btn = $(e.target).closest('.btn')
+      Plugin.call($btn, 'toggle')
+      if (!($(e.target).is('input[type="radio"], input[type="checkbox"]'))) {
+        // Prevent double click on radios, and the double selections (so cancellation) on checkboxes
+        e.preventDefault()
+        // The target component still receive the focus
+        if ($btn.is('input,button')) $btn.trigger('focus')
+        else $btn.find('input:visible,button:visible').first().trigger('focus')
+      }
+    })
+    .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
+      $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
+    })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: carousel.js v3.4.1
+ * https://getbootstrap.com/docs/3.4/javascript/#carousel
+ * ========================================================================
+ * Copyright 2011-2019 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // CAROUSEL CLASS DEFINITION
+  // =========================
+
+  var Carousel = function (element, options) {
+    this.$element    = $(element)
+    this.$indicators = this.$element.find('.carousel-indicators')
+    this.options     = options
+    this.paused      = null
+    this.sliding     = null
+    this.interval    = null
+    this.$active     = null
+    this.$items      = null
+
+    this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
+
+    this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
+      .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
+      .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
+  }
+
+  Carousel.VERSION  = '3.4.1'
+
+  Carousel.TRANSITION_DURATION = 600
+
+  Carousel.DEFAULTS = {
+    interval: 5000,
+    pause: 'hover',
+    wrap: true,
+    keyboard: true
+  }
+
+  Carousel.prototype.keydown = function (e) {
+    if (/input|textarea/i.test(e.target.tagName)) return
+    switch (e.which) {
+      case 37: this.prev(); break
+      case 39: this.next(); break
+      default: return
+    }
+
+    e.preventDefault()
+  }
+
+  Carousel.prototype.cycle = function (e) {
+    e || (this.paused = false)
+
+    this.interval && clearInterval(this.interval)
+
+    this.options.interval
+      && !this.paused
+      && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
+
+    return this
+  }
+
+  Carousel.prototype.getItemIndex = function (item) {
+    this.$items = item.parent().children('.item')
+    return this.$items.index(item || this.$active)
+  }
+
+  Carousel.prototype.getItemForDirection = function (direction, active) {
+    var activeIndex = this.getItemIndex(active)
+    var willWrap = (direction == 'prev' && activeIndex === 0)
+                || (direction == 'next' && activeIndex == (this.$items.length - 1))
+    if (willWrap && !this.options.wrap) return active
+    var delta = direction == 'prev' ? -1 : 1
+    var itemIndex = (activeIndex + delta) % this.$items.length
+    return this.$items.eq(itemIndex)
+  }
+
+  Carousel.prototype.to = function (pos) {
+    var that        = this
+    var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
+
+    if (pos > (this.$items.length - 1) || pos < 0) return
+
+    if (this.sliding)       return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
+    if (activeIndex == pos) return this.pause().cycle()
+
+    return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
+  }
+
+  Carousel.prototype.pause = function (e) {
+    e || (this.paused = true)
+
+    if (this.$element.find('.next, .prev').length && $.support.transition) {
+      this.$element.trigger($.support.transition.end)
+      this.cycle(true)
+    }
+
+    this.interval = clearInterval(this.interval)
+
+    return this
+  }
+
+  Carousel.prototype.next = function () {
+    if (this.sliding) return
+    return this.slide('next')
+  }
+
+  Carousel.prototype.prev = function () {
+    if (this.sliding) return
+    return this.slide('prev')
+  }
+
+  Carousel.prototype.slide = function (type, next) {
+    var $active   = this.$element.find('.item.active')
+    var $next     = next || this.getItemForDirection(type, $active)
+    var isCycling = this.interval
+    var direction = type == 'next' ? 'left' : 'right'
+    var that      = this
+
+    if ($next.hasClass('active')) return (this.sliding = false)
+
+    var relatedTarget = $next[0]
+    var slideEvent = $.Event('slide.bs.carousel', {
+      relatedTarget: relatedTarget,
+      direction: direction
+    })
+    this.$element.trigger(slideEvent)
+    if (slideEvent.isDefaultPrevented()) return
+
+    this.sliding = true
+
+    isCycling && this.pause()
+
+    if (this.$indicators.length) {
+      this.$indicators.find('.active').removeClass('active')
+      var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
+      $nextIndicator && $nextIndicator.addClass('active')
+    }
+
+    var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
+    if ($.support.transition && this.$element.hasClass('slide')) {
+      $next.addClass(type)
+      if (typeof $next === 'object' && $next.length) {
+        $next[0].offsetWidth // force reflow
+      }
+      $active.addClass(direction)
+      $next.addClass(direction)
+      $active
+        .one('bsTransitionEnd', function () {
+          $next.removeClass([type, direction].join(' ')).addClass('active')
+          $active.removeClass(['active', direction].join(' '))
+          that.sliding = false
+          setTimeout(function () {
+            that.$element.trigger(slidEvent)
+          }, 0)
+        })
+        .emulateTransitionEnd(Carousel.TRANSITION_DURATION)
+    } else {
+      $active.removeClass('active')
+      $next.addClass('active')
+      this.sliding = false
+      this.$element.trigger(slidEvent)
+    }
+
+    isCycling && this.cycle()
+
+    return this
+  }
+
+
+  // CAROUSEL PLUGIN DEFINITION
+  // ==========================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this   = $(this)
+      var data    = $this.data('bs.carousel')
+      var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
+      var action  = typeof option == 'string' ? option : options.slide
+
+      if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
+      if (typeof option == 'number') data.to(option)
+      else if (action) data[action]()
+      else if (options.interval) data.pause().cycle()
+    })
+  }
+
+  var old = $.fn.carousel
+
+  $.fn.carousel             = Plugin
+  $.fn.carousel.Constructor = Carousel
+
+
+  // CAROUSEL NO CONFLICT
+  // ====================
+
+  $.fn.carousel.noConflict = function () {
+    $.fn.carousel = old
+    return this
+  }
+
+
+  // CAROUSEL DATA-API
+  // =================
+
+  var clickHandler = function (e) {
+    var $this   = $(this)
+    var href    = $this.attr('href')
+    if (href) {
+      href = href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
+    }
+
+    var target  = $this.attr('data-target') || href
+    var $target = $(document).find(target)
+
+    if (!$target.hasClass('carousel')) return
+
+    var options = $.extend({}, $target.data(), $this.data())
+    var slideIndex = $this.attr('data-slide-to')
+    if (slideIndex) options.interval = false
+
+    Plugin.call($target, options)
+
+    if (slideIndex) {
+      $target.data('bs.carousel').to(slideIndex)
+    }
+
+    e.preventDefault()
+  }
+
+  $(document)
+    .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
+    .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
+
+  $(window).on('load', function () {
+    $('[data-ride="carousel"]').each(function () {
+      var $carousel = $(this)
+      Plugin.call($carousel, $carousel.data())
+    })
+  })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: collapse.js v3.4.1
+ * https://getbootstrap.com/docs/3.4/javascript/#collapse
+ * ========================================================================
+ * Copyright 2011-2019 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+/* jshint latedef: false */
+
++function ($) {
+  'use strict';
+
+  // COLLAPSE PUBLIC CLASS DEFINITION
+  // ================================
+
+  var Collapse = function (element, options) {
+    this.$element      = $(element)
+    this.options       = $.extend({}, Collapse.DEFAULTS, options)
+    this.$trigger      = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
+                           '[data-toggle="collapse"][data-target="#' + element.id + '"]')
+    this.transitioning = null
+
+    if (this.options.parent) {
+      this.$parent = this.getParent()
+    } else {
+      this.addAriaAndCollapsedClass(this.$element, this.$trigger)
+    }
+
+    if (this.options.toggle) this.toggle()
+  }
+
+  Collapse.VERSION  = '3.4.1'
+
+  Collapse.TRANSITION_DURATION = 350
+
+  Collapse.DEFAULTS = {
+    toggle: true
+  }
+
+  Collapse.prototype.dimension = function () {
+    var hasWidth = this.$element.hasClass('width')
+    return hasWidth ? 'width' : 'height'
+  }
+
+  Collapse.prototype.show = function () {
+    if (this.transitioning || this.$element.hasClass('in')) return
+
+    var activesData
+    var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
+
+    if (actives && actives.length) {
+      activesData = actives.data('bs.collapse')
+      if (activesData && activesData.transitioning) return
+    }
+
+    var startEvent = $.Event('show.bs.collapse')
+    this.$element.trigger(startEvent)
+    if (startEvent.isDefaultPrevented()) return
+
+    if (actives && actives.length) {
+      Plugin.call(actives, 'hide')
+      activesData || actives.data('bs.collapse', null)
+    }
+
+    var dimension = this.dimension()
+
+    this.$element
+      .removeClass('collapse')
+      .addClass('collapsing')[dimension](0)
+      .attr('aria-expanded', true)
+
+    this.$trigger
+      .removeClass('collapsed')
+      .attr('aria-expanded', true)
+
+    this.transitioning = 1
+
+    var complete = function () {
+      this.$element
+        .removeClass('collapsing')
+        .addClass('collapse in')[dimension]('')
+      this.transitioning = 0
+      this.$element
+        .trigger('shown.bs.collapse')
+    }
+
+    if (!$.support.transition) return complete.call(this)
+
+    var scrollSize = $.camelCase(['scroll', dimension].join('-'))
+
+    this.$element
+      .one('bsTransitionEnd', $.proxy(complete, this))
+      .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
+  }
+
+  Collapse.prototype.hide = function () {
+    if (this.transitioning || !this.$element.hasClass('in')) return
+
+    var startEvent = $.Event('hide.bs.collapse')
+    this.$element.trigger(startEvent)
+    if (startEvent.isDefaultPrevented()) return
+
+    var dimension = this.dimension()
+
+    this.$element[dimension](this.$element[dimension]())[0].offsetHeight
+
+    this.$element
+      .addClass('collapsing')
+      .removeClass('collapse in')
+      .attr('aria-expanded', false)
+
+    this.$trigger
+      .addClass('collapsed')
+      .attr('aria-expanded', false)
+
+    this.transitioning = 1
+
+    var complete = function () {
+      this.transitioning = 0
+      this.$element
+        .removeClass('collapsing')
+        .addClass('collapse')
+        .trigger('hidden.bs.collapse')
+    }
+
+    if (!$.support.transition) return complete.call(this)
+
+    this.$element
+      [dimension](0)
+      .one('bsTransitionEnd', $.proxy(complete, this))
+      .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
+  }
+
+  Collapse.prototype.toggle = function () {
+    this[this.$element.hasClass('in') ? 'hide' : 'show']()
+  }
+
+  Collapse.prototype.getParent = function () {
+    return $(document).find(this.options.parent)
+      .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
+      .each($.proxy(function (i, element) {
+        var $element = $(element)
+        this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
+      }, this))
+      .end()
+  }
+
+  Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
+    var isOpen = $element.hasClass('in')
+
+    $element.attr('aria-expanded', isOpen)
+    $trigger
+      .toggleClass('collapsed', !isOpen)
+      .attr('aria-expanded', isOpen)
+  }
+
+  function getTargetFromTrigger($trigger) {
+    var href
+    var target = $trigger.attr('data-target')
+      || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
+
+    return $(document).find(target)
+  }
+
+
+  // COLLAPSE PLUGIN DEFINITION
+  // ==========================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this   = $(this)
+      var data    = $this.data('bs.collapse')
+      var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
+
+      if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
+      if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  var old = $.fn.collapse
+
+  $.fn.collapse             = Plugin
+  $.fn.collapse.Constructor = Collapse
+
+
+  // COLLAPSE NO CONFLICT
+  // ====================
+
+  $.fn.collapse.noConflict = function () {
+    $.fn.collapse = old
+    return this
+  }
+
+
+  // COLLAPSE DATA-API
+  // =================
+
+  $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
+    var $this   = $(this)
+
+    if (!$this.attr('data-target')) e.preventDefault()
+
+    var $target = getTargetFromTrigger($this)
+    var data    = $target.data('bs.collapse')
+    var option  = data ? 'toggle' : $this.data()
+
+    Plugin.call($target, option)
+  })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: dropdown.js v3.4.1
+ * https://getbootstrap.com/docs/3.4/javascript/#dropdowns
+ * ========================================================================
+ * Copyright 2011-2019 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // DROPDOWN CLASS DEFINITION
+  // =========================
+
+  var backdrop = '.dropdown-backdrop'
+  var toggle   = '[data-toggle="dropdown"]'
+  var Dropdown = function (element) {
+    $(element).on('click.bs.dropdown', this.toggle)
+  }
+
+  Dropdown.VERSION = '3.4.1'
+
+  function getParent($this) {
+    var selector = $this.attr('data-target')
+
+    if (!selector) {
+      selector = $this.attr('href')
+      selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
+    }
+
+    var $parent = selector !== '#' ? $(document).find(selector) : null
+
+    return $parent && $parent.length ? $parent : $this.parent()
+  }
+
+  function clearMenus(e) {
+    if (e && e.which === 3) return
+    $(backdrop).remove()
+    $(toggle).each(function () {
+      var $this         = $(this)
+      var $parent       = getParent($this)
+      var relatedTarget = { relatedTarget: this }
+
+      if (!$parent.hasClass('open')) return
+
+      if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return
+
+      $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
+
+      if (e.isDefaultPrevented()) return
+
+      $this.attr('aria-expanded', 'false')
+      $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget))
+    })
+  }
+
+  Dropdown.prototype.toggle = function (e) {
+    var $this = $(this)
+
+    if ($this.is('.disabled, :disabled')) return
+
+    var $parent  = getParent($this)
+    var isActive = $parent.hasClass('open')
+
+    clearMenus()
+
+    if (!isActive) {
+      if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
+        // if mobile we use a backdrop because click events don't delegate
+        $(document.createElement('div'))
+          .addClass('dropdown-backdrop')
+          .insertAfter($(this))
+          .on('click', clearMenus)
+      }
+
+      var relatedTarget = { relatedTarget: this }
+      $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
+
+      if (e.isDefaultPrevented()) return
+
+      $this
+        .trigger('focus')
+        .attr('aria-expanded', 'true')
+
+      $parent
+        .toggleClass('open')
+        .trigger($.Event('shown.bs.dropdown', relatedTarget))
+    }
+
+    return false
+  }
+
+  Dropdown.prototype.keydown = function (e) {
+    if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
+
+    var $this = $(this)
+
+    e.preventDefault()
+    e.stopPropagation()
+
+    if ($this.is('.disabled, :disabled')) return
+
+    var $parent  = getParent($this)
+    var isActive = $parent.hasClass('open')
+
+    if (!isActive && e.which != 27 || isActive && e.which == 27) {
+      if (e.which == 27) $parent.find(toggle).trigger('focus')
+      return $this.trigger('click')
+    }
+
+    var desc = ' li:not(.disabled):visible a'
+    var $items = $parent.find('.dropdown-menu' + desc)
+
+    if (!$items.length) return
+
+    var index = $items.index(e.target)
+
+    if (e.which == 38 && index > 0)                 index--         // up
+    if (e.which == 40 && index < $items.length - 1) index++         // down
+    if (!~index)                                    index = 0
+
+    $items.eq(index).trigger('focus')
+  }
+
+
+  // DROPDOWN PLUGIN DEFINITION
+  // ==========================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this = $(this)
+      var data  = $this.data('bs.dropdown')
+
+      if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
+      if (typeof option == 'string') data[option].call($this)
+    })
+  }
+
+  var old = $.fn.dropdown
+
+  $.fn.dropdown             = Plugin
+  $.fn.dropdown.Constructor = Dropdown
+
+
+  // DROPDOWN NO CONFLICT
+  // ====================
+
+  $.fn.dropdown.noConflict = function () {
+    $.fn.dropdown = old
+    return this
+  }
+
+
+  // APPLY TO STANDARD DROPDOWN ELEMENTS
+  // ===================================
+
+  $(document)
+    .on('click.bs.dropdown.data-api', clearMenus)
+    .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
+    .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
+    .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
+    .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: modal.js v3.4.1
+ * https://getbootstrap.com/docs/3.4/javascript/#modals
+ * ========================================================================
+ * Copyright 2011-2019 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // MODAL CLASS DEFINITION
+  // ======================
+
+  var Modal = function (element, options) {
+    this.options = options
+    this.$body = $(document.body)
+    this.$element = $(element)
+    this.$dialog = this.$element.find('.modal-dialog')
+    this.$backdrop = null
+    this.isShown = null
+    this.originalBodyPad = null
+    this.scrollbarWidth = 0
+    this.ignoreBackdropClick = false
+    this.fixedContent = '.navbar-fixed-top, .navbar-fixed-bottom'
+
+    if (this.options.remote) {
+      this.$element
+        .find('.modal-content')
+        .load(this.options.remote, $.proxy(function () {
+          this.$element.trigger('loaded.bs.modal')
+        }, this))
+    }
+  }
+
+  Modal.VERSION = '3.4.1'
+
+  Modal.TRANSITION_DURATION = 300
+  Modal.BACKDROP_TRANSITION_DURATION = 150
+
+  Modal.DEFAULTS = {
+    backdrop: true,
+    keyboard: true,
+    show: true
+  }
+
+  Modal.prototype.toggle = function (_relatedTarget) {
+    return this.isShown ? this.hide() : this.show(_relatedTarget)
+  }
+
+  Modal.prototype.show = function (_relatedTarget) {
+    var that = this
+    var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
+
+    this.$element.trigger(e)
+
+    if (this.isShown || e.isDefaultPrevented()) return
+
+    this.isShown = true
+
+    this.checkScrollbar()
+    this.setScrollbar()
+    this.$body.addClass('modal-open')
+
+    this.escape()
+    this.resize()
+
+    this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
+
+    this.$dialog.on('mousedown.dismiss.bs.modal', function () {
+      that.$element.one('mouseup.dismiss.bs.modal', function (e) {
+        if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true
+      })
+    })
+
+    this.backdrop(function () {
+      var transition = $.support.transition && that.$element.hasClass('fade')
+
+      if (!that.$element.parent().length) {
+        that.$element.appendTo(that.$body) // don't move modals dom position
+      }
+
+      that.$element
+        .show()
+        .scrollTop(0)
+
+      that.adjustDialog()
+
+      if (transition) {
+        that.$element[0].offsetWidth // force reflow
+      }
+
+      that.$element.addClass('in')
+
+      that.enforceFocus()
+
+      var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
+
+      transition ?
+        that.$dialog // wait for modal to slide in
+          .one('bsTransitionEnd', function () {
+            that.$element.trigger('focus').trigger(e)
+          })
+          .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
+        that.$element.trigger('focus').trigger(e)
+    })
+  }
+
+  Modal.prototype.hide = function (e) {
+    if (e) e.preventDefault()
+
+    e = $.Event('hide.bs.modal')
+
+    this.$element.trigger(e)
+
+    if (!this.isShown || e.isDefaultPrevented()) return
+
+    this.isShown = false
+
+    this.escape()
+    this.resize()
+
+    $(document).off('focusin.bs.modal')
+
+    this.$element
+      .removeClass('in')
+      .off('click.dismiss.bs.modal')
+      .off('mouseup.dismiss.bs.modal')
+
+    this.$dialog.off('mousedown.dismiss.bs.modal')
+
+    $.support.transition && this.$element.hasClass('fade') ?
+      this.$element
+        .one('bsTransitionEnd', $.proxy(this.hideModal, this))
+        .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
+      this.hideModal()
+  }
+
+  Modal.prototype.enforceFocus = function () {
+    $(document)
+      .off('focusin.bs.modal') // guard against infinite focus loop
+      .on('focusin.bs.modal', $.proxy(function (e) {
+        if (document !== e.target &&
+          this.$element[0] !== e.target &&
+          !this.$element.has(e.target).length) {
+          this.$element.trigger('focus')
+        }
+      }, this))
+  }
+
+  Modal.prototype.escape = function () {
+    if (this.isShown && this.options.keyboard) {
+      this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
+        e.which == 27 && this.hide()
+      }, this))
+    } else if (!this.isShown) {
+      this.$element.off('keydown.dismiss.bs.modal')
+    }
+  }
+
+  Modal.prototype.resize = function () {
+    if (this.isShown) {
+      $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
+    } else {
+      $(window).off('resize.bs.modal')
+    }
+  }
+
+  Modal.prototype.hideModal = function () {
+    var that = this
+    this.$element.hide()
+    this.backdrop(function () {
+      that.$body.removeClass('modal-open')
+      that.resetAdjustments()
+      that.resetScrollbar()
+      that.$element.trigger('hidden.bs.modal')
+    })
+  }
+
+  Modal.prototype.removeBackdrop = function () {
+    this.$backdrop && this.$backdrop.remove()
+    this.$backdrop = null
+  }
+
+  Modal.prototype.backdrop = function (callback) {
+    var that = this
+    var animate = this.$element.hasClass('fade') ? 'fade' : ''
+
+    if (this.isShown && this.options.backdrop) {
+      var doAnimate = $.support.transition && animate
+
+      this.$backdrop = $(document.createElement('div'))
+        .addClass('modal-backdrop ' + animate)
+        .appendTo(this.$body)
+
+      this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
+        if (this.ignoreBackdropClick) {
+          this.ignoreBackdropClick = false
+          return
+        }
+        if (e.target !== e.currentTarget) return
+        this.options.backdrop == 'static'
+          ? this.$element[0].focus()
+          : this.hide()
+      }, this))
+
+      if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
+
+      this.$backdrop.addClass('in')
+
+      if (!callback) return
+
+      doAnimate ?
+        this.$backdrop
+          .one('bsTransitionEnd', callback)
+          .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
+        callback()
+
+    } else if (!this.isShown && this.$backdrop) {
+      this.$backdrop.removeClass('in')
+
+      var callbackRemove = function () {
+        that.removeBackdrop()
+        callback && callback()
+      }
+      $.support.transition && this.$element.hasClass('fade') ?
+        this.$backdrop
+          .one('bsTransitionEnd', callbackRemove)
+          .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
+        callbackRemove()
+
+    } else if (callback) {
+      callback()
+    }
+  }
+
+  // these following methods are used to handle overflowing modals
+
+  Modal.prototype.handleUpdate = function () {
+    this.adjustDialog()
+  }
+
+  Modal.prototype.adjustDialog = function () {
+    var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
+
+    this.$element.css({
+      paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
+      paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
+    })
+  }
+
+  Modal.prototype.resetAdjustments = function () {
+    this.$element.css({
+      paddingLeft: '',
+      paddingRight: ''
+    })
+  }
+
+  Modal.prototype.checkScrollbar = function () {
+    var fullWindowWidth = window.innerWidth
+    if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
+      var documentElementRect = document.documentElement.getBoundingClientRect()
+      fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left)
+    }
+    this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth
+    this.scrollbarWidth = this.measureScrollbar()
+  }
+
+  Modal.prototype.setScrollbar = function () {
+    var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
+    this.originalBodyPad = document.body.style.paddingRight || ''
+    var scrollbarWidth = this.scrollbarWidth
+    if (this.bodyIsOverflowing) {
+      this.$body.css('padding-right', bodyPad + scrollbarWidth)
+      $(this.fixedContent).each(function (index, element) {
+        var actualPadding = element.style.paddingRight
+        var calculatedPadding = $(element).css('padding-right')
+        $(element)
+          .data('padding-right', actualPadding)
+          .css('padding-right', parseFloat(calculatedPadding) + scrollbarWidth + 'px')
+      })
+    }
+  }
+
+  Modal.prototype.resetScrollbar = function () {
+    this.$body.css('padding-right', this.originalBodyPad)
+    $(this.fixedContent).each(function (index, element) {
+      var padding = $(element).data('padding-right')
+      $(element).removeData('padding-right')
+      element.style.paddingRight = padding ? padding : ''
+    })
+  }
+
+  Modal.prototype.measureScrollbar = function () { // thx walsh
+    var scrollDiv = document.createElement('div')
+    scrollDiv.className = 'modal-scrollbar-measure'
+    this.$body.append(scrollDiv)
+    var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
+    this.$body[0].removeChild(scrollDiv)
+    return scrollbarWidth
+  }
+
+
+  // MODAL PLUGIN DEFINITION
+  // =======================
+
+  function Plugin(option, _relatedTarget) {
+    return this.each(function () {
+      var $this = $(this)
+      var data = $this.data('bs.modal')
+      var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
+
+      if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
+      if (typeof option == 'string') data[option](_relatedTarget)
+      else if (options.show) data.show(_relatedTarget)
+    })
+  }
+
+  var old = $.fn.modal
+
+  $.fn.modal = Plugin
+  $.fn.modal.Constructor = Modal
+
+
+  // MODAL NO CONFLICT
+  // =================
+
+  $.fn.modal.noConflict = function () {
+    $.fn.modal = old
+    return this
+  }
+
+
+  // MODAL DATA-API
+  // ==============
+
+  $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
+    var $this = $(this)
+    var href = $this.attr('href')
+    var target = $this.attr('data-target') ||
+      (href && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
+
+    var $target = $(document).find(target)
+    var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
+
+    if ($this.is('a')) e.preventDefault()
+
+    $target.one('show.bs.modal', function (showEvent) {
+      if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
+      $target.one('hidden.bs.modal', function () {
+        $this.is(':visible') && $this.trigger('focus')
+      })
+    })
+    Plugin.call($target, option, this)
+  })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: tooltip.js v3.4.1
+ * https://getbootstrap.com/docs/3.4/javascript/#tooltip
+ * Inspired by the original jQuery.tipsy by Jason Frame
+ * ========================================================================
+ * Copyright 2011-2019 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
++function ($) {
+  'use strict';
+
+  var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn']
+
+  var uriAttrs = [
+    'background',
+    'cite',
+    'href',
+    'itemtype',
+    'longdesc',
+    'poster',
+    'src',
+    'xlink:href'
+  ]
+
+  var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i
+
+  var DefaultWhitelist = {
+    // Global attributes allowed on any supplied element below.
+    '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],
+    a: ['target', 'href', 'title', 'rel'],
+    area: [],
+    b: [],
+    br: [],
+    col: [],
+    code: [],
+    div: [],
+    em: [],
+    hr: [],
+    h1: [],
+    h2: [],
+    h3: [],
+    h4: [],
+    h5: [],
+    h6: [],
+    i: [],
+    img: ['src', 'alt', 'title', 'width', 'height'],
+    li: [],
+    ol: [],
+    p: [],
+    pre: [],
+    s: [],
+    small: [],
+    span: [],
+    sub: [],
+    sup: [],
+    strong: [],
+    u: [],
+    ul: []
+  }
+
+  /**
+   * A pattern that recognizes a commonly useful subset of URLs that are safe.
+   *
+   * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
+   */
+  var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi
+
+  /**
+   * A pattern that matches safe data URLs. Only matches image, video and audio types.
+   *
+   * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
+   */
+  var DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i
+
+  function allowedAttribute(attr, allowedAttributeList) {
+    var attrName = attr.nodeName.toLowerCase()
+
+    if ($.inArray(attrName, allowedAttributeList) !== -1) {
+      if ($.inArray(attrName, uriAttrs) !== -1) {
+        return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN))
+      }
+
+      return true
+    }
+
+    var regExp = $(allowedAttributeList).filter(function (index, value) {
+      return value instanceof RegExp
+    })
+
+    // Check if a regular expression validates the attribute.
+    for (var i = 0, l = regExp.length; i < l; i++) {
+      if (attrName.match(regExp[i])) {
+        return true
+      }
+    }
+
+    return false
+  }
+
+  function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {
+    if (unsafeHtml.length === 0) {
+      return unsafeHtml
+    }
+
+    if (sanitizeFn && typeof sanitizeFn === 'function') {
+      return sanitizeFn(unsafeHtml)
+    }
+
+    // IE 8 and below don't support createHTMLDocument
+    if (!document.implementation || !document.implementation.createHTMLDocument) {
+      return unsafeHtml
+    }
+
+    var createdDocument = document.implementation.createHTMLDocument('sanitization')
+    createdDocument.body.innerHTML = unsafeHtml
+
+    var whitelistKeys = $.map(whiteList, function (el, i) { return i })
+    var elements = $(createdDocument.body).find('*')
+
+    for (var i = 0, len = elements.length; i < len; i++) {
+      var el = elements[i]
+      var elName = el.nodeName.toLowerCase()
+
+      if ($.inArray(elName, whitelistKeys) === -1) {
+        el.parentNode.removeChild(el)
+
+        continue
+      }
+
+      var attributeList = $.map(el.attributes, function (el) { return el })
+      var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || [])
+
+      for (var j = 0, len2 = attributeList.length; j < len2; j++) {
+        if (!allowedAttribute(attributeList[j], whitelistedAttributes)) {
+          el.removeAttribute(attributeList[j].nodeName)
+        }
+      }
+    }
+
+    return createdDocument.body.innerHTML
+  }
+
+  // TOOLTIP PUBLIC CLASS DEFINITION
+  // ===============================
+
+  var Tooltip = function (element, options) {
+    this.type       = null
+    this.options    = null
+    this.enabled    = null
+    this.timeout    = null
+    this.hoverState = null
+    this.$element   = null
+    this.inState    = null
+
+    this.init('tooltip', element, options)
+  }
+
+  Tooltip.VERSION  = '3.4.1'
+
+  Tooltip.TRANSITION_DURATION = 150
+
+  Tooltip.DEFAULTS = {
+    animation: true,
+    placement: 'top',
+    selector: false,
+    template: '',
+    trigger: 'hover focus',
+    title: '',
+    delay: 0,
+    html: false,
+    container: false,
+    viewport: {
+      selector: 'body',
+      padding: 0
+    },
+    sanitize : true,
+    sanitizeFn : null,
+    whiteList : DefaultWhitelist
+  }
+
+  Tooltip.prototype.init = function (type, element, options) {
+    this.enabled   = true
+    this.type      = type
+    this.$element  = $(element)
+    this.options   = this.getOptions(options)
+    this.$viewport = this.options.viewport && $(document).find($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
+    this.inState   = { click: false, hover: false, focus: false }
+
+    if (this.$element[0] instanceof document.constructor && !this.options.selector) {
+      throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
+    }
+
+    var triggers = this.options.trigger.split(' ')
+
+    for (var i = triggers.length; i--;) {
+      var trigger = triggers[i]
+
+      if (trigger == 'click') {
+        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
+      } else if (trigger != 'manual') {
+        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
+        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
+
+        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
+        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
+      }
+    }
+
+    this.options.selector ?
+      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
+      this.fixTitle()
+  }
+
+  Tooltip.prototype.getDefaults = function () {
+    return Tooltip.DEFAULTS
+  }
+
+  Tooltip.prototype.getOptions = function (options) {
+    var dataAttributes = this.$element.data()
+
+    for (var dataAttr in dataAttributes) {
+      if (dataAttributes.hasOwnProperty(dataAttr) && $.inArray(dataAttr, DISALLOWED_ATTRIBUTES) !== -1) {
+        delete dataAttributes[dataAttr]
+      }
+    }
+
+    options = $.extend({}, this.getDefaults(), dataAttributes, options)
+
+    if (options.delay && typeof options.delay == 'number') {
+      options.delay = {
+        show: options.delay,
+        hide: options.delay
+      }
+    }
+
+    if (options.sanitize) {
+      options.template = sanitizeHtml(options.template, options.whiteList, options.sanitizeFn)
+    }
+
+    return options
+  }
+
+  Tooltip.prototype.getDelegateOptions = function () {
+    var options  = {}
+    var defaults = this.getDefaults()
+
+    this._options && $.each(this._options, function (key, value) {
+      if (defaults[key] != value) options[key] = value
+    })
+
+    return options
+  }
+
+  Tooltip.prototype.enter = function (obj) {
+    var self = obj instanceof this.constructor ?
+      obj : $(obj.currentTarget).data('bs.' + this.type)
+
+    if (!self) {
+      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
+      $(obj.currentTarget).data('bs.' + this.type, self)
+    }
+
+    if (obj instanceof $.Event) {
+      self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
+    }
+
+    if (self.tip().hasClass('in') || self.hoverState == 'in') {
+      self.hoverState = 'in'
+      return
+    }
+
+    clearTimeout(self.timeout)
+
+    self.hoverState = 'in'
+
+    if (!self.options.delay || !self.options.delay.show) return self.show()
+
+    self.timeout = setTimeout(function () {
+      if (self.hoverState == 'in') self.show()
+    }, self.options.delay.show)
+  }
+
+  Tooltip.prototype.isInStateTrue = function () {
+    for (var key in this.inState) {
+      if (this.inState[key]) return true
+    }
+
+    return false
+  }
+
+  Tooltip.prototype.leave = function (obj) {
+    var self = obj instanceof this.constructor ?
+      obj : $(obj.currentTarget).data('bs.' + this.type)
+
+    if (!self) {
+      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
+      $(obj.currentTarget).data('bs.' + this.type, self)
+    }
+
+    if (obj instanceof $.Event) {
+      self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
+    }
+
+    if (self.isInStateTrue()) return
+
+    clearTimeout(self.timeout)
+
+    self.hoverState = 'out'
+
+    if (!self.options.delay || !self.options.delay.hide) return self.hide()
+
+    self.timeout = setTimeout(function () {
+      if (self.hoverState == 'out') self.hide()
+    }, self.options.delay.hide)
+  }
+
+  Tooltip.prototype.show = function () {
+    var e = $.Event('show.bs.' + this.type)
+
+    if (this.hasContent() && this.enabled) {
+      this.$element.trigger(e)
+
+      var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
+      if (e.isDefaultPrevented() || !inDom) return
+      var that = this
+
+      var $tip = this.tip()
+
+      var tipId = this.getUID(this.type)
+
+      this.setContent()
+      $tip.attr('id', tipId)
+      this.$element.attr('aria-describedby', tipId)
+
+      if (this.options.animation) $tip.addClass('fade')
+
+      var placement = typeof this.options.placement == 'function' ?
+        this.options.placement.call(this, $tip[0], this.$element[0]) :
+        this.options.placement
+
+      var autoToken = /\s?auto?\s?/i
+      var autoPlace = autoToken.test(placement)
+      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
+
+      $tip
+        .detach()
+        .css({ top: 0, left: 0, display: 'block' })
+        .addClass(placement)
+        .data('bs.' + this.type, this)
+
+      this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element)
+      this.$element.trigger('inserted.bs.' + this.type)
+
+      var pos          = this.getPosition()
+      var actualWidth  = $tip[0].offsetWidth
+      var actualHeight = $tip[0].offsetHeight
+
+      if (autoPlace) {
+        var orgPlacement = placement
+        var viewportDim = this.getPosition(this.$viewport)
+
+        placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top'    :
+                    placement == 'top'    && pos.top    - actualHeight < viewportDim.top    ? 'bottom' :
+                    placement == 'right'  && pos.right  + actualWidth  > viewportDim.width  ? 'left'   :
+                    placement == 'left'   && pos.left   - actualWidth  < viewportDim.left   ? 'right'  :
+                    placement
+
+        $tip
+          .removeClass(orgPlacement)
+          .addClass(placement)
+      }
+
+      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
+
+      this.applyPlacement(calculatedOffset, placement)
+
+      var complete = function () {
+        var prevHoverState = that.hoverState
+        that.$element.trigger('shown.bs.' + that.type)
+        that.hoverState = null
+
+        if (prevHoverState == 'out') that.leave(that)
+      }
+
+      $.support.transition && this.$tip.hasClass('fade') ?
+        $tip
+          .one('bsTransitionEnd', complete)
+          .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
+        complete()
+    }
+  }
+
+  Tooltip.prototype.applyPlacement = function (offset, placement) {
+    var $tip   = this.tip()
+    var width  = $tip[0].offsetWidth
+    var height = $tip[0].offsetHeight
+
+    // manually read margins because getBoundingClientRect includes difference
+    var marginTop = parseInt($tip.css('margin-top'), 10)
+    var marginLeft = parseInt($tip.css('margin-left'), 10)
+
+    // we must check for NaN for ie 8/9
+    if (isNaN(marginTop))  marginTop  = 0
+    if (isNaN(marginLeft)) marginLeft = 0
+
+    offset.top  += marginTop
+    offset.left += marginLeft
+
+    // $.fn.offset doesn't round pixel values
+    // so we use setOffset directly with our own function B-0
+    $.offset.setOffset($tip[0], $.extend({
+      using: function (props) {
+        $tip.css({
+          top: Math.round(props.top),
+          left: Math.round(props.left)
+        })
+      }
+    }, offset), 0)
+
+    $tip.addClass('in')
+
+    // check to see if placing tip in new offset caused the tip to resize itself
+    var actualWidth  = $tip[0].offsetWidth
+    var actualHeight = $tip[0].offsetHeight
+
+    if (placement == 'top' && actualHeight != height) {
+      offset.top = offset.top + height - actualHeight
+    }
+
+    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
+
+    if (delta.left) offset.left += delta.left
+    else offset.top += delta.top
+
+    var isVertical          = /top|bottom/.test(placement)
+    var arrowDelta          = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
+    var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
+
+    $tip.offset(offset)
+    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
+  }
+
+  Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
+    this.arrow()
+      .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
+      .css(isVertical ? 'top' : 'left', '')
+  }
+
+  Tooltip.prototype.setContent = function () {
+    var $tip  = this.tip()
+    var title = this.getTitle()
+
+    if (this.options.html) {
+      if (this.options.sanitize) {
+        title = sanitizeHtml(title, this.options.whiteList, this.options.sanitizeFn)
+      }
+
+      $tip.find('.tooltip-inner').html(title)
+    } else {
+      $tip.find('.tooltip-inner').text(title)
+    }
+
+    $tip.removeClass('fade in top bottom left right')
+  }
+
+  Tooltip.prototype.hide = function (callback) {
+    var that = this
+    var $tip = $(this.$tip)
+    var e    = $.Event('hide.bs.' + this.type)
+
+    function complete() {
+      if (that.hoverState != 'in') $tip.detach()
+      if (that.$element) { // TODO: Check whether guarding this code with this `if` is really necessary.
+        that.$element
+          .removeAttr('aria-describedby')
+          .trigger('hidden.bs.' + that.type)
+      }
+      callback && callback()
+    }
+
+    this.$element.trigger(e)
+
+    if (e.isDefaultPrevented()) return
+
+    $tip.removeClass('in')
+
+    $.support.transition && $tip.hasClass('fade') ?
+      $tip
+        .one('bsTransitionEnd', complete)
+        .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
+      complete()
+
+    this.hoverState = null
+
+    return this
+  }
+
+  Tooltip.prototype.fixTitle = function () {
+    var $e = this.$element
+    if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {
+      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
+    }
+  }
+
+  Tooltip.prototype.hasContent = function () {
+    return this.getTitle()
+  }
+
+  Tooltip.prototype.getPosition = function ($element) {
+    $element   = $element || this.$element
+
+    var el     = $element[0]
+    var isBody = el.tagName == 'BODY'
+
+    var elRect    = el.getBoundingClientRect()
+    if (elRect.width == null) {
+      // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
+      elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
+    }
+    var isSvg = window.SVGElement && el instanceof window.SVGElement
+    // Avoid using $.offset() on SVGs since it gives incorrect results in jQuery 3.
+    // See https://github.com/twbs/bootstrap/issues/20280
+    var elOffset  = isBody ? { top: 0, left: 0 } : (isSvg ? null : $element.offset())
+    var scroll    = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
+    var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
+
+    return $.extend({}, elRect, scroll, outerDims, elOffset)
+  }
+
+  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
+    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2 } :
+           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
+           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
+        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
+
+  }
+
+  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
+    var delta = { top: 0, left: 0 }
+    if (!this.$viewport) return delta
+
+    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
+    var viewportDimensions = this.getPosition(this.$viewport)
+
+    if (/right|left/.test(placement)) {
+      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
+      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
+      if (topEdgeOffset < viewportDimensions.top) { // top overflow
+        delta.top = viewportDimensions.top - topEdgeOffset
+      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
+        delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
+      }
+    } else {
+      var leftEdgeOffset  = pos.left - viewportPadding
+      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
+      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
+        delta.left = viewportDimensions.left - leftEdgeOffset
+      } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
+        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
+      }
+    }
+
+    return delta
+  }
+
+  Tooltip.prototype.getTitle = function () {
+    var title
+    var $e = this.$element
+    var o  = this.options
+
+    title = $e.attr('data-original-title')
+      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
+
+    return title
+  }
+
+  Tooltip.prototype.getUID = function (prefix) {
+    do prefix += ~~(Math.random() * 1000000)
+    while (document.getElementById(prefix))
+    return prefix
+  }
+
+  Tooltip.prototype.tip = function () {
+    if (!this.$tip) {
+      this.$tip = $(this.options.template)
+      if (this.$tip.length != 1) {
+        throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
+      }
+    }
+    return this.$tip
+  }
+
+  Tooltip.prototype.arrow = function () {
+    return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
+  }
+
+  Tooltip.prototype.enable = function () {
+    this.enabled = true
+  }
+
+  Tooltip.prototype.disable = function () {
+    this.enabled = false
+  }
+
+  Tooltip.prototype.toggleEnabled = function () {
+    this.enabled = !this.enabled
+  }
+
+  Tooltip.prototype.toggle = function (e) {
+    var self = this
+    if (e) {
+      self = $(e.currentTarget).data('bs.' + this.type)
+      if (!self) {
+        self = new this.constructor(e.currentTarget, this.getDelegateOptions())
+        $(e.currentTarget).data('bs.' + this.type, self)
+      }
+    }
+
+    if (e) {
+      self.inState.click = !self.inState.click
+      if (self.isInStateTrue()) self.enter(self)
+      else self.leave(self)
+    } else {
+      self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
+    }
+  }
+
+  Tooltip.prototype.destroy = function () {
+    var that = this
+    clearTimeout(this.timeout)
+    this.hide(function () {
+      that.$element.off('.' + that.type).removeData('bs.' + that.type)
+      if (that.$tip) {
+        that.$tip.detach()
+      }
+      that.$tip = null
+      that.$arrow = null
+      that.$viewport = null
+      that.$element = null
+    })
+  }
+
+  Tooltip.prototype.sanitizeHtml = function (unsafeHtml) {
+    return sanitizeHtml(unsafeHtml, this.options.whiteList, this.options.sanitizeFn)
+  }
+
+  // TOOLTIP PLUGIN DEFINITION
+  // =========================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this   = $(this)
+      var data    = $this.data('bs.tooltip')
+      var options = typeof option == 'object' && option
+
+      if (!data && /destroy|hide/.test(option)) return
+      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  var old = $.fn.tooltip
+
+  $.fn.tooltip             = Plugin
+  $.fn.tooltip.Constructor = Tooltip
+
+
+  // TOOLTIP NO CONFLICT
+  // ===================
+
+  $.fn.tooltip.noConflict = function () {
+    $.fn.tooltip = old
+    return this
+  }
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: popover.js v3.4.1
+ * https://getbootstrap.com/docs/3.4/javascript/#popovers
+ * ========================================================================
+ * Copyright 2011-2019 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // POPOVER PUBLIC CLASS DEFINITION
+  // ===============================
+
+  var Popover = function (element, options) {
+    this.init('popover', element, options)
+  }
+
+  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
+
+  Popover.VERSION  = '3.4.1'
+
+  Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
+    placement: 'right',
+    trigger: 'click',
+    content: '',
+    template: ''
+  })
+
+
+  // NOTE: POPOVER EXTENDS tooltip.js
+  // ================================
+
+  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
+
+  Popover.prototype.constructor = Popover
+
+  Popover.prototype.getDefaults = function () {
+    return Popover.DEFAULTS
+  }
+
+  Popover.prototype.setContent = function () {
+    var $tip    = this.tip()
+    var title   = this.getTitle()
+    var content = this.getContent()
+
+    if (this.options.html) {
+      var typeContent = typeof content
+
+      if (this.options.sanitize) {
+        title = this.sanitizeHtml(title)
+
+        if (typeContent === 'string') {
+          content = this.sanitizeHtml(content)
+        }
+      }
+
+      $tip.find('.popover-title').html(title)
+      $tip.find('.popover-content').children().detach().end()[
+        typeContent === 'string' ? 'html' : 'append'
+      ](content)
+    } else {
+      $tip.find('.popover-title').text(title)
+      $tip.find('.popover-content').children().detach().end().text(content)
+    }
+
+    $tip.removeClass('fade top bottom left right in')
+
+    // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
+    // this manually by checking the contents.
+    if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
+  }
+
+  Popover.prototype.hasContent = function () {
+    return this.getTitle() || this.getContent()
+  }
+
+  Popover.prototype.getContent = function () {
+    var $e = this.$element
+    var o  = this.options
+
+    return $e.attr('data-content')
+      || (typeof o.content == 'function' ?
+        o.content.call($e[0]) :
+        o.content)
+  }
+
+  Popover.prototype.arrow = function () {
+    return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
+  }
+
+
+  // POPOVER PLUGIN DEFINITION
+  // =========================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this   = $(this)
+      var data    = $this.data('bs.popover')
+      var options = typeof option == 'object' && option
+
+      if (!data && /destroy|hide/.test(option)) return
+      if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  var old = $.fn.popover
+
+  $.fn.popover             = Plugin
+  $.fn.popover.Constructor = Popover
+
+
+  // POPOVER NO CONFLICT
+  // ===================
+
+  $.fn.popover.noConflict = function () {
+    $.fn.popover = old
+    return this
+  }
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: scrollspy.js v3.4.1
+ * https://getbootstrap.com/docs/3.4/javascript/#scrollspy
+ * ========================================================================
+ * Copyright 2011-2019 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // SCROLLSPY CLASS DEFINITION
+  // ==========================
+
+  function ScrollSpy(element, options) {
+    this.$body          = $(document.body)
+    this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
+    this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)
+    this.selector       = (this.options.target || '') + ' .nav li > a'
+    this.offsets        = []
+    this.targets        = []
+    this.activeTarget   = null
+    this.scrollHeight   = 0
+
+    this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
+    this.refresh()
+    this.process()
+  }
+
+  ScrollSpy.VERSION  = '3.4.1'
+
+  ScrollSpy.DEFAULTS = {
+    offset: 10
+  }
+
+  ScrollSpy.prototype.getScrollHeight = function () {
+    return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
+  }
+
+  ScrollSpy.prototype.refresh = function () {
+    var that          = this
+    var offsetMethod  = 'offset'
+    var offsetBase    = 0
+
+    this.offsets      = []
+    this.targets      = []
+    this.scrollHeight = this.getScrollHeight()
+
+    if (!$.isWindow(this.$scrollElement[0])) {
+      offsetMethod = 'position'
+      offsetBase   = this.$scrollElement.scrollTop()
+    }
+
+    this.$body
+      .find(this.selector)
+      .map(function () {
+        var $el   = $(this)
+        var href  = $el.data('target') || $el.attr('href')
+        var $href = /^#./.test(href) && $(href)
+
+        return ($href
+          && $href.length
+          && $href.is(':visible')
+          && [[$href[offsetMethod]().top + offsetBase, href]]) || null
+      })
+      .sort(function (a, b) { return a[0] - b[0] })
+      .each(function () {
+        that.offsets.push(this[0])
+        that.targets.push(this[1])
+      })
+  }
+
+  ScrollSpy.prototype.process = function () {
+    var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset
+    var scrollHeight = this.getScrollHeight()
+    var maxScroll    = this.options.offset + scrollHeight - this.$scrollElement.height()
+    var offsets      = this.offsets
+    var targets      = this.targets
+    var activeTarget = this.activeTarget
+    var i
+
+    if (this.scrollHeight != scrollHeight) {
+      this.refresh()
+    }
+
+    if (scrollTop >= maxScroll) {
+      return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
+    }
+
+    if (activeTarget && scrollTop < offsets[0]) {
+      this.activeTarget = null
+      return this.clear()
+    }
+
+    for (i = offsets.length; i--;) {
+      activeTarget != targets[i]
+        && scrollTop >= offsets[i]
+        && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
+        && this.activate(targets[i])
+    }
+  }
+
+  ScrollSpy.prototype.activate = function (target) {
+    this.activeTarget = target
+
+    this.clear()
+
+    var selector = this.selector +
+      '[data-target="' + target + '"],' +
+      this.selector + '[href="' + target + '"]'
+
+    var active = $(selector)
+      .parents('li')
+      .addClass('active')
+
+    if (active.parent('.dropdown-menu').length) {
+      active = active
+        .closest('li.dropdown')
+        .addClass('active')
+    }
+
+    active.trigger('activate.bs.scrollspy')
+  }
+
+  ScrollSpy.prototype.clear = function () {
+    $(this.selector)
+      .parentsUntil(this.options.target, '.active')
+      .removeClass('active')
+  }
+
+
+  // SCROLLSPY PLUGIN DEFINITION
+  // ===========================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this   = $(this)
+      var data    = $this.data('bs.scrollspy')
+      var options = typeof option == 'object' && option
+
+      if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  var old = $.fn.scrollspy
+
+  $.fn.scrollspy             = Plugin
+  $.fn.scrollspy.Constructor = ScrollSpy
+
+
+  // SCROLLSPY NO CONFLICT
+  // =====================
+
+  $.fn.scrollspy.noConflict = function () {
+    $.fn.scrollspy = old
+    return this
+  }
+
+
+  // SCROLLSPY DATA-API
+  // ==================
+
+  $(window).on('load.bs.scrollspy.data-api', function () {
+    $('[data-spy="scroll"]').each(function () {
+      var $spy = $(this)
+      Plugin.call($spy, $spy.data())
+    })
+  })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: tab.js v3.4.1
+ * https://getbootstrap.com/docs/3.4/javascript/#tabs
+ * ========================================================================
+ * Copyright 2011-2019 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // TAB CLASS DEFINITION
+  // ====================
+
+  var Tab = function (element) {
+    // jscs:disable requireDollarBeforejQueryAssignment
+    this.element = $(element)
+    // jscs:enable requireDollarBeforejQueryAssignment
+  }
+
+  Tab.VERSION = '3.4.1'
+
+  Tab.TRANSITION_DURATION = 150
+
+  Tab.prototype.show = function () {
+    var $this    = this.element
+    var $ul      = $this.closest('ul:not(.dropdown-menu)')
+    var selector = $this.data('target')
+
+    if (!selector) {
+      selector = $this.attr('href')
+      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
+    }
+
+    if ($this.parent('li').hasClass('active')) return
+
+    var $previous = $ul.find('.active:last a')
+    var hideEvent = $.Event('hide.bs.tab', {
+      relatedTarget: $this[0]
+    })
+    var showEvent = $.Event('show.bs.tab', {
+      relatedTarget: $previous[0]
+    })
+
+    $previous.trigger(hideEvent)
+    $this.trigger(showEvent)
+
+    if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
+
+    var $target = $(document).find(selector)
+
+    this.activate($this.closest('li'), $ul)
+    this.activate($target, $target.parent(), function () {
+      $previous.trigger({
+        type: 'hidden.bs.tab',
+        relatedTarget: $this[0]
+      })
+      $this.trigger({
+        type: 'shown.bs.tab',
+        relatedTarget: $previous[0]
+      })
+    })
+  }
+
+  Tab.prototype.activate = function (element, container, callback) {
+    var $active    = container.find('> .active')
+    var transition = callback
+      && $.support.transition
+      && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)
+
+    function next() {
+      $active
+        .removeClass('active')
+        .find('> .dropdown-menu > .active')
+        .removeClass('active')
+        .end()
+        .find('[data-toggle="tab"]')
+        .attr('aria-expanded', false)
+
+      element
+        .addClass('active')
+        .find('[data-toggle="tab"]')
+        .attr('aria-expanded', true)
+
+      if (transition) {
+        element[0].offsetWidth // reflow for transition
+        element.addClass('in')
+      } else {
+        element.removeClass('fade')
+      }
+
+      if (element.parent('.dropdown-menu').length) {
+        element
+          .closest('li.dropdown')
+          .addClass('active')
+          .end()
+          .find('[data-toggle="tab"]')
+          .attr('aria-expanded', true)
+      }
+
+      callback && callback()
+    }
+
+    $active.length && transition ?
+      $active
+        .one('bsTransitionEnd', next)
+        .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
+      next()
+
+    $active.removeClass('in')
+  }
+
+
+  // TAB PLUGIN DEFINITION
+  // =====================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this = $(this)
+      var data  = $this.data('bs.tab')
+
+      if (!data) $this.data('bs.tab', (data = new Tab(this)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  var old = $.fn.tab
+
+  $.fn.tab             = Plugin
+  $.fn.tab.Constructor = Tab
+
+
+  // TAB NO CONFLICT
+  // ===============
+
+  $.fn.tab.noConflict = function () {
+    $.fn.tab = old
+    return this
+  }
+
+
+  // TAB DATA-API
+  // ============
+
+  var clickHandler = function (e) {
+    e.preventDefault()
+    Plugin.call($(this), 'show')
+  }
+
+  $(document)
+    .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
+    .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: affix.js v3.4.1
+ * https://getbootstrap.com/docs/3.4/javascript/#affix
+ * ========================================================================
+ * Copyright 2011-2019 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+  'use strict';
+
+  // AFFIX CLASS DEFINITION
+  // ======================
+
+  var Affix = function (element, options) {
+    this.options = $.extend({}, Affix.DEFAULTS, options)
+
+    var target = this.options.target === Affix.DEFAULTS.target ? $(this.options.target) : $(document).find(this.options.target)
+
+    this.$target = target
+      .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
+      .on('click.bs.affix.data-api',  $.proxy(this.checkPositionWithEventLoop, this))
+
+    this.$element     = $(element)
+    this.affixed      = null
+    this.unpin        = null
+    this.pinnedOffset = null
+
+    this.checkPosition()
+  }
+
+  Affix.VERSION  = '3.4.1'
+
+  Affix.RESET    = 'affix affix-top affix-bottom'
+
+  Affix.DEFAULTS = {
+    offset: 0,
+    target: window
+  }
+
+  Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
+    var scrollTop    = this.$target.scrollTop()
+    var position     = this.$element.offset()
+    var targetHeight = this.$target.height()
+
+    if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
+
+    if (this.affixed == 'bottom') {
+      if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
+      return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
+    }
+
+    var initializing   = this.affixed == null
+    var colliderTop    = initializing ? scrollTop : position.top
+    var colliderHeight = initializing ? targetHeight : height
+
+    if (offsetTop != null && scrollTop <= offsetTop) return 'top'
+    if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
+
+    return false
+  }
+
+  Affix.prototype.getPinnedOffset = function () {
+    if (this.pinnedOffset) return this.pinnedOffset
+    this.$element.removeClass(Affix.RESET).addClass('affix')
+    var scrollTop = this.$target.scrollTop()
+    var position  = this.$element.offset()
+    return (this.pinnedOffset = position.top - scrollTop)
+  }
+
+  Affix.prototype.checkPositionWithEventLoop = function () {
+    setTimeout($.proxy(this.checkPosition, this), 1)
+  }
+
+  Affix.prototype.checkPosition = function () {
+    if (!this.$element.is(':visible')) return
+
+    var height       = this.$element.height()
+    var offset       = this.options.offset
+    var offsetTop    = offset.top
+    var offsetBottom = offset.bottom
+    var scrollHeight = Math.max($(document).height(), $(document.body).height())
+
+    if (typeof offset != 'object')         offsetBottom = offsetTop = offset
+    if (typeof offsetTop == 'function')    offsetTop    = offset.top(this.$element)
+    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
+
+    var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
+
+    if (this.affixed != affix) {
+      if (this.unpin != null) this.$element.css('top', '')
+
+      var affixType = 'affix' + (affix ? '-' + affix : '')
+      var e         = $.Event(affixType + '.bs.affix')
+
+      this.$element.trigger(e)
+
+      if (e.isDefaultPrevented()) return
+
+      this.affixed = affix
+      this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
+
+      this.$element
+        .removeClass(Affix.RESET)
+        .addClass(affixType)
+        .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
+    }
+
+    if (affix == 'bottom') {
+      this.$element.offset({
+        top: scrollHeight - height - offsetBottom
+      })
+    }
+  }
+
+
+  // AFFIX PLUGIN DEFINITION
+  // =======================
+
+  function Plugin(option) {
+    return this.each(function () {
+      var $this   = $(this)
+      var data    = $this.data('bs.affix')
+      var options = typeof option == 'object' && option
+
+      if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  var old = $.fn.affix
+
+  $.fn.affix             = Plugin
+  $.fn.affix.Constructor = Affix
+
+
+  // AFFIX NO CONFLICT
+  // =================
+
+  $.fn.affix.noConflict = function () {
+    $.fn.affix = old
+    return this
+  }
+
+
+  // AFFIX DATA-API
+  // ==============
+
+  $(window).on('load', function () {
+    $('[data-spy="affix"]').each(function () {
+      var $spy = $(this)
+      var data = $spy.data()
+
+      data.offset = data.offset || {}
+
+      if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
+      if (data.offsetTop    != null) data.offset.top    = data.offsetTop
+
+      Plugin.call($spy, data)
+    })
+  })
+
+}(jQuery);
diff --git a/modules/cms/src/main/resources/static/modules/cmsfront/themes/js/bootstrap.min.js b/modules/cms/src/main/resources/static/modules/cmsfront/themes/js/bootstrap.min.js
new file mode 100644
index 00000000..eb0a8b41
--- /dev/null
+++ b/modules/cms/src/main/resources/static/modules/cmsfront/themes/js/bootstrap.min.js
@@ -0,0 +1,6 @@
+/*!
+ * Bootstrap v3.4.1 (https://getbootstrap.com/)
+ * Copyright 2011-2019 Twitter, Inc.
+ * Licensed under the MIT license
+ */
+if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");!function(t){"use strict";var e=jQuery.fn.jquery.split(" ")[0].split(".");if(e[0]<2&&e[1]<9||1==e[0]&&9==e[1]&&e[2]<1||3this.$items.length-1||t<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){e.to(t)}):i==t?this.pause().cycle():this.slide(idocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&t?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!t?this.scrollbarWidth:""})},s.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},s.prototype.checkScrollbar=function(){var t=window.innerWidth;if(!t){var e=document.documentElement.getBoundingClientRect();t=e.right-Math.abs(e.left)}this.bodyIsOverflowing=document.body.clientWidth
',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0},sanitize:!0,sanitizeFn:null,whiteList:t},m.prototype.init=function(t,e,i){if(this.enabled=!0,this.type=t,this.$element=g(e),this.options=this.getOptions(i),this.$viewport=this.options.viewport&&g(document).find(g.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var o=this.options.trigger.split(" "),n=o.length;n--;){var s=o[n];if("click"==s)this.$element.on("click."+this.type,this.options.selector,g.proxy(this.toggle,this));else if("manual"!=s){var a="hover"==s?"mouseenter":"focusin",r="hover"==s?"mouseleave":"focusout";this.$element.on(a+"."+this.type,this.options.selector,g.proxy(this.enter,this)),this.$element.on(r+"."+this.type,this.options.selector,g.proxy(this.leave,this))}}this.options.selector?this._options=g.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},m.prototype.getDefaults=function(){return m.DEFAULTS},m.prototype.getOptions=function(t){var e=this.$element.data();for(var i in e)e.hasOwnProperty(i)&&-1!==g.inArray(i,o)&&delete e[i];return(t=g.extend({},this.getDefaults(),e,t)).delay&&"number"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),t.sanitize&&(t.template=n(t.template,t.whiteList,t.sanitizeFn)),t},m.prototype.getDelegateOptions=function(){var i={},o=this.getDefaults();return this._options&&g.each(this._options,function(t,e){o[t]!=e&&(i[t]=e)}),i},m.prototype.enter=function(t){var e=t instanceof this.constructor?t:g(t.currentTarget).data("bs."+this.type);if(e||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e)),t instanceof g.Event&&(e.inState["focusin"==t.type?"focus":"hover"]=!0),e.tip().hasClass("in")||"in"==e.hoverState)e.hoverState="in";else{if(clearTimeout(e.timeout),e.hoverState="in",!e.options.delay||!e.options.delay.show)return e.show();e.timeout=setTimeout(function(){"in"==e.hoverState&&e.show()},e.options.delay.show)}},m.prototype.isInStateTrue=function(){for(var t in this.inState)if(this.inState[t])return!0;return!1},m.prototype.leave=function(t){var e=t instanceof this.constructor?t:g(t.currentTarget).data("bs."+this.type);if(e||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e)),t instanceof g.Event&&(e.inState["focusout"==t.type?"focus":"hover"]=!1),!e.isInStateTrue()){if(clearTimeout(e.timeout),e.hoverState="out",!e.options.delay||!e.options.delay.hide)return e.hide();e.timeout=setTimeout(function(){"out"==e.hoverState&&e.hide()},e.options.delay.hide)}},m.prototype.show=function(){var t=g.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(t);var e=g.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(t.isDefaultPrevented()||!e)return;var i=this,o=this.tip(),n=this.getUID(this.type);this.setContent(),o.attr("id",n),this.$element.attr("aria-describedby",n),this.options.animation&&o.addClass("fade");var s="function"==typeof this.options.placement?this.options.placement.call(this,o[0],this.$element[0]):this.options.placement,a=/\s?auto?\s?/i,r=a.test(s);r&&(s=s.replace(a,"")||"top"),o.detach().css({top:0,left:0,display:"block"}).addClass(s).data("bs."+this.type,this),this.options.container?o.appendTo(g(document).find(this.options.container)):o.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var l=this.getPosition(),h=o[0].offsetWidth,d=o[0].offsetHeight;if(r){var p=s,c=this.getPosition(this.$viewport);s="bottom"==s&&l.bottom+d>c.bottom?"top":"top"==s&&l.top-dc.width?"left":"left"==s&&l.left-ha.top+a.height&&(n.top=a.top+a.height-l)}else{var h=e.left-s,d=e.left+s+i;ha.right&&(n.left=a.left+a.width-d)}return n},m.prototype.getTitle=function(){var t=this.$element,e=this.options;return t.attr("data-original-title")||("function"==typeof e.title?e.title.call(t[0]):e.title)},m.prototype.getUID=function(t){for(;t+=~~(1e6*Math.random()),document.getElementById(t););return t},m.prototype.tip=function(){if(!this.$tip&&(this.$tip=g(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},m.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},m.prototype.enable=function(){this.enabled=!0},m.prototype.disable=function(){this.enabled=!1},m.prototype.toggleEnabled=function(){this.enabled=!this.enabled},m.prototype.toggle=function(t){var e=this;t&&((e=g(t.currentTarget).data("bs."+this.type))||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e))),t?(e.inState.click=!e.inState.click,e.isInStateTrue()?e.enter(e):e.leave(e)):e.tip().hasClass("in")?e.leave(e):e.enter(e)},m.prototype.destroy=function(){var t=this;clearTimeout(this.timeout),this.hide(function(){t.$element.off("."+t.type).removeData("bs."+t.type),t.$tip&&t.$tip.detach(),t.$tip=null,t.$arrow=null,t.$viewport=null,t.$element=null})},m.prototype.sanitizeHtml=function(t){return n(t,this.options.whiteList,this.options.sanitizeFn)};var e=g.fn.tooltip;g.fn.tooltip=function i(o){return this.each(function(){var t=g(this),e=t.data("bs.tooltip"),i="object"==typeof o&&o;!e&&/destroy|hide/.test(o)||(e||t.data("bs.tooltip",e=new m(this,i)),"string"==typeof o&&e[o]())})},g.fn.tooltip.Constructor=m,g.fn.tooltip.noConflict=function(){return g.fn.tooltip=e,this}}(jQuery),function(n){"use strict";var s=function(t,e){this.init("popover",t,e)};if(!n.fn.tooltip)throw new Error("Popover requires tooltip.js");s.VERSION="3.4.1",s.DEFAULTS=n.extend({},n.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),((s.prototype=n.extend({},n.fn.tooltip.Constructor.prototype)).constructor=s).prototype.getDefaults=function(){return s.DEFAULTS},s.prototype.setContent=function(){var t=this.tip(),e=this.getTitle(),i=this.getContent();if(this.options.html){var o=typeof i;this.options.sanitize&&(e=this.sanitizeHtml(e),"string"===o&&(i=this.sanitizeHtml(i))),t.find(".popover-title").html(e),t.find(".popover-content").children().detach().end()["string"===o?"html":"append"](i)}else t.find(".popover-title").text(e),t.find(".popover-content").children().detach().end().text(i);t.removeClass("fade top bottom left right in"),t.find(".popover-title").html()||t.find(".popover-title").hide()},s.prototype.hasContent=function(){return this.getTitle()||this.getContent()},s.prototype.getContent=function(){var t=this.$element,e=this.options;return t.attr("data-content")||("function"==typeof e.content?e.content.call(t[0]):e.content)},s.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var t=n.fn.popover;n.fn.popover=function e(o){return this.each(function(){var t=n(this),e=t.data("bs.popover"),i="object"==typeof o&&o;!e&&/destroy|hide/.test(o)||(e||t.data("bs.popover",e=new s(this,i)),"string"==typeof o&&e[o]())})},n.fn.popover.Constructor=s,n.fn.popover.noConflict=function(){return n.fn.popover=t,this}}(jQuery),function(s){"use strict";function n(t,e){this.$body=s(document.body),this.$scrollElement=s(t).is(document.body)?s(window):s(t),this.options=s.extend({},n.DEFAULTS,e),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",s.proxy(this.process,this)),this.refresh(),this.process()}function e(o){return this.each(function(){var t=s(this),e=t.data("bs.scrollspy"),i="object"==typeof o&&o;e||t.data("bs.scrollspy",e=new n(this,i)),"string"==typeof o&&e[o]()})}n.VERSION="3.4.1",n.DEFAULTS={offset:10},n.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},n.prototype.refresh=function(){var t=this,o="offset",n=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),s.isWindow(this.$scrollElement[0])||(o="position",n=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var t=s(this),e=t.data("target")||t.attr("href"),i=/^#./.test(e)&&s(e);return i&&i.length&&i.is(":visible")&&[[i[o]().top+n,e]]||null}).sort(function(t,e){return t[0]-e[0]}).each(function(){t.offsets.push(this[0]),t.targets.push(this[1])})},n.prototype.process=function(){var t,e=this.$scrollElement.scrollTop()+this.options.offset,i=this.getScrollHeight(),o=this.options.offset+i-this.$scrollElement.height(),n=this.offsets,s=this.targets,a=this.activeTarget;if(this.scrollHeight!=i&&this.refresh(),o<=e)return a!=(t=s[s.length-1])&&this.activate(t);if(a&&e=n[t]&&(n[t+1]===undefined||e .active"),n=i&&r.support.transition&&(o.length&&o.hasClass("fade")||!!e.find("> .fade").length);function s(){o.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),t.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),n?(t[0].offsetWidth,t.addClass("in")):t.removeClass("fade"),t.parent(".dropdown-menu").length&&t.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),i&&i()}o.length&&n?o.one("bsTransitionEnd",s).emulateTransitionEnd(a.TRANSITION_DURATION):s(),o.removeClass("in")};var t=r.fn.tab;r.fn.tab=e,r.fn.tab.Constructor=a,r.fn.tab.noConflict=function(){return r.fn.tab=t,this};var i=function(t){t.preventDefault(),e.call(r(this),"show")};r(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',i).on("click.bs.tab.data-api",'[data-toggle="pill"]',i)}(jQuery),function(l){"use strict";var h=function(t,e){this.options=l.extend({},h.DEFAULTS,e);var i=this.options.target===h.DEFAULTS.target?l(this.options.target):l(document).find(this.options.target);this.$target=i.on("scroll.bs.affix.data-api",l.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",l.proxy(this.checkPositionWithEventLoop,this)),this.$element=l(t),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};function i(o){return this.each(function(){var t=l(this),e=t.data("bs.affix"),i="object"==typeof o&&o;e||t.data("bs.affix",e=new h(this,i)),"string"==typeof o&&e[o]()})}h.VERSION="3.4.1",h.RESET="affix affix-top affix-bottom",h.DEFAULTS={offset:0,target:window},h.prototype.getState=function(t,e,i,o){var n=this.$target.scrollTop(),s=this.$element.offset(),a=this.$target.height();if(null!=i&&"top"==this.affixed)return n 50) + $('#home > .navbar').removeClass('navbar-transparent'); + else + $('#home > .navbar').addClass('navbar-transparent'); + }); + + $("a[href='#']").click(function(e) { + e.preventDefault(); + }); + + function cleanSource(html) { + html = html.replace(/×/g, "×") + .replace(/«/g, "«") + .replace(/»/g, "»") + .replace(/←/g, "←") + .replace(/→/g, "→"); + + var lines = html.split(/\n/); + + lines.shift(); + lines.splice(-1, 1); + + var indentSize = lines[0].length - lines[0].trim().length, + re = new RegExp(" {" + indentSize + "}"); + + lines = lines.map(function(line){ + if (line.match(re)) { + line = line.substring(indentSize); + } + + return line; + }); + + lines = lines.join("\n"); + + return lines; + } + +})(); diff --git a/modules/cms/src/main/resources/views/functions/abbr.html b/modules/cms/src/main/resources/views/functions/abbr.html new file mode 100644 index 00000000..c0aea683 --- /dev/null +++ b/modules/cms/src/main/resources/views/functions/abbr.html @@ -0,0 +1,4 @@ +<% +var title = para0, length = para1; +return @com.jeesite.common.lang.StringUtils.abbr(title, length); +%> \ No newline at end of file diff --git a/modules/cms/src/main/resources/views/functions/article.html b/modules/cms/src/main/resources/views/functions/article.html new file mode 100644 index 00000000..0a461503 --- /dev/null +++ b/modules/cms/src/main/resources/views/functions/article.html @@ -0,0 +1,4 @@ +<% +var articleId = para0; +return @com.jeesite.modules.cms.utils.CmsUtils.getArticle(articleId); +%> \ No newline at end of file diff --git a/modules/cms/src/main/resources/views/functions/articleList.html b/modules/cms/src/main/resources/views/functions/articleList.html new file mode 100644 index 00000000..b5f51a55 --- /dev/null +++ b/modules/cms/src/main/resources/views/functions/articleList.html @@ -0,0 +1,4 @@ +<% +var siteCode = para0, categoryCode = para1, number = para2, params = para3!; +return @com.jeesite.modules.cms.utils.CmsUtils.getArticleList(siteCode, categoryCode, number, params); +%> \ No newline at end of file diff --git a/modules/cms/src/main/resources/views/functions/category.html b/modules/cms/src/main/resources/views/functions/category.html new file mode 100644 index 00000000..a88b4c5e --- /dev/null +++ b/modules/cms/src/main/resources/views/functions/category.html @@ -0,0 +1,4 @@ +<% +var categoryCode = para0; +return @com.jeesite.modules.cms.utils.CmsUtils.getCategory(categoryCode); +%> \ No newline at end of file diff --git a/modules/cms/src/main/resources/views/functions/categoryList.html b/modules/cms/src/main/resources/views/functions/categoryList.html new file mode 100644 index 00000000..fde2d5a4 --- /dev/null +++ b/modules/cms/src/main/resources/views/functions/categoryList.html @@ -0,0 +1,4 @@ +<% +var siteCode = para0, parentCode = para1, number = para2, params = para3!; +return @com.jeesite.modules.cms.utils.CmsUtils.getCategoryList(siteCode, parentCode, number, params); +%> \ No newline at end of file diff --git a/modules/cms/src/main/resources/views/functions/site.html b/modules/cms/src/main/resources/views/functions/site.html new file mode 100644 index 00000000..3a0810d1 --- /dev/null +++ b/modules/cms/src/main/resources/views/functions/site.html @@ -0,0 +1,4 @@ +<% +var siteCode = para0!'main'; +return @com.jeesite.modules.cms.utils.CmsUtils.getSite(siteCode); +%> \ No newline at end of file diff --git a/modules/cms/src/main/resources/views/functions/siteList.html b/modules/cms/src/main/resources/views/functions/siteList.html new file mode 100644 index 00000000..433f9237 --- /dev/null +++ b/modules/cms/src/main/resources/views/functions/siteList.html @@ -0,0 +1,3 @@ +<% +return @com.jeesite.modules.cms.utils.CmsUtils.getSiteList(); +%> \ No newline at end of file diff --git a/modules/cms/src/main/resources/views/htmltags/cms/article.html b/modules/cms/src/main/resources/views/htmltags/cms/article.html new file mode 100644 index 00000000..3cd10f62 --- /dev/null +++ b/modules/cms/src/main/resources/views/htmltags/cms/article.html @@ -0,0 +1,10 @@ +<% + var p = { + // 标签参数 预留功能 + id: id!, // 文章的id + attribute:attribute! //文章的属性,反向获取文章 + + }; + + var article= @com.jeesite.modules.cms.utils.CmsUtils.getArticle("main"); +%> diff --git a/modules/cms/src/main/resources/views/htmltags/cms/articleList.html b/modules/cms/src/main/resources/views/htmltags/cms/articleList.html new file mode 100644 index 00000000..f62e9847 --- /dev/null +++ b/modules/cms/src/main/resources/views/htmltags/cms/articleList.html @@ -0,0 +1,14 @@ +<% + var p = { + // 标签参数 + path: path!, // 绑定form上model中属性的值 + class:class!, // 绑定textarea上的class属性的值 + rows:rows!, // 绑定textarea上的rows属性值 + cols:cols!, // 绑定textarea上的cols属性值 + value:value!, + maxlength:maxlength! + }; +%> + +${p.path}--${p.value} + diff --git a/modules/cms/src/main/resources/views/htmltags/cms/articleNext.html b/modules/cms/src/main/resources/views/htmltags/cms/articleNext.html new file mode 100644 index 00000000..f62e9847 --- /dev/null +++ b/modules/cms/src/main/resources/views/htmltags/cms/articleNext.html @@ -0,0 +1,14 @@ +<% + var p = { + // 标签参数 + path: path!, // 绑定form上model中属性的值 + class:class!, // 绑定textarea上的class属性的值 + rows:rows!, // 绑定textarea上的rows属性值 + cols:cols!, // 绑定textarea上的cols属性值 + value:value!, + maxlength:maxlength! + }; +%> + +${p.path}--${p.value} + diff --git a/modules/cms/src/main/resources/views/htmltags/cms/articlePosition.html b/modules/cms/src/main/resources/views/htmltags/cms/articlePosition.html new file mode 100644 index 00000000..f62e9847 --- /dev/null +++ b/modules/cms/src/main/resources/views/htmltags/cms/articlePosition.html @@ -0,0 +1,14 @@ +<% + var p = { + // 标签参数 + path: path!, // 绑定form上model中属性的值 + class:class!, // 绑定textarea上的class属性的值 + rows:rows!, // 绑定textarea上的rows属性值 + cols:cols!, // 绑定textarea上的cols属性值 + value:value!, + maxlength:maxlength! + }; +%> + +${p.path}--${p.value} + diff --git a/modules/cms/src/main/resources/views/htmltags/cms/articlePreNext.html b/modules/cms/src/main/resources/views/htmltags/cms/articlePreNext.html new file mode 100644 index 00000000..f62e9847 --- /dev/null +++ b/modules/cms/src/main/resources/views/htmltags/cms/articlePreNext.html @@ -0,0 +1,14 @@ +<% + var p = { + // 标签参数 + path: path!, // 绑定form上model中属性的值 + class:class!, // 绑定textarea上的class属性的值 + rows:rows!, // 绑定textarea上的rows属性值 + cols:cols!, // 绑定textarea上的cols属性值 + value:value!, + maxlength:maxlength! + }; +%> + +${p.path}--${p.value} + diff --git a/modules/cms/src/main/resources/views/htmltags/cms/channel.html b/modules/cms/src/main/resources/views/htmltags/cms/channel.html new file mode 100644 index 00000000..f62e9847 --- /dev/null +++ b/modules/cms/src/main/resources/views/htmltags/cms/channel.html @@ -0,0 +1,14 @@ +<% + var p = { + // 标签参数 + path: path!, // 绑定form上model中属性的值 + class:class!, // 绑定textarea上的class属性的值 + rows:rows!, // 绑定textarea上的rows属性值 + cols:cols!, // 绑定textarea上的cols属性值 + value:value!, + maxlength:maxlength! + }; +%> + +${p.path}--${p.value} + diff --git a/modules/cms/src/main/resources/views/htmltags/cms/channelArticleList.html b/modules/cms/src/main/resources/views/htmltags/cms/channelArticleList.html new file mode 100644 index 00000000..f62e9847 --- /dev/null +++ b/modules/cms/src/main/resources/views/htmltags/cms/channelArticleList.html @@ -0,0 +1,14 @@ +<% + var p = { + // 标签参数 + path: path!, // 绑定form上model中属性的值 + class:class!, // 绑定textarea上的class属性的值 + rows:rows!, // 绑定textarea上的rows属性值 + cols:cols!, // 绑定textarea上的cols属性值 + value:value!, + maxlength:maxlength! + }; +%> + +${p.path}--${p.value} + diff --git a/modules/cms/src/main/resources/views/htmltags/cms/channelImage.html b/modules/cms/src/main/resources/views/htmltags/cms/channelImage.html new file mode 100644 index 00000000..f62e9847 --- /dev/null +++ b/modules/cms/src/main/resources/views/htmltags/cms/channelImage.html @@ -0,0 +1,14 @@ +<% + var p = { + // 标签参数 + path: path!, // 绑定form上model中属性的值 + class:class!, // 绑定textarea上的class属性的值 + rows:rows!, // 绑定textarea上的rows属性值 + cols:cols!, // 绑定textarea上的cols属性值 + value:value!, + maxlength:maxlength! + }; +%> + +${p.path}--${p.value} + diff --git a/modules/cms/src/main/resources/views/htmltags/cms/channelImageList.html b/modules/cms/src/main/resources/views/htmltags/cms/channelImageList.html new file mode 100644 index 00000000..f62e9847 --- /dev/null +++ b/modules/cms/src/main/resources/views/htmltags/cms/channelImageList.html @@ -0,0 +1,14 @@ +<% + var p = { + // 标签参数 + path: path!, // 绑定form上model中属性的值 + class:class!, // 绑定textarea上的class属性的值 + rows:rows!, // 绑定textarea上的rows属性值 + cols:cols!, // 绑定textarea上的cols属性值 + value:value!, + maxlength:maxlength! + }; +%> + +${p.path}--${p.value} + diff --git a/modules/cms/src/main/resources/views/htmltags/cms/channelList.html b/modules/cms/src/main/resources/views/htmltags/cms/channelList.html new file mode 100644 index 00000000..f62e9847 --- /dev/null +++ b/modules/cms/src/main/resources/views/htmltags/cms/channelList.html @@ -0,0 +1,14 @@ +<% + var p = { + // 标签参数 + path: path!, // 绑定form上model中属性的值 + class:class!, // 绑定textarea上的class属性的值 + rows:rows!, // 绑定textarea上的rows属性值 + cols:cols!, // 绑定textarea上的cols属性值 + value:value!, + maxlength:maxlength! + }; +%> + +${p.path}--${p.value} + diff --git a/modules/cms/src/main/resources/views/modules/cms/articleForm.html b/modules/cms/src/main/resources/views/modules/cms/articleForm.html new file mode 100644 index 00000000..ac220919 --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cms/articleForm.html @@ -0,0 +1,252 @@ +<% layout('/layouts/default.html', {title: '文章管理', libs: ['validate','fileupload','ueditor']}){ %> + +
+
+
+
+ ${text(article.isNewRecord ? '新增文章' : '编辑文章')}(${@CmsUtils.getCurrentSite().getSiteName()}) +
+
+ +
+
+ <#form:form id="inputForm" model="${article}" action="${ctx}/cms/article/save" method="post" class="form-horizontal"> +
+
${text('基本信息')}
+ <#form:hidden path="id"/> + <#form:hidden path="wordCount"/> +
+
+
+ +
+ <#form:treeselect id="category" title="${text('所属栏目')}" + path="category.categoryCode" labelPath="category.categoryName" + url="${ctx}/cms/category/treeData?excludeCode=${article.category.categoryCode}" + class="required" allowClear="true" canSelectRoot="true" canSelectParent="true" /> +
+
+
+
+
+ +
+ <#form:radio path="source" dictType="cms_source" class="form-control required" /> +
+
+
+
+
+
+
+ +
+
+ <#form:input path="title" maxlength="255" class="form-control text-ruler required"/> + + + + + + <#form:input path="color" maxlength="50" class="form-control" style="width:80px;" placeholder="${text('标题颜色')}"/> + + +
+
+
+
+
+
+
+
+ +
+ <#form:input path="href" maxlength="1000" class="form-control"/> +
+
+
+
+
+
+
+
+ +
+
+ <#form:input path="weight" class="form-control width-90 digits" maxlength="10"/>   + <#form:checkbox id="weightTop" label="${text('置顶')}" value="${article.weight==9999 ?'1' : ''}" + class="form-control" style="vertical-align:middle;"/> +
+   +
+
+
+
+
+ +
+ <#form:input path="weightDate" readonly="true" maxlength="20" class="form-control laydate" + dataFormat="datetime" data-type="datetime" data-format="yyyy-MM-dd HH:mm"/> +
+
+
+
+
${text('详细信息')}
+
+
+
+ +
+ <#form:textarea path="description" maxlength="500" class="form-control"/> +
+
+
+
+
+
+
+ +
+ <#form:ueditor id="content" path="articleData.content" maxlength="10000" height="500" class="required" simpleToolbars="false" readonly="false" outline="false"/> +
+
+
+
+
${text('其他信息')}
+
+
+
+ +
+ <#form:fileupload id="uploadImage" bizKey="${article.id}" + bizType="article_image" returnPath="true" + filePathInputId="image" uploadType="image" readonly="false" + maxUploadNum="4" isMini="false" /> + <#form:input path="image" maxlength="1000" readonly="true" class="form-control" /> +
+
+
+
+
+
+
+ +
+ <#form:input path="keywords" maxlength="500" class="form-control"/> +
+
+
+
+
+ +
+
+ <#form:checkbox path="posidList" dictType="cms_post" class="form-control" /> +
+
+
+
+
+
+
+
+ +
+ <#form:select path="state" dictType="sys_status" blankOption="true" class="form-control" /> +
+
+
+
+
+ +
+ <#form:input path="createDate" readonly="true" maxlength="20" class="form-control Wdate" + dataFormat="datetime" onclick="WdatePicker({dateFmt:'yyyy-MM-dd HH:mm',isShowClear:false});"/> +
+
+
+
+
${text('高级信息')}
+
+
+
+ +
+ <#form:select path="customContentView" items="${contentViewList}" itemLabel="id" itemValue="id" blankOption="true" class="form-control " /> +
+
+
+
+
+
+
+ +
+ <#form:input path="viewConfig" maxlength="1000" placeholder="视图参数例如: {count:2, title_show:'yes'} 则在视图文件中的获取方法是:${'${'}viewConfig_count}、${'${'}viewConfig_titleShow}" class="form-control"/> +
+
+
+
+
+
+
+ +
+ <#form:textarea path="remarks" rows="4" maxlength="500" class="form-control"/> +
+
+
+
+ <#form:extend collapsed="true" /> + + +
+
+<% } %> + + \ No newline at end of file diff --git a/modules/cms/src/main/resources/views/modules/cms/articleList.html b/modules/cms/src/main/resources/views/modules/cms/articleList.html new file mode 100644 index 00000000..11f59ef8 --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cms/articleList.html @@ -0,0 +1,94 @@ +<% layout('/layouts/default.html', {title: '内容管理', libs: ['dataGrid']}){ %> +
+
+
+
+ ${text('内容管理')} +
+
+ ${text('访问网站')} + ${text('查询')} + <% if(hasPermi('cms:article:edit')){ %> + ${text('新增')} + <% } %> +
+
+
+ <#form:form id="searchForm" model="${article}" action="${ctx}/cms/article/listData" method="post" class="form-inline hide" + data-page-no="${parameter.pageNo}" data-page-size="${parameter.pageSize}" data-order-by="${parameter.orderBy}"> +
+ +
+ <#form:input id="categoryCode" path="category.categoryCode" maxlength="64" class="form-control width-120"/> +
+
+
+ +
+ <#form:input path="title" maxlength="255" class="form-control width-120"/> +
+
+
+ +
+ <#form:input path="keywords" maxlength="500" class="form-control width-120"/> +
+
+
+ +
+ <#form:select path="status" dictType="sys_search_status" blankOption="true" class="form-control"/> +
+
+
+ + +
+ +
+
+
+
+
+<% } %> + \ No newline at end of file diff --git a/modules/cms/src/main/resources/views/modules/cms/categoryForm.html b/modules/cms/src/main/resources/views/modules/cms/categoryForm.html new file mode 100644 index 00000000..f148b859 --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cms/categoryForm.html @@ -0,0 +1,278 @@ +<% layout('/layouts/default.html', {title: '栏目添加', libs: ['validate','fileupload']}){ %> +
+
+
+
+ ${text(category.isNewRecord ? '新增栏目' : '编辑栏目')} +
+
+ +
+
+ <#form:form id="inputForm" model="${category}" action="${ctx}/cms/category/save" method="post" class="form-horizontal"> +
+
+
+
+ +
+ <#form:treeselect id="parent" title="${text('上级栏目')}" + path="parent.id" labelPath="parent.categoryName" + url="${ctx}/cms/category/treeData?excludeCode=${category.id}" + class="" allowClear="true" canSelectRoot="true" + canSelectParent="true" /> +
+
+
+
+
+ +
+ <#form:select path="site.siteCode" items="${@CmsUtils.getSiteList()}" itemLabel="siteName" itemValue="siteCode" class="form-control required" /> +
+
+
+
+
+
+
+ +
+ <#form:hidden path="isNewRecord" /> + <#form:input path="categoryCode" maxlength="64" readonly="${!category.isNewRecord}" + class="form-control required abc" /> +
+
+
+
+
+ +
+ <#form:select path="moduleType" dictType="cms_module_type" blankOption="true" class="form-control required" /> +
+
+
+
+
+
+
+ +
+ <#form:input path="categoryName" maxlength="100" class="form-control required" /> +
+
+
+
+
+ +
+ <#form:input path="treeSort" class="form-control required digits" /> +
+
+
+
+
+
+
+ +
+ <#form:fileupload id="uploadImage" bizKey="${category.id}" bizType="category_image" + returnPath="true" filePathInputId="image" uploadType="image" readonly="false" + maxUploadNum="1" isMini="false" /> + <#form:input path="image" maxlength="255" class="form-control" /> +
+
+
+
+
+
+
+ +
+ <#form:input path="href" maxlength="255" placeholder="栏目超链接地址,优先级“高”" class="form-control" /> +
+
+
+
+
+ +
+ <#form:input path="target" maxlength="20" placeholder="栏目超链接打开的目标窗口,新窗口打开,请填写:“_blank”" class="form-control" /> +
+
+
+
+
+
+
+ +
+ <#form:input path="description" maxlength="500" placeholder="填写描述,有助于搜搜引擎优化" class="form-control" /> +
+
+
+
+
+ +
+ <#form:input path="keywords" maxlength="500" placeholder="填写关键词,有助于搜索引擎优化" class="form-control" /> +
+
+
+
+
+
${text('栏目配置')}
+
+
+
+ +
+ <#form:radio path="inMenu" dictType="sys_show_hide" class="form-control" /> +
+
+
+
+
+ +
+ <#form:radio path="isCanComment" dictType="sys_yes_no" class="form-control" /> +
+
+
+
+
+
+
+ +
+ <#form:radio path="inList" dictType="sys_show_hide" class="form-control" /> +
+
+
+
+
+ +
+ <#form:radio path="isNeedAudit" dictType="sys_yes_no" class="form-control" /> +
+
+
+
+
+
+
+ +
+ <#form:radio path="showModes" dictType="cms_show_modes" class="form-control" /> +
+
+
+
+
+
+
+ +
+ <#form:select path="customListView" items="${listViewList}" itemLabel="id" itemValue="id" blankOption="true" class="form-control " /> +
+
+
+
+
+ +
+ <#form:select path="customContentView" items="${contentViewList}" itemLabel="id" itemValue="id" blankOption="true" class="form-control " /> +
+
+
+
+
+
+
+ +
+ <#form:input path="viewConfig" maxlength="1000" class="form-control" + placeholder="视图参数例如: {count:2, title_show:'yes'} 则在视图文件中的获取方法是:${'${'}viewConfig_count}、${'${'}viewConfig_titleShow}" /> +
+
    +
  • 例如视图参数设置为:count:2,titleShow:'yes'则在视图文件中的获取方法是:\${viewConfig_count}、\${viewConfig_titleShow}。
  • +
  • 设置栏目的管理地址:若设置【adminUrl:false】表示无管理地址,在内容发布栏目列表中不显示该栏目;
  • +
  • 设置【adminUrl:'/cms/guestbook'】表示有管理地址,在内容发布栏目列表中点击该栏目链接到该地址。
  • + +
+
+
+
+
+
${text('其他信息')}
+
+
+
+ +
+ <#form:textarea path="remarks" rows="4" maxlength="500" class="form-control" /> +
+
+
+
+ <#form:extend collapsed="true" /> + + +
+
+<% } %> + \ No newline at end of file diff --git a/modules/cms/src/main/resources/views/modules/cms/categoryList.html b/modules/cms/src/main/resources/views/modules/cms/categoryList.html new file mode 100644 index 00000000..c6a95bb3 --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cms/categoryList.html @@ -0,0 +1,111 @@ +<% layout('/layouts/default.html', {title: '栏目管理', libs: ['dataGrid']}){ %> +
+
+
+
+ ${text('栏目管理')}( +
+ +
+
+ ${text('查询')} + ${text('刷新')} + ${text('展开')} + ${text('折叠')} <% + if(hasPermi('cms:category:edit')){ %> + ${text('新增')} + <% } %> +
+
+
+ <#form:form id="searchForm" model="${category}" action="${ctx}/cms/category/listData" method="post" class="form-inline hide" + data-page-no="${parameter.pageNo}" data-page-size="${parameter.pageSize}" data-order-by="${parameter.orderBy}"> + <#form:hidden path="site.siteCode" maxlength="64" class="form-control width-120" /> +
+ +
+ <#form:input path="categoryName" maxlength="100" class="form-control width-120" /> +
+
+
+ +
+ <#form:input path="moduleType" maxlength="50" class="form-control width-120" /> +
+
+
+ +
+ <#form:select path="status" dictType="sys_search_status" blankOption="true" class="form-control" /> +
+
+
+ +
+ <#form:input path="remarks" maxlength="500" class="form-control width-120" /> +
+
+
+ + +
+ +
+
+
+
+<% } %> + \ No newline at end of file diff --git a/modules/cms/src/main/resources/views/modules/cms/cmsIndex.html b/modules/cms/src/main/resources/views/modules/cms/cmsIndex.html new file mode 100644 index 00000000..fb0e08cc --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cms/cmsIndex.html @@ -0,0 +1,108 @@ +<% layout('/layouts/default.html', {title: '内容管理', libs:['layout','zTree']}){ %> +
+
+
+
+ +
+ + + + +
+
+
+
+
+
+
+
+
+ +
+<% } %> + diff --git a/modules/cms/src/main/resources/views/modules/cms/cmsNone.html b/modules/cms/src/main/resources/views/modules/cms/cmsNone.html new file mode 100644 index 00000000..aa278c83 --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cms/cmsNone.html @@ -0,0 +1,9 @@ +<% layout('/layouts/default.html', {title: '公共模型', libs: []}){ %> +
+
+
+ 请在左侧选择站点栏目(公共模型不可操作)。 +
+
+
+<% } %> diff --git a/modules/cms/src/main/resources/views/modules/cms/commentForm.html b/modules/cms/src/main/resources/views/modules/cms/commentForm.html new file mode 100644 index 00000000..d91730ab --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cms/commentForm.html @@ -0,0 +1,188 @@ +<% layout('/layouts/default.html', {title: '文章评论表管理', libs: ['validate','fileupload']}){ %> +
+
+
+
+ ${text(comment.isNewRecord ? '新增文章评论表' : '编辑文章评论表')} +
+
+ +
+
+ <#form:form id="inputForm" model="${comment}" action="${ctx}/cms/comment/save" method="post" class="form-horizontal"> +
+
${text('基本信息')}
+ <#form:hidden path="id"/> +
+
+
+ +
+ <#form:input path="categoryCode" maxlength="64" class="form-control required"/> +
+
+
+
+
+ +
+ <#form:input path="articleId" maxlength="64" class="form-control required"/> +
+
+
+
+
+
+
+ +
+ <#form:input path="parentId" maxlength="64" class="form-control"/> +
+
+
+
+
+ +
+ <#form:input path="articleTitle" maxlength="255" class="form-control required"/> +
+
+
+
+
+
+
+ +
+ <#form:textarea path="content" rows="4" maxlength="255" class="form-control required"/> +
+
+
+
+
+
+
+ +
+ <#form:input path="name" maxlength="50" class="form-control"/> +
+
+
+
+
+ +
+ <#form:input path="ip" maxlength="100" class="form-control"/> +
+
+
+
+
+
+
+ +
+ <#form:input path="auditUserCode" maxlength="64" class="form-control"/> +
+
+
+
+
+ +
+ <#form:input path="auditDate" class="form-control"/> +
+
+
+
+
+
+
+ +
+ <#form:input path="auditComment" maxlength="200" class="form-control"/> +
+
+
+
+
+ +
+ <#form:input path="hitsPlus" class="form-control digits"/> +
+
+
+
+
+
+
+ +
+ <#form:input path="hitsMinus" class="form-control digits"/> +
+
+
+
+
+
+
+ +
+ <#form:fileupload id="uploadImage" bizKey="${comment.id}" bizType="comment_image" + uploadType="image" class="" readonly="false"/> +
+
+
+
+
+
+
+ +
+ <#form:fileupload id="uploadFile" bizKey="${comment.id}" bizType="comment_file" + uploadType="all" class="" readonly="false"/> +
+
+
+
+
+ + +
+
+<% } %> + \ No newline at end of file diff --git a/modules/cms/src/main/resources/views/modules/cms/commentList.html b/modules/cms/src/main/resources/views/modules/cms/commentList.html new file mode 100644 index 00000000..a6982d53 --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cms/commentList.html @@ -0,0 +1,150 @@ +<% layout('/layouts/default.html', {title: '文章评论表管理', libs: ['dataGrid']}){ %> +
+
+
+
+ ${text('文章评论表管理')} +
+
+ ${text('查询')} + <% if(hasPermi('cms:comment:edit')){ %> + ${text('新增')} + <% } %> +
+
+
+ <#form:form id="searchForm" model="${comment}" action="${ctx}/cms/comment/listData" method="post" class="form-inline hide" + data-page-no="${parameter.pageNo}" data-page-size="${parameter.pageSize}" data-order-by="${parameter.orderBy}"> +
+ +
+ <#form:input path="categoryCode" maxlength="64" class="form-control width-120"/> +
+
+
+ +
+ <#form:input path="articleId" maxlength="64" class="form-control width-120"/> +
+
+
+ +
+ <#form:input path="parentId" maxlength="64" class="form-control width-120"/> +
+
+
+ +
+ <#form:input path="articleTitle" maxlength="255" class="form-control width-120"/> +
+
+
+ +
+ <#form:input path="content" maxlength="255" class="form-control width-120"/> +
+
+
+ +
+ <#form:input path="name" maxlength="50" class="form-control width-120"/> +
+
+
+ +
+ <#form:input path="ip" maxlength="100" class="form-control width-120"/> +
+
+
+ +
+ <#form:input path="auditUserCode" maxlength="64" class="form-control width-120"/> +
+
+
+ +
+ <#form:input path="auditDate" class="form-control width-120"/> +
+
+
+ +
+ <#form:input path="auditComment" maxlength="200" class="form-control width-120"/> +
+
+
+ +
+ <#form:input path="hitsPlus" class="form-control width-120"/> +
+
+
+ +
+ <#form:input path="hitsMinus" class="form-control width-120"/> +
+
+
+ +
+ <#form:select path="status" dictType="sys_search_status" blankOption="true" class="form-control"/> +
+
+
+ + +
+ +
+
+
+
+
+<% } %> + \ No newline at end of file diff --git a/modules/cms/src/main/resources/views/modules/cms/reportForm.html b/modules/cms/src/main/resources/views/modules/cms/reportForm.html new file mode 100644 index 00000000..f8671738 --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cms/reportForm.html @@ -0,0 +1,122 @@ +<% layout('/layouts/default.html', {title: '内容举报表管理', libs: ['validate','fileupload']}){ %> +
+
+
+
+ ${text(report.isNewRecord ? '新增内容举报表' : '编辑内容举报表')} +
+
+ +
+
+ <#form:form id="inputForm" model="${report}" action="${ctx}/cms/report/save" method="post" class="form-horizontal"> +
+
${text('基本信息')}
+ <#form:hidden path="id"/> +
+
+
+
+ +
+ <#form:input path="reportSource" maxlength="1" class="form-control"/> +
+
+
+
+
+
+
+ +
+ <#form:input path="reportContent" maxlength="500" class="form-control"/> +
+
+
+
+
+
+
+ +
+ <#form:input path="reportUrl" maxlength="1000" class="form-control"/> +
+
+
+
+
+
+
+ +
+ <#form:input path="reportType" maxlength="1" class="form-control"/> +
+
+
+
+
+
+
+ +
+ <#form:input path="reportCause" maxlength="500" class="form-control"/> +
+
+
+
+
+
+
+ +
+ <#form:fileupload id="uploadImage" bizKey="${report.id}" bizType="report_image" + uploadType="image" class="" readonly="false"/> +
+
+
+
+
+
+
+ +
+ <#form:fileupload id="uploadFile" bizKey="${report.id}" bizType="report_file" + uploadType="all" class="" readonly="false"/> +
+
+
+
+
+ + +
+
+<% } %> + \ No newline at end of file diff --git a/modules/cms/src/main/resources/views/modules/cms/reportList.html b/modules/cms/src/main/resources/views/modules/cms/reportList.html new file mode 100644 index 00000000..2fbf77bb --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cms/reportList.html @@ -0,0 +1,91 @@ +<% layout('/layouts/default.html', {title: '内容举报表管理', libs: ['dataGrid']}){ %> +
+
+
+
+ ${text('内容举报表管理')} +
+
+ ${text('查询')} + <% if(hasPermi('cms:report:edit')){ %> + ${text('新增')} + <% } %> +
+
+
+ <#form:form id="searchForm" model="${report}" action="${ctx}/cms/report/listData" method="post" class="form-inline hide" + data-page-no="${parameter.pageNo}" data-page-size="${parameter.pageSize}" data-order-by="${parameter.orderBy}"> +
+ +
+ <#form:input path="reportSource" maxlength="1" class="form-control width-120"/> +
+
+
+ +
+ <#form:input path="reportContent" maxlength="500" class="form-control width-120"/> +
+
+
+ +
+ <#form:input path="reportUrl" maxlength="1000" class="form-control width-120"/> +
+
+
+ +
+ <#form:input path="reportType" maxlength="1" class="form-control width-120"/> +
+
+
+ +
+ <#form:input path="reportCause" maxlength="500" class="form-control width-120"/> +
+
+
+ + +
+ +
+
+
+
+
+<% } %> + \ No newline at end of file diff --git a/modules/cms/src/main/resources/views/modules/cms/siteForm.html b/modules/cms/src/main/resources/views/modules/cms/siteForm.html new file mode 100644 index 00000000..5f8a1ff6 --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cms/siteForm.html @@ -0,0 +1,185 @@ +<% layout('/layouts/default.html', {title: '站点管理', libs: ['validate','fileupload','ueditor','dataGrid']}){ %> + +
+
+
+
+ ${text(site.isNewRecord ? '新增站点' : '编辑站点')} +
+
+ +
+
+ <#form:form id="inputForm" model="${site}" action="${ctx}/cms/site/save" method="post" class="form-horizontal"> +
+
${text('基本信息')}
+
+
+
+ +
+ <#form:input path="siteName" maxlength="100" placeholder="默认站点" class="form-control required"/> +
+
+
+
+
+ +
+ <#form:hidden path="isNewRecord" /> + <#form:input path="siteCode" maxlength="64" readonly="${!site.isNewRecord}" + class="form-control required abc" /> +
+
+
+
+
+
+
+ +
+ <#form:input path="domain" maxlength="500" class="form-control" placeholder="www.jeesite.com"/> +
+
+
+
+
+ +
+ <#form:input path="siteSort" maxlength="500" class="form-control required digits"/> +
+
+
+
+
+
+
+ +
+ <#form:input path="title" maxlength="100" placeholder="演示站点" class="form-control required"/> +
+
+
+
+
+
+
+ +
+ <#form:fileupload id="uploadLogo" bizKey="${site.id}" bizType="site_logo" returnPath="true" + filePathInputId="logo" + uploadType="image" readonly="false" maxUploadNum="1" isMini="false"/> + <#form:input path="logo" class="form-control"/> + + +
+
+
+
${text('详细信息')}
+
+
+
+ +
+ <#form:textarea path="description" maxlength="500" rows="3" placeholder="填写描述,有助于搜索引擎优化" class="form-control"/> +
+
+
+
+
+
+
+ +
+ <#form:input path="keywords" maxlength="500" placeholder="填写关键词,通过,或|分割,有助于搜索引擎优化" class="form-control"/> +
+
+
+
+
+
+
+ +
+ <#form:select path="theme" dictType="cms_theme" class="form-control" /> + + +
+
+
+
+
+ +
+ <#form:select path="customIndexView" items="${indexViewList}" itemLabel="id" itemValue="id" class="form-control required" /> + +
+
+
+
+
+
+
+ +
+ + <#form:ueditor name="copyright" path="copyright" maxlength="10000" height="200" class="required" + simpleToolbars="false" readonly="false" outline="false"/> +
+ +
+
+
+
${text('其他信息')}
+
+
+
+ +
+ <#form:textarea path="remarks" rows="4" maxlength="500" class="form-control"/> +
+
+
+
+ + +
+ + +
+
+<% } %> + \ No newline at end of file diff --git a/modules/cms/src/main/resources/views/modules/cms/siteList.html b/modules/cms/src/main/resources/views/modules/cms/siteList.html new file mode 100644 index 00000000..da056567 --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cms/siteList.html @@ -0,0 +1,90 @@ +<% layout('/layouts/default.html', {title: '站点管理', libs: ['dataGrid']}){ %> +
+
+
+
+ ${text('站点管理')} +
+
+ ${text('查询')} + <% if(hasPermi('cms:site:edit')){ %> + ${text('新增')} + <% } %> +
+
+
+ <#form:form id="searchForm" model="${site}" action="${ctx}/cms/site/listData" method="post" class="form-inline hide" + data-page-no="${parameter.pageNo}" data-page-size="${parameter.pageSize}" data-order-by="${parameter.orderBy}"> +
+ +
+ <#form:input path="siteName" maxlength="100" class="form-control width-120"/> +
+
+
+ +
+ <#form:input path="title" maxlength="100" class="form-control width-120"/> +
+
+
+ +
+ <#form:input path="domain" maxlength="500" class="form-control width-120"/> +
+
+
+ +
+ <#form:select path="status" dictType="sys_search_status" blankOption="true" class="form-control"/> +
+
+
+ + +
+ +
+
+
+
+
+<% } %> + \ No newline at end of file diff --git a/modules/cms/src/main/resources/views/modules/cms/tplForm.html b/modules/cms/src/main/resources/views/modules/cms/tplForm.html new file mode 100644 index 00000000..0d7093d7 --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cms/tplForm.html @@ -0,0 +1,57 @@ +<% layout('/layouts/default.html', {title: '模板内容', libs: ['validate','ueditor']}){%> +
+
+
+
+ ${text('模板内容')} +
+
+ +
+
+ <#form:form id="inputForm" model="${template}" class="form-horizontal2"> +
+
+
+
+  ${text('文件名')}: + <#form:input value="${template.filePath}/${template.fileName}" + name="fileName" maxlength="255" class="form-control required nofocus" /> +
+
+
+
+
+ <#form:textarea path="fileContent" rows="23" + encodeHtml="true" maxlength="990000" + class="form-control autoHeight" /> +
+
+
+ + +
+
+<% } %> + diff --git a/modules/cms/src/main/resources/views/modules/cms/tplHelp.html b/modules/cms/src/main/resources/views/modules/cms/tplHelp.html new file mode 100644 index 00000000..cdd47ac5 --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cms/tplHelp.html @@ -0,0 +1,9 @@ +<% layout('/layouts/default.html', {title: '模板帮助文档', libs: []}){ %> +
+
+
+ 左侧点击,查看模板内容。 +
+
+
+<% } %> diff --git a/modules/cms/src/main/resources/views/modules/cms/tplIndex.html b/modules/cms/src/main/resources/views/modules/cms/tplIndex.html new file mode 100644 index 00000000..c779911d --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cms/tplIndex.html @@ -0,0 +1,90 @@ +<% layout('/layouts/default.html', {title: '站点模版',libs:['dataGrid','layout','zTree']}){ %> + +
+
+
+
+
+ ${text('模板目录')} +
+
+ + + +
+
+
+
+
+
+
+
+
+ +
+<% } %> + diff --git a/modules/cms/src/main/resources/views/modules/cms/visitLogForm.html b/modules/cms/src/main/resources/views/modules/cms/visitLogForm.html new file mode 100644 index 00000000..14209141 --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cms/visitLogForm.html @@ -0,0 +1,366 @@ +<% layout('/layouts/default.html', {title: '访问日志表管理', libs: ['validate','fileupload']}){ %> +
+
+
+
+ ${text(visitLog.isNewRecord ? '新增访问日志表' : '编辑访问日志表')} +
+
+ +
+
+ <#form:form id="inputForm" model="${visitLog}" action="${ctx}/cms/visitLog/save" method="post" class="form-horizontal"> +
+
${text('基本信息')}
+ <#form:hidden path="id"/> +
+
+
+ +
+ <#form:input path="requestUrl" maxlength="1000" class="form-control"/> +
+
+
+
+
+ +
+ <#form:input path="requestUrlHost" maxlength="128" class="form-control"/> +
+
+
+
+
+
+
+ +
+ <#form:input path="sourceReferer" maxlength="1000" class="form-control"/> +
+
+
+
+
+ +
+ <#form:input path="sourceRefererHost" maxlength="128" class="form-control"/> +
+
+
+
+
+
+
+ +
+ <#form:input path="sourceType" maxlength="1" class="form-control"/> +
+
+
+
+
+ +
+ <#form:input path="searchEngine" maxlength="200" class="form-control"/> +
+
+
+
+
+
+
+ +
+ <#form:input path="searchWord" maxlength="200" class="form-control"/> +
+
+
+
+
+ +
+ <#form:input path="remoteAddr" maxlength="50" class="form-control"/> +
+
+
+
+
+
+
+ +
+ <#form:input path="userAgent" maxlength="500" class="form-control"/> +
+
+
+
+
+ +
+ <#form:input path="userLanguage" maxlength="32" class="form-control"/> +
+
+
+
+
+
+
+ +
+ <#form:input path="userScreenSize" maxlength="32" class="form-control"/> +
+
+
+
+
+ +
+ <#form:input path="userDevice" maxlength="32" class="form-control"/> +
+
+
+
+
+
+
+ +
+ <#form:input path="userOsName" maxlength="32" class="form-control"/> +
+
+
+
+
+ +
+ <#form:input path="userBrowser" maxlength="32" class="form-control"/> +
+
+
+
+
+
+
+ +
+ <#form:input path="userBrowserVersion" maxlength="16" class="form-control"/> +
+
+
+
+
+ +
+ <#form:input path="uniqueVisitId" maxlength="64" class="form-control"/> +
+
+
+
+
+
+
+ +
+ <#form:input path="visitDate" maxlength="8" class="form-control"/> +
+
+
+
+
+ +
+ <#form:input path="visitTime" class="form-control"/> +
+
+
+
+
+
+
+ +
+ <#form:input path="isNewVisit" maxlength="1" class="form-control"/> +
+
+
+
+
+ +
+ <#form:input path="firstVisitTime" class="form-control digits"/> +
+
+
+
+
+
+
+ +
+ <#form:input path="prevRemainTime" class="form-control digits"/> +
+
+
+
+
+ +
+ <#form:input path="totalRemainTime" class="form-control digits"/> +
+
+
+
+
+
+
+ +
+ <#form:input path="siteCode" maxlength="64" class="form-control"/> +
+
+
+
+
+ +
+ <#form:input path="siteName" maxlength="100" class="form-control"/> +
+
+
+
+
+
+
+ +
+ <#form:input path="categoryCode" maxlength="64" class="form-control"/> +
+
+
+
+
+ +
+ <#form:input path="categoryName" maxlength="100" class="form-control"/> +
+
+
+
+
+
+
+ +
+ <#form:input path="contentId" maxlength="64" class="form-control"/> +
+
+
+
+
+ +
+ <#form:input path="contentTitle" maxlength="255" class="form-control"/> +
+
+
+
+
+
+
+ +
+ <#form:input path="visitUserCode" maxlength="100" class="form-control"/> +
+
+
+
+
+ +
+ <#form:input path="visitUserName" maxlength="100" class="form-control"/> +
+
+
+
+
+
+
+ +
+ <#form:fileupload id="uploadImage" bizKey="${visitLog.id}" bizType="visitLog_image" + uploadType="image" class="" readonly="false"/> +
+
+
+
+
+
+
+ +
+ <#form:fileupload id="uploadFile" bizKey="${visitLog.id}" bizType="visitLog_file" + uploadType="all" class="" readonly="false"/> +
+
+
+
+
+ + +
+
+<% } %> + \ No newline at end of file diff --git a/modules/cms/src/main/resources/views/modules/cms/visitLogList.html b/modules/cms/src/main/resources/views/modules/cms/visitLogList.html new file mode 100644 index 00000000..75968d3d --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cms/visitLogList.html @@ -0,0 +1,112 @@ +<% layout('/layouts/default.html', {title: '访问日志表管理', libs: ['dataGrid']}){ %> +
+
+
+
+ ${text('访问日志表管理')} +
+ +
+
+ <#form:form id="searchForm" model="${visitLog}" action="${ctx}/cms/visitLog/listData" method="post" class="form-inline hide" + data-page-no="${parameter.pageNo}" data-page-size="${parameter.pageSize}" data-order-by="${parameter.orderBy}"> +
+ +
+ <#form:input path="requestUrl" maxlength="1000" class="form-control width-120"/> +
+
+
+ +
+ <#form:input path="requestUrlHost" maxlength="128" class="form-control width-120"/> +
+
+
+ +
+ <#form:input path="sourceReferer" maxlength="1000" class="form-control width-120"/> +
+
+
+ +
+ <#form:input path="sourceRefererHost" maxlength="128" class="form-control width-120"/> +
+
+ +
+ +
+ <#form:input path="searchWord" maxlength="200" class="form-control width-120"/> +
+
+ + + + + + +
+ + +
+ +
+
+
+
+
+<% } %> + \ No newline at end of file diff --git a/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/comment.html b/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/comment.html new file mode 100644 index 00000000..20e0fc0f --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/comment.html @@ -0,0 +1,7 @@ +<% layout('layouts/default.html', {title: '留言', libs: []}){ %> + + +留言 + + +<% } %> \ No newline at end of file diff --git a/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/include/banner.html b/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/include/banner.html new file mode 100644 index 00000000..d31238c0 --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/include/banner.html @@ -0,0 +1,15 @@ +

+ +
\ No newline at end of file diff --git a/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/include/footer.html b/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/include/footer.html new file mode 100644 index 00000000..1d342d98 --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/include/footer.html @@ -0,0 +1,16 @@ + + + diff --git a/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/include/head.html b/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/include/head.html new file mode 100644 index 00000000..ad12e6e1 --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/include/head.html @@ -0,0 +1,14 @@ +<%/* Copyright (c) 2013-Now http://jeesite.com All rights reserved. */%> + + + + + + + + + +${(isNotBlank(title!) ? title! + ' - ' : '') + @Global.getConfig('productName')} + + + diff --git a/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/include/header.html b/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/include/header.html new file mode 100644 index 00000000..d143047e --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/include/header.html @@ -0,0 +1,49 @@ + + + + + + \ No newline at end of file diff --git a/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/index.html b/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/index.html new file mode 100644 index 00000000..aea44769 --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/index.html @@ -0,0 +1,35 @@ +<% layout('layouts/default.html', {title:site.siteName+'-首页', libs: []}){ %> +
+
+
+

JeeSite平台简介

+

${site.description}

+

更多...

+
+
+
+
+ <#html:foreach items="${categoryList(site.siteCode, '0', 3, '')}" var="category,status"> + <#html:if test="${category.moduleType == 'article'}"> +
+
+
+
+

更多>>${category.categoryName}

+
+
+
    + <#html:foreach items="${articleList(site.siteCode, category.categoryCode, 5)}" var="article,status"> +
  • ${status.index}.   ${article.updateDate,'yyyy-MM-dd'} + ${abbr(article.title,28)}
  • + +
+
+ +
+
+
+ + +
+<% } %> diff --git a/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/layouts/default.html b/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/layouts/default.html new file mode 100644 index 00000000..1e335112 --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/layouts/default.html @@ -0,0 +1,15 @@ +<%/* Copyright (c) 2013-Now http://jeesite.com All rights reserved. */ +/* + * 默认布局文件 + * @param title 页面标题 + * @param bodyClass body标签的class内容 + */ +%> + +<% include('../include/head.html', {title: text(title!)}){} %> + +
+<% include('../include/header.html'){} %> +${layoutContent} +<% include('../include/footer.html'){} %> +
\ No newline at end of file diff --git a/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/list.html b/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/list.html new file mode 100644 index 00000000..d64e6881 --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/list.html @@ -0,0 +1,31 @@ +<% layout('layouts/default.html', {title: '列表页面', libs: []}){ %> +<% include('include/banner.html'){} %> +
+
+

栏目列表

+
    + <#html:foreach items="${qmark(categoryList! != null, categoryList!, categoryList(site.siteCode, category.parentCode, 50, ''))}" var="category,status"> +
  • ${category.categoryName}
  • + +
+
+
+

${category.categoryName}

+ <#html:if test="${page! != null && category.moduleType == 'article'}"> +
    + <#html:foreach items="${page.list}" var="article,status"> +
  • ${article.updateDate,'yyyy-MM-dd'} + ${abbr(article.title,96)}
  • + +
+ + + +
+
+<% } %> + diff --git a/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/listCategory.html b/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/listCategory.html new file mode 100644 index 00000000..177dceed --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/listCategory.html @@ -0,0 +1,41 @@ +<% layout('layouts/default.html', {title: '列表页面', libs: []}){ %> +<% include('include/banner.html'){} %> +
+
+

栏目列表

+
    + <#html:foreach items="${qmark(categoryList! != null, categoryList!, categoryList(site.siteCode, category.parentCode, 50, ''))}" var="category,status"> +
  • ${category.categoryName}
  • + +
+
+
+

${category.categoryName}

+

+ <#html:foreach items="${qmark(categoryList! != null, categoryList!, [])}" var="category,status"> + <#html:if test="${category.moduleType == 'article'}"> +
+
+
+
+

更多>>${category.categoryName}

+
+
+
    + <#html:foreach items="${articleList(site.siteCode, category.categoryCode, 5)}" var="article,status"> +
  • ${status.index}.   ${article.updateDate,'yyyy-MM-dd'} + ${abbr(article.title,28)}
  • + +
+
+ +
+
+
+ + +
+
+
+<% } %> + diff --git a/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/map.html b/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/map.html new file mode 100644 index 00000000..ee32dc55 --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/map.html @@ -0,0 +1,32 @@ +<% layout('layouts/default.html', {title: '站点地图', libs: []}){ %> + +
+

站点地图

+ <#html:foreach items="${siteList()}" var="site"> + +
+ <#html:foreach items="${categoryList(site.siteCode, '0', -1, '')}" var="category"> +
+ ${category.categoryName} +
+ <#html:set value="${categoryList(site.siteCode, category.categoryCode, -1, '')}" export="categoryList" /> + <#html:if test="${isNotEmpty(categoryList)}"> +
+ <#html:foreach items="${categoryList}" var="category"> + ${category.categoryName} + +
+ + +
+ +
+<% } %> diff --git a/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/search.html b/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/search.html new file mode 100644 index 00000000..03192892 --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/search.html @@ -0,0 +1,98 @@ +<% layout('layouts/default.html', {title: '全站搜索', libs: []}){ %> + + + +
+ + + +
+<% } %> \ No newline at end of file diff --git a/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/viewArticle.html b/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/viewArticle.html new file mode 100644 index 00000000..204fe354 --- /dev/null +++ b/modules/cms/src/main/resources/views/modules/cmsfront/themes/default/viewArticle.html @@ -0,0 +1,9 @@ +<% layout('layouts/default.html', {title:'文章查看',libs: []}){ %> +<% include('include/banner.html'){} %> +
+

${article.title}

+
摘要:${article.description}
+
${article.articleData.content}
+ +
+<% } %> diff --git a/root/pom.xml b/root/pom.xml index f648ad94..23e8ca8e 100644 --- a/root/pom.xml +++ b/root/pom.xml @@ -16,6 +16,7 @@ ../parent ../common ../modules/core + ../modules/cms ../web diff --git a/web/pom.xml b/web/pom.xml index 213772d1..ccaeb314 100644 --- a/web/pom.xml +++ b/web/pom.xml @@ -61,6 +61,13 @@ ${project.parent.version} --> + +