diff --git a/admin-console/bin/.gitignore b/admin-console/bin/.gitignore index 0ac90b6fef5fe952b3907150accf1ebada662e6b..e1d9f7e98c040a342bdbd67cee9e8c82651792dc 100644 --- a/admin-console/bin/.gitignore +++ b/admin-console/bin/.gitignore @@ -1,9 +1,3 @@ -/application.properties -/banner.txt -/beetl.properties -/btsql-ext.properties -/com/ -/excelTemplates/ -/sql/ -/static/ -/templates/ +/target/ +/filesystem/ +/src/ diff --git a/admin-console/bin/README.md b/admin-console/bin/README.md new file mode 100644 index 0000000000000000000000000000000000000000..339253d60e4d8b0722503cc18756d97bed64d76f --- /dev/null +++ b/admin-console/bin/README.md @@ -0,0 +1,2 @@ + +##### 系统管理 diff --git a/admin-console/bin/pom.xml b/admin-console/bin/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..65c30d955778d7c9447ce457abd40b86f2d5d127 --- /dev/null +++ b/admin-console/bin/pom.xml @@ -0,0 +1,42 @@ + + 4.0.0 + admin-console + jar + + com.ibeetl + admin + 1.1.4 + ../pom.xml + + + + com.ibeetl + admin-core + 1.1.4 + + + com.oracle + ojdbc6 + 11.2.0 + + + + io.springfox + springfox-swagger2 + 2.9.2 + + + + io.springfox + springfox-swagger-ui + 2.9.2 + + + com.github.xiaoymin + swagger-bootstrap-ui + 1.6 + + + + diff --git a/admin-console/pom.xml b/admin-console/pom.xml index 99ee2bf02b2681b767e7d9e2191848b6c9c05402..ff2eec349add51782888dfd41376d104cbb6c31c 100644 --- a/admin-console/pom.xml +++ b/admin-console/pom.xml @@ -1,27 +1,24 @@ - - 4.0.0 - admin-console - jar - - com.ibeetl - admin - ${plus.version} - ../pom.xml - - - - com.ibeetl - admin-core - ${plus.version} - - - - - mysql - mysql-connector-java - 6.0.5 - - - - + + 4.0.0 + admin-console + jar + + com.ibeetl + admin + ${plus.version} + ../pom.xml + + + + com.ibeetl + admin-core + ${plus.version} + + + com.oracle + ojdbc6 + 11.2.0 + + + diff --git a/admin-console/src/main/java/META-INF/MANIFEST.MF b/admin-console/src/main/java/META-INF/MANIFEST.MF new file mode 100644 index 0000000000000000000000000000000000000000..393aa80685c3e09ce59509b0a6240634b0263c74 --- /dev/null +++ b/admin-console/src/main/java/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: com.ibeetl.admin.CosonleApplication + diff --git a/admin-console/src/main/java/com/ibeetl/admin/CosonleApplication.java b/admin-console/src/main/java/com/ibeetl/admin/CosonleApplication.java index 76300ad44776496d3fbfbe0e65d00bc23464e9e5..47748d7caf4cd15ed5df6910c1547c7ddebfbb64 100644 --- a/admin-console/src/main/java/com/ibeetl/admin/CosonleApplication.java +++ b/admin-console/src/main/java/com/ibeetl/admin/CosonleApplication.java @@ -20,6 +20,4 @@ public class CosonleApplication extends SpringBootServletInitializer { SpringApplication.run(CosonleApplication.class, args); } - - } \ No newline at end of file diff --git a/admin-console/src/main/java/com/ibeetl/admin/console/dao/RoleConsoleDao.java b/admin-console/src/main/java/com/ibeetl/admin/console/dao/RoleConsoleDao.java index c98730ea2595f21f82e795e4bab335166be26597..dc2a65300cd0358205aea31c5fec8007c4de2bf2 100644 --- a/admin-console/src/main/java/com/ibeetl/admin/console/dao/RoleConsoleDao.java +++ b/admin-console/src/main/java/com/ibeetl/admin/console/dao/RoleConsoleDao.java @@ -6,7 +6,6 @@ import org.beetl.sql.core.annotatoin.SqlResource; import org.beetl.sql.core.engine.PageQuery; import org.beetl.sql.core.mapper.BaseMapper; -import com.ibeetl.admin.console.web.query.RoleUserQuery; import com.ibeetl.admin.core.entity.CoreRole; import com.ibeetl.admin.core.entity.CoreUser; diff --git a/admin-console/src/main/java/com/ibeetl/admin/console/dao/RoleFunctionConsoleDao.java b/admin-console/src/main/java/com/ibeetl/admin/console/dao/RoleFunctionConsoleDao.java index 1ed684827c4b4a1a52a4fe107ca3292e29011054..7134e3c1d28f044d46b0a823e1aee53ac7823898 100644 --- a/admin-console/src/main/java/com/ibeetl/admin/console/dao/RoleFunctionConsoleDao.java +++ b/admin-console/src/main/java/com/ibeetl/admin/console/dao/RoleFunctionConsoleDao.java @@ -1,23 +1,22 @@ -package com.ibeetl.admin.console.dao; - -import java.util.List; - -import org.beetl.sql.core.annotatoin.Param; -import org.beetl.sql.core.annotatoin.SqlResource; -import org.beetl.sql.core.mapper.BaseMapper; - -import com.ibeetl.admin.console.web.dto.RoleDataAccessFunction; -import com.ibeetl.admin.core.entity.CoreRoleFunction; - -@SqlResource("console.roleFunction") -public interface RoleFunctionConsoleDao extends BaseMapper { - - - void deleteRoleFunction(List ids); - - List getFunctionIdByRole(Long roleId); - - List getQueryFunctionAndRoleData(Long roleId); - - -} +package com.ibeetl.admin.console.dao; + +import java.util.List; + +import org.beetl.sql.core.annotatoin.SqlResource; +import org.beetl.sql.core.mapper.BaseMapper; + +import com.ibeetl.admin.console.web.dto.RoleDataAccessFunction; +import com.ibeetl.admin.core.entity.CoreRoleFunction; + +@SqlResource("console.roleFunction") +public interface RoleFunctionConsoleDao extends BaseMapper { + + + void deleteRoleFunction(List ids); + + List getFunctionIdByRole(Long roleId); + + List getQueryFunctionAndRoleData(Long roleId); + + +} diff --git a/admin-console/src/main/java/com/ibeetl/admin/console/dao/UserConsoleDao.java b/admin-console/src/main/java/com/ibeetl/admin/console/dao/UserConsoleDao.java index 342cbf2eaaef0abc11297b5a3a0440fc43f21aee..69d458f90af461a05d9dc6203fc8f7dfa327181e 100644 --- a/admin-console/src/main/java/com/ibeetl/admin/console/dao/UserConsoleDao.java +++ b/admin-console/src/main/java/com/ibeetl/admin/console/dao/UserConsoleDao.java @@ -1,6 +1,7 @@ package com.ibeetl.admin.console.dao; -import org.beetl.sql.core.annotatoin.Param; +import java.util.List; + import org.beetl.sql.core.annotatoin.SqlResource; import org.beetl.sql.core.engine.PageQuery; import org.beetl.sql.core.mapper.BaseMapper; @@ -9,8 +10,6 @@ import com.ibeetl.admin.core.entity.CoreUser; import com.ibeetl.admin.core.entity.CoreUserRole; import com.ibeetl.admin.core.util.enums.GeneralStateEnum; -import java.util.List; - @SqlResource("console.user") public interface UserConsoleDao extends BaseMapper { diff --git a/admin-console/src/main/java/com/ibeetl/admin/console/service/FunctionConsoleService.java b/admin-console/src/main/java/com/ibeetl/admin/console/service/FunctionConsoleService.java index 14843d784f030efc13c4dd0d270852fd84f10b02..3fc5db1d1756161e15ec25e4fc6950f9f5f82e03 100644 --- a/admin-console/src/main/java/com/ibeetl/admin/console/service/FunctionConsoleService.java +++ b/admin-console/src/main/java/com/ibeetl/admin/console/service/FunctionConsoleService.java @@ -16,11 +16,9 @@ import com.ibeetl.admin.core.dao.CoreMenuDao; import com.ibeetl.admin.core.dao.CoreRoleMenuDao; import com.ibeetl.admin.core.entity.CoreFunction; import com.ibeetl.admin.core.entity.CoreMenu; -import com.ibeetl.admin.core.entity.CoreOrg; import com.ibeetl.admin.core.entity.CoreRoleFunction; import com.ibeetl.admin.core.entity.CoreRoleMenu; import com.ibeetl.admin.core.rbac.tree.FunctionItem; -import com.ibeetl.admin.core.rbac.tree.OrgItem; import com.ibeetl.admin.core.service.BaseService; import com.ibeetl.admin.core.service.CorePlatformService; import com.ibeetl.admin.core.util.PlatformException; diff --git a/admin-console/src/main/java/com/ibeetl/admin/console/service/MenuConsoleService.java b/admin-console/src/main/java/com/ibeetl/admin/console/service/MenuConsoleService.java index 59864b340e63f976c42bce67940fe3d7b2c62439..07c19f1ccad022e27f47eeec3f0c0d864472f607 100644 --- a/admin-console/src/main/java/com/ibeetl/admin/console/service/MenuConsoleService.java +++ b/admin-console/src/main/java/com/ibeetl/admin/console/service/MenuConsoleService.java @@ -1,92 +1,90 @@ -package com.ibeetl.admin.console.service; - -import com.ibeetl.admin.console.dao.MenuConsoleDao; -import com.ibeetl.admin.console.web.query.MenuQuery; -import com.ibeetl.admin.core.dao.CoreRoleMenuDao; -import com.ibeetl.admin.core.entity.CoreMenu; -import com.ibeetl.admin.core.rbac.tree.MenuItem; -import com.ibeetl.admin.core.service.BaseService; -import com.ibeetl.admin.core.service.CorePlatformService; -import com.ibeetl.admin.core.util.PlatformException; - -import org.beetl.sql.core.engine.PageQuery; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.annotation.CacheEvict; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.ArrayList; -import java.util.List; - -@Service -@Transactional -public class MenuConsoleService extends BaseService { - - @Autowired - MenuConsoleDao menuDao; - @Autowired - CoreRoleMenuDao roleMenuDao; - - @Autowired - CorePlatformService platformService; - - public void queryByCondtion(PageQuery query) { - menuDao.queryByCondtion(query); - queryListAfter(query.getList()); - } - - public Long saveMenu(CoreMenu menu) { - CoreMenu query = new CoreMenu(); - query.setCode(menu.getCode()); - long queryCount = menuDao.templateCount(query); - if (queryCount > 0) { - throw new PlatformException("菜单编码已存在"); - } - menuDao.insert(menu, true); - platformService.clearMenuCache(); - return menu.getId(); - } - - public void deleteMenu(Long menuId) { - deleteMenuId(menuId); - } - - public void batchDeleteMenuId(List menuIds) { - for (Long id : menuIds) { - deleteMenuId(id); - } - platformService.clearMenuCache(); - } - - public void updateMenu(CoreMenu menu) { - menuDao.updateById(menu); - platformService.clearMenuCache(); - } - - public CoreMenu getMenu(Long menuId) { - CoreMenu menu = menuDao.unique(menuId); - platformService.clearMenuCache(); - return menu; - } - - - private void deleteMenuId(Long menuId) { - MenuItem root = platformService.buildMenu(); - MenuItem fun = root.findChild(menuId); - List all = fun.findAllItem(); - //也删除自身 - all.add(fun); - realDeleteMenu(all); - } - - private void realDeleteMenu(List all) { - List ids = new ArrayList<>(all.size()); - for (MenuItem item : all) { - ids.add(item.getId()); - this.menuDao.deleteById(item.getId()); - } - //删除角色和菜单的关系 - roleMenuDao.deleteRoleMenu(ids); - - } -} +package com.ibeetl.admin.console.service; + +import java.util.ArrayList; +import java.util.List; + +import org.beetl.sql.core.engine.PageQuery; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.ibeetl.admin.console.dao.MenuConsoleDao; +import com.ibeetl.admin.core.dao.CoreRoleMenuDao; +import com.ibeetl.admin.core.entity.CoreMenu; +import com.ibeetl.admin.core.rbac.tree.MenuItem; +import com.ibeetl.admin.core.service.BaseService; +import com.ibeetl.admin.core.service.CorePlatformService; +import com.ibeetl.admin.core.util.PlatformException; + +@Service +@Transactional +public class MenuConsoleService extends BaseService { + + @Autowired + MenuConsoleDao menuDao; + @Autowired + CoreRoleMenuDao roleMenuDao; + + @Autowired + CorePlatformService platformService; + + public void queryByCondtion(PageQuery query) { + menuDao.queryByCondtion(query); + queryListAfter(query.getList()); + } + + public Long saveMenu(CoreMenu menu) { + CoreMenu query = new CoreMenu(); + query.setCode(menu.getCode()); + long queryCount = menuDao.templateCount(query); + if (queryCount > 0) { + throw new PlatformException("菜单编码已存在"); + } + menuDao.insert(menu, true); + platformService.clearMenuCache(); + return menu.getId(); + } + + public void deleteMenu(Long menuId) { + deleteMenuId(menuId); + } + + public void batchDeleteMenuId(List menuIds) { + for (Long id : menuIds) { + deleteMenuId(id); + } + platformService.clearMenuCache(); + } + + public void updateMenu(CoreMenu menu) { + menuDao.updateById(menu); + platformService.clearMenuCache(); + } + + public CoreMenu getMenu(Long menuId) { + CoreMenu menu = menuDao.unique(menuId); + platformService.clearMenuCache(); + return menu; + } + + + private void deleteMenuId(Long menuId) { + MenuItem root = platformService.buildMenu(); + MenuItem fun = root.findChild(menuId); + List all = fun.findAllItem(); + //也删除自身 + all.add(fun); + realDeleteMenu(all); + } + + private void realDeleteMenu(List all) { + List ids = new ArrayList<>(all.size()); + for (MenuItem item : all) { + ids.add(item.getId()); + this.menuDao.deleteById(item.getId()); + } + //删除角色和菜单的关系 + roleMenuDao.deleteRoleMenu(ids); + + } +} diff --git a/admin-console/src/main/java/com/ibeetl/admin/console/service/RoleConsoleService.java b/admin-console/src/main/java/com/ibeetl/admin/console/service/RoleConsoleService.java index 6ab6a817ba966576153f361fa253aca8c2b8ad3d..fb074263c934456c51c3d354105c3df57221859d 100644 --- a/admin-console/src/main/java/com/ibeetl/admin/console/service/RoleConsoleService.java +++ b/admin-console/src/main/java/com/ibeetl/admin/console/service/RoleConsoleService.java @@ -69,7 +69,7 @@ public class RoleConsoleService extends BaseService { //从缓存里取出组织机构名称 for(CoreUser user:list) { Long orgId = user.getOrgId(); - Integer orgId1 = (Integer)user.get("orgId1"); + Integer orgId1 = Integer.valueOf(user.get("orgId1").toString()); user.set("orgIdText", root.findChild(orgId).getName()); user.set("orgId1Text", root.findChild((long)orgId1).getName()); diff --git a/admin-console/src/main/java/com/ibeetl/admin/console/web/AuditConsoleController.java b/admin-console/src/main/java/com/ibeetl/admin/console/web/AuditConsoleController.java index 18b9d5c8236630356a281c371a465783beefdf19..d8d99c26543c8bb632deb1c44bcc28bb363febf1 100644 --- a/admin-console/src/main/java/com/ibeetl/admin/console/web/AuditConsoleController.java +++ b/admin-console/src/main/java/com/ibeetl/admin/console/web/AuditConsoleController.java @@ -1,83 +1,84 @@ -package com.ibeetl.admin.console.web; - +package com.ibeetl.admin.console.web; -import java.util.List; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.beetl.sql.core.engine.PageQuery; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.servlet.ModelAndView; - -import com.ibeetl.admin.console.service.AuditConsoleService; -import com.ibeetl.admin.console.web.query.AuditQuery; -import com.ibeetl.admin.console.web.query.UserQuery; -import com.ibeetl.admin.core.annotation.Function; -import com.ibeetl.admin.core.annotation.Query; -import com.ibeetl.admin.core.entity.CoreAudit; -import com.ibeetl.admin.core.util.AnnotationUtil; -import com.ibeetl.admin.core.web.JsonResult; -/** - * 用户管理接口 - * @author xiandafu - * - */ -@Controller -public class AuditConsoleController { - private final Log log = LogFactory.getLog(this.getClass()); - private static final String MODEL = "/admin/audit"; - - @Autowired - AuditConsoleService auditConsoleService; - - - /*页面*/ - - @GetMapping(MODEL + "/index.do") - @Function("trace") - public ModelAndView index() { - ModelAndView view = new ModelAndView("/admin/audit/index.html"); - view.addObject("search", AuditQuery.class.getName()); - return view; - } - - - /*Json*/ - - @PostMapping(MODEL + "/view.json") - @ResponseBody - @Function("trace") - public JsonResult view(Long id) { - CoreAudit audit = auditConsoleService.queryById(id); - return JsonResult.success(audit); - } - - - - @RequestMapping(MODEL + "/list.json") - @Function("trace") - @ResponseBody - public JsonResult> list(AuditQuery condtion) { - - PageQuery page = condtion.getPageQuery(); - auditConsoleService.queryByCondtion(page); - return JsonResult.success(page); - } - - - @PostMapping(MODEL + "/list/condition.json") - @Function("trace") - @ResponseBody - public JsonResult>> listCondtion() { - List> list = AnnotationUtil.getInstance().getAnnotations(Query.class, AuditQuery.class); - return JsonResult.success(list); - } - - -} + +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.beetl.sql.core.engine.PageQuery; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.servlet.ModelAndView; + +import com.ibeetl.admin.console.service.AuditConsoleService; +import com.ibeetl.admin.console.web.query.AuditQuery; +import com.ibeetl.admin.core.annotation.Function; +import com.ibeetl.admin.core.annotation.Query; +import com.ibeetl.admin.core.entity.CoreAudit; +import com.ibeetl.admin.core.util.AnnotationUtil; +import com.ibeetl.admin.core.web.JsonResult; + +import io.swagger.annotations.Api; +/** + * 用户管理接口 + * @author xiandafu + * + */ +@Api(value="用户管理接口",tags={"用户管理接口"}) +@Controller +public class AuditConsoleController { + private final Log log = LogFactory.getLog(this.getClass()); + private static final String MODEL = "/admin/audit"; + + @Autowired + AuditConsoleService auditConsoleService; + + + /*页面*/ + @GetMapping(MODEL + "/index.do") + @Function("trace") + public ModelAndView index() { + ModelAndView view = new ModelAndView("/admin/audit/index.html"); + view.addObject("search", AuditQuery.class.getName()); + return view; + } + + + /*Json*/ + + @PostMapping(MODEL + "/view.json") + @ResponseBody + @Function("trace") + public JsonResult view(Long id) { + CoreAudit audit = auditConsoleService.queryById(id); + return JsonResult.success(audit); + } + + + + @RequestMapping(MODEL + "/list.json") + @Function("trace") + @ResponseBody + public JsonResult> list(AuditQuery condtion) { + + PageQuery page = condtion.getPageQuery(); + auditConsoleService.queryByCondtion(page); + return JsonResult.success(page); + } + + + @PostMapping(MODEL + "/list/condition.json") + @Function("trace") + @ResponseBody + public JsonResult>> listCondtion() { + List> list = AnnotationUtil.getInstance().getAnnotations(Query.class, AuditQuery.class); + return JsonResult.success(list); + } + + +} diff --git a/admin-console/src/main/java/com/ibeetl/admin/console/web/MenuController.java b/admin-console/src/main/java/com/ibeetl/admin/console/web/MenuController.java index 6f434eae6fb883e5e1fa068d8e1c205e21da03cd..a5089050dbbac92505fd66a7726bd73dc5bdafba 100644 --- a/admin-console/src/main/java/com/ibeetl/admin/console/web/MenuController.java +++ b/admin-console/src/main/java/com/ibeetl/admin/console/web/MenuController.java @@ -1,175 +1,173 @@ -package com.ibeetl.admin.console.web; - -import java.util.Date; -import java.util.List; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.beetl.sql.core.engine.PageQuery; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.servlet.ModelAndView; - -import com.ibeetl.admin.console.service.MenuConsoleService; -import com.ibeetl.admin.console.web.query.FunctionQuery; -import com.ibeetl.admin.console.web.query.MenuQuery; -import com.ibeetl.admin.core.annotation.Function; -import com.ibeetl.admin.core.annotation.Query; -import com.ibeetl.admin.core.entity.CoreFunction; -import com.ibeetl.admin.core.entity.CoreMenu; -import com.ibeetl.admin.core.rbac.tree.MenuItem; -import com.ibeetl.admin.core.service.CorePlatformService; -import com.ibeetl.admin.core.util.AnnotationUtil; -import com.ibeetl.admin.core.util.ConvertUtil; -import com.ibeetl.admin.core.web.JsonResult; - -/** - * @author lijiazhi - */ -@Controller -public class MenuController { - - - private static final String MODEL = "/admin/menu"; - private final Log log = LogFactory.getLog(this.getClass()); - - - @Autowired - MenuConsoleService menuService; - - @Autowired - CorePlatformService platformService; - - /*页面*/ - - @GetMapping(MODEL + "/index.do") - @Function("menu") - public ModelAndView index() { - ModelAndView view = new ModelAndView("/admin/menu/index.html"); - view.addObject("search", MenuQuery.class.getName()); - return view; - } - - @GetMapping(MODEL + "/add.do") - @Function("menu.add") - public ModelAndView add() { - ModelAndView view = new ModelAndView("/admin/menu/add.html"); - return view; - } - @GetMapping(MODEL + "/edit.do") - @Function("menu.edit") - public ModelAndView edit(Integer id) { - ModelAndView view = new ModelAndView("/admin/menu/edit.html"); - CoreMenu menu = menuService.queryById(id); - view.addObject("menu", menu); - return view; - } - - /*Json*/ - - /** - * 查询 - * @param menu - * @return - */ - @PostMapping(MODEL + "/list/condition.json") - @Function("menu.query") - @ResponseBody - public JsonResult condition() { - List> list = AnnotationUtil.getInstance().getAnnotations(Query.class, MenuQuery.class); - return JsonResult.success(list); - } - - - @PostMapping(MODEL + "/list.json") - @Function("menu.query") - @ResponseBody - public JsonResult list(MenuQuery condtion) { - PageQuery page = condtion.getPageQuery(); - menuService.queryByCondtion(page); - return JsonResult.success(page); - } - - - /** - * 添加 - * @param menu - * @return - */ - @PostMapping(MODEL + "/save.json") - @Function("menu.save") - @ResponseBody - public JsonResult save(@Validated CoreMenu menu) { - menu.setCreateTime(new Date()); - Long id = menuService.saveMenu(menu); - return JsonResult.success(id); - } - - /** - * 更新 - * @param fun - * @return - */ - @PostMapping(MODEL + "/update.json") - @Function("menu.update") - @ResponseBody - public JsonResult update(CoreMenu fun) { - menuService.updateMenu(fun); - return new JsonResult().success(); - } - - /** - * 根据id查询菜单信息 - * @param id 菜单Id - * @return - */ - @PostMapping(MODEL + "/view.json") - @Function("menu.query") - @ResponseBody - public JsonResult view(Long id) { - CoreMenu fun = menuService.queryById(id); - MenuItem root = this.platformService.buildMenu(); - MenuItem child = root.findChild(fun.getId()); - CoreMenu parent = child.getParent().getData(); - fun.set("parentMenuName", parent.getName()); - return JsonResult.success(fun); - } - - /** - * 删除 - * @param id 菜单id - * @return - */ - @PostMapping(MODEL + "/delete.json") - @Function("menu.delete") - @ResponseBody - public JsonResult delete(Long id) { - menuService.deleteMenu(id); - return new JsonResult().success(); - } - - /** - * 批量删除 - * @param ids 菜单id集合 - * @return - */ - @PostMapping(MODEL + "/batchDel.json") - @Function("menu.delete") - @ResponseBody - public JsonResult delete(String ids) { - List dels = ConvertUtil.str2longs(ids); - menuService.batchDeleteMenuId(dels); - return new JsonResult().success(); - } - - - - -} - - +package com.ibeetl.admin.console.web; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.beetl.sql.core.engine.PageQuery; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.servlet.ModelAndView; + +import com.ibeetl.admin.console.service.MenuConsoleService; +import com.ibeetl.admin.console.web.query.MenuQuery; +import com.ibeetl.admin.core.annotation.Function; +import com.ibeetl.admin.core.annotation.Query; +import com.ibeetl.admin.core.entity.CoreMenu; +import com.ibeetl.admin.core.rbac.tree.MenuItem; +import com.ibeetl.admin.core.service.CorePlatformService; +import com.ibeetl.admin.core.util.AnnotationUtil; +import com.ibeetl.admin.core.util.ConvertUtil; +import com.ibeetl.admin.core.web.JsonResult; + +/** + * @author lijiazhi + */ +@Controller +public class MenuController { + + + private static final String MODEL = "/admin/menu"; + private final Log log = LogFactory.getLog(this.getClass()); + + + @Autowired + MenuConsoleService menuService; + + @Autowired + CorePlatformService platformService; + + /*页面*/ + + @GetMapping(MODEL + "/index.do") + @Function("menu") + public ModelAndView index() { + ModelAndView view = new ModelAndView("/admin/menu/index.html"); + view.addObject("search", MenuQuery.class.getName()); + return view; + } + + @GetMapping(MODEL + "/add.do") + @Function("menu.add") + public ModelAndView add() { + ModelAndView view = new ModelAndView("/admin/menu/add.html"); + return view; + } + @GetMapping(MODEL + "/edit.do") + @Function("menu.edit") + public ModelAndView edit(Integer id) { + ModelAndView view = new ModelAndView("/admin/menu/edit.html"); + CoreMenu menu = menuService.queryById(id); + view.addObject("menu", menu); + return view; + } + + /*Json*/ + + /** + * 查询 + * @param menu + * @return + */ + @PostMapping(MODEL + "/list/condition.json") + @Function("menu.query") + @ResponseBody + public JsonResult condition() { + List> list = AnnotationUtil.getInstance().getAnnotations(Query.class, MenuQuery.class); + return JsonResult.success(list); + } + + + @PostMapping(MODEL + "/list.json") + @Function("menu.query") + @ResponseBody + public JsonResult list(MenuQuery condtion) { + PageQuery page = condtion.getPageQuery(); + menuService.queryByCondtion(page); + return JsonResult.success(page); + } + + + /** + * 添加 + * @param menu + * @return + */ + @PostMapping(MODEL + "/save.json") + @Function("menu.save") + @ResponseBody + public JsonResult save(@Validated CoreMenu menu) { + menu.setCreateTime(new Date()); + Long id = menuService.saveMenu(menu); + return JsonResult.success(id); + } + + /** + * 更新 + * @param fun + * @return + */ + @PostMapping(MODEL + "/update.json") + @Function("menu.update") + @ResponseBody + public JsonResult update(CoreMenu fun) { + menuService.updateMenu(fun); + return new JsonResult().success(); + } + + /** + * 根据id查询菜单信息 + * @param id 菜单Id + * @return + */ + @PostMapping(MODEL + "/view.json") + @Function("menu.query") + @ResponseBody + public JsonResult view(Long id) { + CoreMenu fun = menuService.queryById(id); + MenuItem root = this.platformService.buildMenu(); + MenuItem child = root.findChild(fun.getId()); + CoreMenu parent = child.getParent().getData(); + fun.set("parentMenuName", parent.getName()); + return JsonResult.success(fun); + } + + /** + * 删除 + * @param id 菜单id + * @return + */ + @PostMapping(MODEL + "/delete.json") + @Function("menu.delete") + @ResponseBody + public JsonResult delete(Long id) { + menuService.deleteMenu(id); + return new JsonResult().success(); + } + + /** + * 批量删除 + * @param ids 菜单id集合 + * @return + */ + @PostMapping(MODEL + "/batchDel.json") + @Function("menu.delete") + @ResponseBody + public JsonResult delete(String ids) { + List dels = ConvertUtil.str2longs(ids); + menuService.batchDeleteMenuId(dels); + return new JsonResult().success(); + } + + + + +} + + diff --git a/admin-console/src/main/java/com/ibeetl/admin/console/web/UserConsoleController.java b/admin-console/src/main/java/com/ibeetl/admin/console/web/UserConsoleController.java index 6b180dcedcdb036b1d595580b1d1990adcb221e0..025520a03c7859a4a4433519fac732690a17f836 100644 --- a/admin-console/src/main/java/com/ibeetl/admin/console/web/UserConsoleController.java +++ b/admin-console/src/main/java/com/ibeetl/admin/console/web/UserConsoleController.java @@ -1,316 +1,317 @@ -package com.ibeetl.admin.console.web; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.beetl.sql.core.engine.PageQuery; -import org.jxls.common.Context; -import org.jxls.util.JxlsHelper; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.servlet.ModelAndView; - -import com.ibeetl.admin.console.service.OrgConsoleService; -import com.ibeetl.admin.console.service.RoleConsoleService; -import com.ibeetl.admin.console.service.UserConsoleService; -import com.ibeetl.admin.console.web.dto.UserExcelExportData; -import com.ibeetl.admin.console.web.query.UserQuery; -import com.ibeetl.admin.console.web.query.UserRoleQuery; -import com.ibeetl.admin.core.annotation.Function; -import com.ibeetl.admin.core.annotation.Query; -import com.ibeetl.admin.core.entity.CoreUser; -import com.ibeetl.admin.core.entity.CoreUserRole; -import com.ibeetl.admin.core.file.FileItem; -import com.ibeetl.admin.core.file.FileService; -import com.ibeetl.admin.core.service.CorePlatformService; -import com.ibeetl.admin.core.util.AnnotationUtil; -import com.ibeetl.admin.core.util.ConvertUtil; -import com.ibeetl.admin.core.util.PlatformException; -import com.ibeetl.admin.core.util.ValidateConfig; -import com.ibeetl.admin.core.util.enums.GeneralStateEnum; -import com.ibeetl.admin.core.web.JsonResult; - -/** - * 用户管理接口 - * - * @author xiandafu - */ -@Controller -public class UserConsoleController { - private final Log log = LogFactory.getLog(this.getClass()); - private static final String MODEL = "/admin/user"; - - @Autowired - UserConsoleService userConsoleService; - - @Autowired - CorePlatformService platformService; - - @Autowired - RoleConsoleService roleConsoleService; - @Autowired - OrgConsoleService orgConsoleService; - @Autowired - FileService fileService; - - - - - /* 页面 */ - - @GetMapping(MODEL + "/index.do") - @Function("user") - public ModelAndView index() { - ModelAndView view = new ModelAndView("/admin/user/index.html"); - view.addObject("search", UserQuery.class.getName()); - return view; - } - - @GetMapping(MODEL + "/edit.do") - @Function("user.edit") - public ModelAndView edit(String id) { - ModelAndView view = new ModelAndView("/admin/user/edit.html"); - CoreUser user = userConsoleService.queryById(id); - view.addObject("user", user); - return view; - } - - @GetMapping(MODEL + "/add.do") - @Function("user.add") - public ModelAndView add() { - ModelAndView view = new ModelAndView("/admin/user/add.html"); - return view; - } - - @GetMapping(MODEL + "/changePassword.do") - @Function("user.add") - public ModelAndView changePassword(Long id) { - CoreUser user = userConsoleService.queryById(id); - ModelAndView view = new ModelAndView("/admin/user/changePassword.html"); - view.addObject("user", user); - return view; - } - - @GetMapping(MODEL + "/role/list.do") - @Function("user.role") - public ModelAndView userRoleIndex(Long id) { - CoreUser user = userConsoleService.queryById(id); - ModelAndView view = new ModelAndView("/admin/user/userRole.html"); - view.addObject("search", UserRoleQuery.class.getName()); - view.addObject("user", user); - return view; - } - - @GetMapping(MODEL + "/role/add.do") - @Function("user.role") - public ModelAndView userRoleAdd(Long id) { - CoreUser user = userConsoleService.queryById(id); - ModelAndView view = new ModelAndView("/admin/user/userRoleAdd.html"); - view.addObject("user", user); - return view; - } - - /* Json */ - - @PostMapping(MODEL + "/delete.json") - @Function("user.delete") - @ResponseBody - public JsonResult delete(String ids) { - List dels = ConvertUtil.str2longs(ids); - userConsoleService.batchDelSysUser(dels); - return JsonResult.success(); - } - - @PostMapping(MODEL + "/update.json") - @Function("user.update") - @ResponseBody - public JsonResult update(@Validated(ValidateConfig.UPDATE.class) CoreUser user) { - boolean success = userConsoleService.updateTemplate(user); - if (success) { - this.platformService.clearFunctionCache(); - return JsonResult.success(); - } else { - return JsonResult.failMessage("保存失败!"); - } - } - - @PostMapping(MODEL + "/add.json") - @Function("user.add") - @ResponseBody - public JsonResult add(@Validated(ValidateConfig.ADD.class) CoreUser user) { - if (!platformService.isAllowUserName(user.getCode())) { - return JsonResult.failMessage("不允许的注册名字 " + user.getCode()); - } - user.setCreateTime(new Date()); - userConsoleService.saveUser(user); - return JsonResult.success(user.getId()); - } - - @PostMapping(MODEL + "/view.json") - @ResponseBody - @Function("user.query") - public JsonResult view(Long id) { - CoreUser user = userConsoleService.queryById(id); - return JsonResult.success(user); - } - - @PostMapping(MODEL + "/list.json") - @Function("user.query") - @ResponseBody - public JsonResult> index(UserQuery condtion) { - - PageQuery page = condtion.getPageQuery(); - userConsoleService.queryByCondtion(page); - return JsonResult.success(page); - } - - @PostMapping(MODEL + "/list/condition.json") - @Function("user.query") - @ResponseBody - public JsonResult>> indexCondtion() { - List> list = AnnotationUtil.getInstance().getAnnotations(Query.class, UserQuery.class); - return JsonResult.success(list); - } - - @PostMapping(MODEL + "/disable.json") - @Function("user.disable") - @ResponseBody - public JsonResult disableUser(String ids) { - - List dels = ConvertUtil.str2longs(ids); - - userConsoleService.batchUpdateUserState(dels, GeneralStateEnum.DISABLE); - for (Long id : dels) { - CoreUser user = userConsoleService.queryById(id); - this.platformService.restUserSession(user.getCode()); - } - return JsonResult.success(); - - } - - /** - * 启用用户操作 - * - * @return - */ - @PostMapping(MODEL + "/enable.json") - @Function("user.enable") - @ResponseBody - public JsonResult enableUser(String ids) { - - List enables = ConvertUtil.str2longs(ids); - userConsoleService.batchUpdateUserState(enables, GeneralStateEnum.ENABLE); - return JsonResult.success(); - - } - - /** - * 管理员重置用户密码 - * - * @return - */ - @PostMapping(MODEL + "/changePassword.json") - @Function("user.reset") - @ResponseBody - public JsonResult changePassword(Long id, String password) { - - userConsoleService.resetPassword(id, password); - return new JsonResult().success(); - } - - /** - * 用户所有授权角色列表 - * - * @param id - * 用户id - * @return - */ - @PostMapping(MODEL + "/role/list.json") - @Function("user.role") - @ResponseBody - public JsonResult> getRoleList(UserRoleQuery roleQuery) { - List list = userConsoleService.getUserRoles(roleQuery); - return JsonResult.success(list); - } - - /** - * 用户添加授权角色页 - * - * @return - */ - @PostMapping(MODEL + "/role/add.json") - @Function("user.role") - @ResponseBody - public JsonResult saveUserRole(@Validated CoreUserRole userRole) { - userRole.setCreateTime(new Date()); - this.userConsoleService.saveUserRole(userRole); - this.platformService.clearFunctionCache(); - return JsonResult.success(userRole.getId()); - - } - - /** - * 删除用户角色授权 - * - * @return - */ - @PostMapping(MODEL + "/role/delete.json") - @Function("user.role") - @ResponseBody - public JsonResult delUserRole(String ids) { - List dels = ConvertUtil.str2longs(ids); - - userConsoleService.deleteUserRoles(dels); - this.platformService.clearFunctionCache(); - return JsonResult.success(); - } - - - @PostMapping(MODEL + "/excel/export.json") - @Function("user.export") - @ResponseBody - public JsonResult export(HttpServletResponse response,UserQuery condtion) { - String excelTemplate ="excelTemplates/admin/user/user_collection_template.xls"; - PageQuery page = condtion.getPageQuery(); - //取出全部符合条件的 - page.setPageSize(Integer.MAX_VALUE); - page.setPageNumber(1); - page.setTotalRow(Integer.MAX_VALUE); - List users =userConsoleService.queryExcel(page); - try(InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(excelTemplate)) { - if(is==null) { - throw new PlatformException("模板资源不存在:"+excelTemplate); - } - FileItem item = fileService.createFileTemp("user_collection.xls"); - OutputStream os = item.openOutpuStream(); - Context context = new Context(); - context.putVar("users", users); - JxlsHelper.getInstance().processTemplate(is, os, context); - //下载参考FileSystemContorller - return JsonResult.success(item.getPath()); - } catch (IOException e) { - throw new PlatformException(e.getMessage()); - } - - } - - - - - - -} +package com.ibeetl.admin.console.web; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.beetl.sql.core.engine.PageQuery; +import org.jxls.common.Context; +import org.jxls.util.JxlsHelper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.servlet.ModelAndView; + +import com.ibeetl.admin.console.service.OrgConsoleService; +import com.ibeetl.admin.console.service.RoleConsoleService; +import com.ibeetl.admin.console.service.UserConsoleService; +import com.ibeetl.admin.console.web.dto.UserExcelExportData; +import com.ibeetl.admin.console.web.query.UserQuery; +import com.ibeetl.admin.console.web.query.UserRoleQuery; +import com.ibeetl.admin.core.annotation.Function; +import com.ibeetl.admin.core.annotation.Query; +import com.ibeetl.admin.core.entity.CoreUser; +import com.ibeetl.admin.core.entity.CoreUserRole; +import com.ibeetl.admin.core.file.FileItem; +import com.ibeetl.admin.core.file.FileService; +import com.ibeetl.admin.core.service.CorePlatformService; +import com.ibeetl.admin.core.util.AnnotationUtil; +import com.ibeetl.admin.core.util.ConvertUtil; +import com.ibeetl.admin.core.util.PlatformException; +import com.ibeetl.admin.core.util.ValidateConfig; +import com.ibeetl.admin.core.util.enums.GeneralStateEnum; +import com.ibeetl.admin.core.web.JsonResult; + +import springfox.documentation.annotations.ApiIgnore; + +/** + * 用户管理接口 + * + * @author xiandafu + */ +@ApiIgnore +@Controller +public class UserConsoleController { + private final Log log = LogFactory.getLog(this.getClass()); + private static final String MODEL = "/admin/user"; + + @Autowired + UserConsoleService userConsoleService; + + @Autowired + CorePlatformService platformService; + + @Autowired + RoleConsoleService roleConsoleService; + @Autowired + OrgConsoleService orgConsoleService; + @Autowired + FileService fileService; + + + + + /* 页面 */ + + @GetMapping(MODEL + "/index.do") + @Function("user") + public ModelAndView index() { + ModelAndView view = new ModelAndView("/admin/user/index.html"); + view.addObject("search", UserQuery.class.getName()); + return view; + } + + @GetMapping(MODEL + "/edit.do") + @Function("user.edit") + public ModelAndView edit(String id) { + ModelAndView view = new ModelAndView("/admin/user/edit.html"); + CoreUser user = userConsoleService.queryById(id); + view.addObject("user", user); + return view; + } + + @GetMapping(MODEL + "/add.do") + @Function("user.add") + public ModelAndView add() { + ModelAndView view = new ModelAndView("/admin/user/add.html"); + return view; + } + + @GetMapping(MODEL + "/changePassword.do") +// @Function("user.add") + public ModelAndView changePassword(Long id) { + CoreUser user = userConsoleService.queryById(id); + ModelAndView view = new ModelAndView("/admin/user/changePassword.html"); + view.addObject("user", user); + return view; + } + + @GetMapping(MODEL + "/role/list.do") + @Function("user.role") + public ModelAndView userRoleIndex(Long id) { + CoreUser user = userConsoleService.queryById(id); + ModelAndView view = new ModelAndView("/admin/user/userRole.html"); + view.addObject("search", UserRoleQuery.class.getName()); + view.addObject("user", user); + return view; + } + + @GetMapping(MODEL + "/role/add.do") + @Function("user.role") + public ModelAndView userRoleAdd(Long id) { + CoreUser user = userConsoleService.queryById(id); + ModelAndView view = new ModelAndView("/admin/user/userRoleAdd.html"); + view.addObject("user", user); + return view; + } + + /* Json */ + + @PostMapping(MODEL + "/delete.json") + @Function("user.delete") + @ResponseBody + public JsonResult delete(String ids) { + List dels = ConvertUtil.str2longs(ids); + userConsoleService.batchDelSysUser(dels); + return JsonResult.success(); + } + + @PostMapping(MODEL + "/update.json") + @Function("user.update") + @ResponseBody + public JsonResult update(@Validated(ValidateConfig.UPDATE.class) CoreUser user) { + boolean success = userConsoleService.updateTemplate(user); + if (success) { + this.platformService.clearFunctionCache(); + return JsonResult.success(); + } else { + return JsonResult.failMessage("保存失败!"); + } + } + + @PostMapping(MODEL + "/add.json") + @Function("user.add") + @ResponseBody + public JsonResult add(@Validated(ValidateConfig.ADD.class) CoreUser user) { + if (!platformService.isAllowUserName(user.getCode())) { + return JsonResult.failMessage("不允许的注册名字 " + user.getCode()); + } + user.setCreateTime(new Date()); + userConsoleService.saveUser(user); + return JsonResult.success(user.getId()); + } + + @PostMapping(MODEL + "/view.json") + @ResponseBody + @Function("user.query") + public JsonResult view(Long id) { + CoreUser user = userConsoleService.queryById(id); + return JsonResult.success(user); + } + + @PostMapping(MODEL + "/list.json") + @Function("user.query") + @ResponseBody + public JsonResult> index(UserQuery condtion) { + + PageQuery page = condtion.getPageQuery(); + userConsoleService.queryByCondtion(page); + return JsonResult.success(page); + } + + @PostMapping(MODEL + "/list/condition.json") + @Function("user.query") + @ResponseBody + public JsonResult>> indexCondtion() { + List> list = AnnotationUtil.getInstance().getAnnotations(Query.class, UserQuery.class); + return JsonResult.success(list); + } + + @PostMapping(MODEL + "/disable.json") + @Function("user.disable") + @ResponseBody + public JsonResult disableUser(String ids) { + + List dels = ConvertUtil.str2longs(ids); + + userConsoleService.batchUpdateUserState(dels, GeneralStateEnum.DISABLE); + for (Long id : dels) { + CoreUser user = userConsoleService.queryById(id); + this.platformService.restUserSession(user.getCode()); + } + return JsonResult.success(); + + } + + /** + * 启用用户操作 + * + * @return + */ + @PostMapping(MODEL + "/enable.json") + @Function("user.enable") + @ResponseBody + public JsonResult enableUser(String ids) { + + List enables = ConvertUtil.str2longs(ids); + userConsoleService.batchUpdateUserState(enables, GeneralStateEnum.ENABLE); + return JsonResult.success(); + + } + + /** + * 管理员重置用户密码 + * + * @return + */ + @PostMapping(MODEL + "/changePassword.json") +// @Function("user.reset") + @ResponseBody + public JsonResult changePassword(Long id, String password) { + + userConsoleService.resetPassword(id, password); + return new JsonResult().success(); + } + + /** + * 用户所有授权角色列表 + * + * @param id + * 用户id + * @return + */ + @PostMapping(MODEL + "/role/list.json") + @Function("user.role") + @ResponseBody + public JsonResult> getRoleList(UserRoleQuery roleQuery) { + List list = userConsoleService.getUserRoles(roleQuery); + return JsonResult.success(list); + } + + /** + * 用户添加授权角色页 + * + * @return + */ + @PostMapping(MODEL + "/role/add.json") + @Function("user.role") + @ResponseBody + public JsonResult saveUserRole(@Validated CoreUserRole userRole) { + userRole.setCreateTime(new Date()); + this.userConsoleService.saveUserRole(userRole); + this.platformService.clearFunctionCache(); + return JsonResult.success(userRole.getId()); + + } + + /** + * 删除用户角色授权 + * + * @return + */ + @PostMapping(MODEL + "/role/delete.json") + @Function("user.role") + @ResponseBody + public JsonResult delUserRole(String ids) { + List dels = ConvertUtil.str2longs(ids); + + userConsoleService.deleteUserRoles(dels); + this.platformService.clearFunctionCache(); + return JsonResult.success(); + } + + + @PostMapping(MODEL + "/excel/export.json") + @Function("user.export") + @ResponseBody + public JsonResult export(HttpServletResponse response,UserQuery condtion) { + String excelTemplate ="excelTemplates/admin/user/user_collection_template.xls"; + PageQuery page = condtion.getPageQuery(); + //取出全部符合条件的 + page.setPageSize(Integer.MAX_VALUE); + page.setPageNumber(1); + page.setTotalRow(Integer.MAX_VALUE); + List users =userConsoleService.queryExcel(page); + try(InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(excelTemplate)) { + if(is==null) { + throw new PlatformException("模板资源不存在:"+excelTemplate); + } + FileItem item = fileService.createFileTemp("user_collection.xls"); + OutputStream os = item.openOutpuStream(); + Context context = new Context(); + context.putVar("users", users); + JxlsHelper.getInstance().processTemplate(is, os, context); + //下载参考FileSystemContorller + return JsonResult.success(item.getPath()); + } catch (IOException e) { + throw new PlatformException(e.getMessage()); + } + + } + + + + + + +} diff --git a/admin-console/src/main/java/com/ibeetl/admin/console/web/dto/UserExcelExportData.java b/admin-console/src/main/java/com/ibeetl/admin/console/web/dto/UserExcelExportData.java index 5abe00ebcf7e7570a2d5af5986e19ee50e057fd5..6d3ffafb88bde88d0d2da57bbe2264da76eceace 100644 --- a/admin-console/src/main/java/com/ibeetl/admin/console/web/dto/UserExcelExportData.java +++ b/admin-console/src/main/java/com/ibeetl/admin/console/web/dto/UserExcelExportData.java @@ -1,10 +1,5 @@ package com.ibeetl.admin.console.web.dto; -import javax.validation.constraints.NotBlank; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.ibeetl.admin.core.annotation.Dict; - /** * excel导出需要的模板数据 * @author xiandafu diff --git a/admin-console/src/main/java/com/ibeetl/admin/console/web/query/CmsBlogQuery.java b/admin-console/src/main/java/com/ibeetl/admin/console/web/query/CmsBlogQuery.java index fa91f4b13aca44d75c8564a73af119b49a8a69d3..66b05f9a3fe23203af4ee061b572135e30d2eb96 100644 --- a/admin-console/src/main/java/com/ibeetl/admin/console/web/query/CmsBlogQuery.java +++ b/admin-console/src/main/java/com/ibeetl/admin/console/web/query/CmsBlogQuery.java @@ -1,9 +1,7 @@ package com.ibeetl.admin.console.web.query; import com.ibeetl.admin.core.annotation.Query; -import com.ibeetl.admin.core.util.enums.CoreDictType; import com.ibeetl.admin.core.web.query.PageParam; -import java.util.Date; /** *CmsBlog查询 */ diff --git a/admin-console/src/main/java/com/ibeetl/admin/console/web/query/CoreDictQuery.java b/admin-console/src/main/java/com/ibeetl/admin/console/web/query/CoreDictQuery.java index 798da499adcf734fff727e048f8c1d9bd6ad6991..0dd97ee481eae15502d13138d5027130faaccf0a 100644 --- a/admin-console/src/main/java/com/ibeetl/admin/console/web/query/CoreDictQuery.java +++ b/admin-console/src/main/java/com/ibeetl/admin/console/web/query/CoreDictQuery.java @@ -1,9 +1,7 @@ package com.ibeetl.admin.console.web.query; import com.ibeetl.admin.core.annotation.Query; -import com.ibeetl.admin.core.util.enums.CoreDictType; import com.ibeetl.admin.core.web.query.PageParam; -import java.util.Date; /** *CoreDict查询 */ diff --git a/admin-console/src/main/java/com/ibeetl/admin/console/web/query/CoreFunctionQuery.java b/admin-console/src/main/java/com/ibeetl/admin/console/web/query/CoreFunctionQuery.java index 6762d537e465507a8260d0dd374c7c43b5a8ddd4..13460f5fc14af290a99b5f678c9eb225d75d8053 100644 --- a/admin-console/src/main/java/com/ibeetl/admin/console/web/query/CoreFunctionQuery.java +++ b/admin-console/src/main/java/com/ibeetl/admin/console/web/query/CoreFunctionQuery.java @@ -1,7 +1,6 @@ package com.ibeetl.admin.console.web.query; import com.ibeetl.admin.core.annotation.Query; -import com.ibeetl.admin.core.util.enums.CoreDictType; import com.ibeetl.admin.core.web.query.PageParam; /** *功能查询 diff --git a/admin-console/src/main/java/com/ibeetl/admin/console/web/query/OrgUserQuery.java b/admin-console/src/main/java/com/ibeetl/admin/console/web/query/OrgUserQuery.java index e9784bcffbdd44f986223c7f9aff160442eb4614..f8887dec8ec0bdfe25049e75805095c78343d986 100644 --- a/admin-console/src/main/java/com/ibeetl/admin/console/web/query/OrgUserQuery.java +++ b/admin-console/src/main/java/com/ibeetl/admin/console/web/query/OrgUserQuery.java @@ -1,9 +1,6 @@ package com.ibeetl.admin.console.web.query; -import java.util.Date; - import com.ibeetl.admin.core.annotation.Query; -import com.ibeetl.admin.core.util.Tool; import com.ibeetl.admin.core.util.enums.CoreDictType; import com.ibeetl.admin.core.web.query.PageParam; diff --git a/admin-console/src/main/java/com/ibeetl/admin/console/web/query/RoleUserQuery.java b/admin-console/src/main/java/com/ibeetl/admin/console/web/query/RoleUserQuery.java index 3cbbeaff77add8e76d74d01da4ed2b986e11e7da..884415ca3708e37ef74b7c3b537b2a559900fafc 100644 --- a/admin-console/src/main/java/com/ibeetl/admin/console/web/query/RoleUserQuery.java +++ b/admin-console/src/main/java/com/ibeetl/admin/console/web/query/RoleUserQuery.java @@ -1,7 +1,6 @@ package com.ibeetl.admin.console.web.query; import com.ibeetl.admin.core.annotation.Query; -import com.ibeetl.admin.core.util.enums.CoreDictType; import com.ibeetl.admin.core.web.query.PageParam; /** diff --git a/admin-console/src/main/java/com/ibeetl/admin/console/web/query/UserQuery.java b/admin-console/src/main/java/com/ibeetl/admin/console/web/query/UserQuery.java index 8fffd19f0d7d8c56dff9fe10033dbbde19f46be1..9e3164ae926121b70d9640cc94bf25a31cab59cc 100644 --- a/admin-console/src/main/java/com/ibeetl/admin/console/web/query/UserQuery.java +++ b/admin-console/src/main/java/com/ibeetl/admin/console/web/query/UserQuery.java @@ -23,9 +23,7 @@ public class UserQuery extends PageParam { @Query(name="职务",display=true,type=Query.TYPE_DICT,dict="job_type",group="job_type") private String jobType0; - - @Query(name="职务明细",display=true,type=Query.TYPE_DICT,dict="",group="job_type") - private String jobType1; + @Query(name="创建日期",display=true,type=Query.TYPE_DATE_BETWEEN) @@ -66,12 +64,7 @@ public class UserQuery extends PageParam { public void setJobType0(String jobType0) { this.jobType0 = jobType0; } - public String getJobType1() { - return jobType1; - } - public void setJobType1(String jobType1) { - this.jobType1 = jobType1; - } + public String getCreateDateRange() { return createDateRange; } diff --git a/admin-console/src/main/java/com/ibeetl/admin/console/web/query/WorkflowQuery.java b/admin-console/src/main/java/com/ibeetl/admin/console/web/query/WorkflowQuery.java index 73187f3355a76c6025f68b437ba6d2cff7b8a9d6..706f30eb5571b8c9dcd5e048bb0ee10d894be39a 100644 --- a/admin-console/src/main/java/com/ibeetl/admin/console/web/query/WorkflowQuery.java +++ b/admin-console/src/main/java/com/ibeetl/admin/console/web/query/WorkflowQuery.java @@ -1,7 +1,5 @@ package com.ibeetl.admin.console.web.query; -import java.util.Date; - import com.ibeetl.admin.core.annotation.Query; import com.ibeetl.admin.core.web.query.PageParam; diff --git a/admin-console/src/main/java/com/ibeetl/admin/quartz/QuartzTaskConfig.java b/admin-console/src/main/java/com/ibeetl/admin/quartz/QuartzTaskConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..39abba6101a2e7d095a47471bf03bbacdee966ca --- /dev/null +++ b/admin-console/src/main/java/com/ibeetl/admin/quartz/QuartzTaskConfig.java @@ -0,0 +1,54 @@ +package com.ibeetl.admin.quartz; + +import com.ibeetl.admin.quartz.entity.Timetask; +import com.ibeetl.admin.quartz.service.DynamicTask; +import com.ibeetl.admin.quartz.service.TimetaskService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * @author wangshihao + * @Title: 定时任务自启 + * @Description: 在系统启动的时候初始化已有的定时任务 + * @date 2018/9/2910:04 + */ + +@Configuration +public class QuartzTaskConfig { + + @Autowired(required = false) + private DynamicTask dynamicTask; + + @Autowired(required = false) + private TimetaskService timetaskService; + + @Bean + public boolean initTask() { + List listTimetask = new ArrayList<>(); + listTimetask = timetaskService.queryList(); + if(listTimetask.size() > 0){ + for(Timetask task : listTimetask){ + try { + if(task.getIsEffect()==1&&task.getIsStart()==1) { + boolean rs = dynamicTask.startOrStop(task, true); + if (rs) { + System.out.println("任务ID:" + task.getTaskId() +"在"+new Date()+ "初次启动成功! "); + } else { + System.out.println("任务ID:" + task.getTaskId() +"在"+new Date()+ "初次启动失败! "); + } + } + + } catch (Exception e) { + e.printStackTrace(); + } + } + } + return true; + } + +} diff --git a/admin-console/src/main/java/com/ibeetl/admin/quartz/dao/TimetaskDao.java b/admin-console/src/main/java/com/ibeetl/admin/quartz/dao/TimetaskDao.java new file mode 100644 index 0000000000000000000000000000000000000000..8aef80d359f57498e69aea8121b1f87431327001 --- /dev/null +++ b/admin-console/src/main/java/com/ibeetl/admin/quartz/dao/TimetaskDao.java @@ -0,0 +1,19 @@ +package com.ibeetl.admin.quartz.dao; + +import java.util.List; + +import org.beetl.sql.core.annotatoin.SqlResource; +import org.beetl.sql.core.mapper.BaseMapper; +import org.beetl.sql.core.engine.PageQuery; + +import com.ibeetl.admin.quartz.entity.*; + +/** + * Timetask Dao + */ +@SqlResource("quartz.timetask") +public interface TimetaskDao extends BaseMapper{ + public PageQuery queryByCondition(PageQuery query); + public void batchDelTimetaskByIds( List ids); + public List queryList(); +} \ No newline at end of file diff --git a/admin-console/src/main/java/com/ibeetl/admin/quartz/entity/ScheduleBean.java b/admin-console/src/main/java/com/ibeetl/admin/quartz/entity/ScheduleBean.java new file mode 100644 index 0000000000000000000000000000000000000000..185249fc77e55d552a3028b422877b240f7c46c1 --- /dev/null +++ b/admin-console/src/main/java/com/ibeetl/admin/quartz/entity/ScheduleBean.java @@ -0,0 +1,203 @@ +package com.ibeetl.admin.quartz.entity; + +import com.ibeetl.admin.quartz.service.TimeTypeEnum; +import org.quartz.Job; +import org.quartz.Scheduler; + +import java.util.Map; + +/** + * ScheduleBean + * @author Wenyi Feng + */ + +public class ScheduleBean { + + /** QuartzTaskStart scheduler obj */ + private Scheduler scheduler; + + /** 编号 */ + private Long id; + + /** task name */ + private String name; + + /** task description */ + private String description; + + /** time type */ + private TimeTypeEnum timeType; + + /** 类clazz */ + private Class clazz; + + /** job参数 */ + private Map paramJobMap; + + /** trigger参数 */ + private Map paramTriggerMap; + + /** cron */ + private String cron; + + /** time, simple */ + private Integer time; + + /** 时间点 */ + private Long atTime; + + /** job name */ + private String jobName; + + /** job group name */ + private String jobGroup; + + /** trigger name */ + private String triggerName; + + /** trigger group name */ + private String triggerGroup; + + /** + * 无参数构成方法 + */ + public ScheduleBean() { + } + + /** + * 简单的 快速的构成方法 + * @param scheduler Scheduler对象 + * @param clazz Class + * @param jobName 任务名称 + * @param triggerName 触发器名称 + */ + public ScheduleBean(Scheduler scheduler, + Class clazz, + String jobName, + String triggerName) { + this.scheduler = scheduler; + this.clazz = clazz; + this.jobName = jobName; + this.triggerName = triggerName; + } + + public Scheduler getScheduler() { + return scheduler; + } + + public void setScheduler(Scheduler scheduler) { + this.scheduler = scheduler; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public TimeTypeEnum getTimeType() { + return timeType; + } + + public void setTimeType(TimeTypeEnum timeType) { + this.timeType = timeType; + } + + public Class getClazz() { + return clazz; + } + + public void setClazz(Class clazz) { + this.clazz = clazz; + } + + public Map getParamJobMap() { + return paramJobMap; + } + + public void setParamJobMap(Map paramJobMap) { + this.paramJobMap = paramJobMap; + } + + public Map getParamTriggerMap() { + return paramTriggerMap; + } + + public void setParamTriggerMap(Map paramTriggerMap) { + this.paramTriggerMap = paramTriggerMap; + } + + public String getCron() { + return cron; + } + + public void setCron(String cron) { + this.cron = cron; + } + + public Integer getTime() { + return time; + } + + public void setTime(Integer time) { + this.time = time; + } + + public Long getAtTime() { + return atTime; + } + + public void setAtTime(Long atTime) { + this.atTime = atTime; + } + + public String getJobName() { + return jobName; + } + + public void setJobName(String jobName) { + this.jobName = jobName; + } + + public String getJobGroup() { + return jobGroup; + } + + public void setJobGroup(String jobGroup) { + this.jobGroup = jobGroup; + } + + public String getTriggerName() { + return triggerName; + } + + public void setTriggerName(String triggerName) { + this.triggerName = triggerName; + } + + public String getTriggerGroup() { + return triggerGroup; + } + + public void setTriggerGroup(String triggerGroup) { + this.triggerGroup = triggerGroup; + } +} diff --git a/admin-console/src/main/java/com/ibeetl/admin/quartz/entity/Timetask.java b/admin-console/src/main/java/com/ibeetl/admin/quartz/entity/Timetask.java new file mode 100644 index 0000000000000000000000000000000000000000..2d7051b7b147aa8a497db5f2360b238be1d7b550 --- /dev/null +++ b/admin-console/src/main/java/com/ibeetl/admin/quartz/entity/Timetask.java @@ -0,0 +1,168 @@ +package com.ibeetl.admin.quartz.entity; + +import java.util.Date; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Null; + +import org.beetl.sql.core.annotatoin.*; + +import com.ibeetl.admin.core.util.ValidateConfig; + +import org.beetl.sql.core.TailBean; +import java.math.*; + +import com.ibeetl.admin.core.annotation.Dict; +import com.ibeetl.admin.core.entity.BaseEntity; + + +/* +* +* gen by Spring Boot2 Admin 2018-09-28 +*/ +public class Timetask extends BaseEntity{ + + @NotNull(message = "ID不能为空", groups =ValidateConfig.UPDATE.class) + @AssignID("uuid") + private String id ; + + private String createBy ; + + private Date createDate ; + + private String createName ; + + private String cronExpression ; + + private Long isEffect ; + + private Long isStart ; + + private String taskDescribe ; + + private String taskId ; + + private String className ; + + private String runServerIp ; + + private String runServer ; + + private String updateBy ; + + private Date updateDate ; + + private String updateName ; + + public Timetask() + { + } + + public String getId(){ + return id; + } + public void setId(String id){ + this.id = id; + } + + public String getCreateBy(){ + return createBy; + } + public void setCreateBy(String createBy){ + this.createBy = createBy; + } + + public Date getCreateDate(){ + return createDate; + } + public void setCreateDate(Date createDate){ + this.createDate = createDate; + } + + public String getCreateName(){ + return createName; + } + public void setCreateName(String createName){ + this.createName = createName; + } + + public String getCronExpression(){ + return cronExpression; + } + public void setCronExpression(String cronExpression){ + this.cronExpression = cronExpression; + } + + public Long getIsEffect(){ + return isEffect; + } + public void setIsEffect(Long isEffect){ + this.isEffect = isEffect; + } + + public Long getIsStart(){ + return isStart; + } + public void setIsStart(Long isStart){ + this.isStart = isStart; + } + + public String getTaskDescribe(){ + return taskDescribe; + } + public void setTaskDescribe(String taskDescribe){ + this.taskDescribe = taskDescribe; + } + + public String getTaskId(){ + return taskId; + } + public void setTaskId(String taskId){ + this.taskId = taskId; + } + + public String getClassName(){ + return className; + } + public void setClassName(String className){ + this.className = className; + } + + public String getRunServerIp(){ + return runServerIp; + } + public void setRunServerIp(String runServerIp){ + this.runServerIp = runServerIp; + } + + public String getRunServer(){ + return runServer; + } + public void setRunServer(String runServer){ + this.runServer = runServer; + } + + public String getUpdateBy(){ + return updateBy; + } + public void setUpdateBy(String updateBy){ + this.updateBy = updateBy; + } + + public Date getUpdateDate(){ + return updateDate; + } + public void setUpdateDate(Date updateDate){ + this.updateDate = updateDate; + } + + public String getUpdateName(){ + return updateName; + } + public void setUpdateName(String updateName){ + this.updateName = updateName; + } + + +} diff --git a/admin-console/src/main/java/com/ibeetl/admin/quartz/job/CpWxUserSyncJob.java b/admin-console/src/main/java/com/ibeetl/admin/quartz/job/CpWxUserSyncJob.java new file mode 100644 index 0000000000000000000000000000000000000000..b35a7f6b6844b4bca0f563b3d19e6522b572fa13 --- /dev/null +++ b/admin-console/src/main/java/com/ibeetl/admin/quartz/job/CpWxUserSyncJob.java @@ -0,0 +1,22 @@ +package com.ibeetl.admin.quartz.job; + +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.springframework.scheduling.quartz.QuartzJobBean; + +import java.util.Date; + +/** + * @author gaoyh + * @Title: 企业微信用户同步 + * @Description: 企业微信用户、组织架构数据同步 + * @date 2018/11/06 + */ +public class CpWxUserSyncJob extends QuartzJobBean { + + + @Override + protected void executeInternal(JobExecutionContext context) throws JobExecutionException { + System.out.println("定时任务testjob1正在运行 : " + new Date()); + } +} diff --git a/admin-console/src/main/java/com/ibeetl/admin/quartz/service/DynamicTask.java b/admin-console/src/main/java/com/ibeetl/admin/quartz/service/DynamicTask.java new file mode 100644 index 0000000000000000000000000000000000000000..30931f083e3201b198e3f482404b087658828021 --- /dev/null +++ b/admin-console/src/main/java/com/ibeetl/admin/quartz/service/DynamicTask.java @@ -0,0 +1,193 @@ +package com.ibeetl.admin.quartz.service; + + +import com.ibeetl.admin.core.util.MyClassLoader; +import com.ibeetl.admin.quartz.entity.Timetask; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.quartz.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import java.io.IOException; +import java.net.UnknownHostException; +import java.util.List; + +/** + * 动态任务,用以动态调整Spring的任务 + * @author JueYue + * @date 2013-9-20 + * @version 1.0 + */ +@Service +public class DynamicTask { + + private final Log log = LogFactory.getLog(this.getClass()); + + private static final long IS_EFFECT_N = 0; + private static final long IS_EFFECT_Y = 1; + private static final long IS_START_N = 0; + private static final long IS_START_Y = 1; + + @Autowired + private Scheduler schedulerFactory; + + @Autowired + private TimetaskService timetaskService; + + /** + * 启动定时任务 + * @param task + */ + private boolean startTask(Timetask task){ + try { + //向调度器中添加任务 + scheduleJob(task); + return true; + } catch (SchedulerException e) { + log.error("startTask SchedulerException"+" cron_" + task.getId()+ e.getMessage()); + } + return false; + } + + /** + * 结束计划任务 + * @param task + * @throws SchedulerException + */ + private boolean endTask(Timetask task){ + try{ + TriggerKey triggerKey = new TriggerKey("cron_" + task.getId()); + //停止触发器 + schedulerFactory.pauseTrigger(triggerKey); + //移除触发器 + schedulerFactory.unscheduleJob(triggerKey); + JobKey jobKey = new JobKey(task.getId()); + //删除任务 + schedulerFactory.deleteJob(jobKey); + return true; + }catch (SchedulerException e) { + log.error("endTask SchedulerException" + " cron_" + task.getId() + e.getMessage()); + } + return false; + } + + + /** + * 开关定时任务 + * @param task + * @param flag + * @return + * @throws SchedulerException + */ + public boolean startOrStop(Timetask task, boolean flag){ + boolean isSuccess = flag ? startTask(task) : endTask(task); + if(isSuccess){ + task.setIsStart(IS_START_Y); + task.setIsEffect(IS_EFFECT_Y); + timetaskService.update(task); + //systemService.addLog((start?"开启任务":"停止任务")+task.getTaskId(), Globals.Log_Type_UPDATE, Globals.Log_Leavel_INFO); + log.info((flag?"开启任务":"停止任务")+"--任务ID:"+task.getTaskId()+"--任务描述:"+task.getTaskDescribe()+"--任务类:"+task.getClassName() ); + } + return isSuccess; + } + + /** + * 更新触发规则 + * @param task + * @return + */ +// public boolean updateCronExpression(Timetask task) { +// try { +// String newExpression = task.getCronExpression(); +// task = timeTaskService.get(Timetask.class, task.getId()); +// +// //任务运行中 +// if("1".equals(task.getIsStart())){ +// +//// CronTriggerBean trigger = (CronTriggerBean)schedulerFactory.getTrigger("cron_" + task.getId(), Scheduler.DEFAULT_GROUP); +//// String originExpression = trigger.getCronExpression(); +// //检查运行中的任务触发规则是否与新规则一致 +//// if (!originExpression.equalsIgnoreCase(newExpression)) { +//// trigger.setCronExpression(newExpression); +//// schedulerFactory.rescheduleJob("cron_" + task.getId(), Scheduler.DEFAULT_GROUP, trigger); +//// } +// //通过触发器key 向调度器 获取触发器实例 +// Trigger oldTrigger = schedulerFactory.getTrigger(new TriggerKey("cron_" + task.getId())); +// //获取bulid对象 +// TriggerBuilder tb = oldTrigger.getTriggerBuilder(); +// //创建触发器 +// CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(newExpression); +// Trigger newTrigger = tb.withSchedule(cronScheduleBuilder).build(); +// //更新触发器 +// schedulerFactory.rescheduleJob(oldTrigger.getKey(), newTrigger); +// +// }else{ +// //立即生效 +// List ipList = IpUtil.getLocalIPList(); +// String runServerIp = task.getRunServerIp(); +// boolean isStart = task.getIsStart().equals("0"); +// boolean isSuccess = false; +// if(ipList.contains(runServerIp) || StringUtil.isEmpty(runServerIp) || "本地".equals(runServerIp)){//当前服务器IP匹配成功 +// isSuccess = this.startOrStop(task ,isStart); +// }else{ +// try { +// String url = "http://" + task.getRunServer() + "/timeTaskController.do?remoteTask";//spring-mvc.xml +// String param = "id=" + task.getId() + "&isStart=" + (isStart ? "1" : "0"); +// String jsonstr = HttpRequest.httpPost(url, param, false); +// if (null != jsonstr && jsonstr.length() > 0) { +// JSONObject json = (JSONObject) JSONObject.parse(jsonstr); +// isSuccess = json.getBooleanValue("success"); +// } +// } catch (ClientProtocolException e) { +// log.info("远程主机‘" + task.getRunServer() + "’响应超时"); +// return false; +// } catch (IOException e) { +// log.info("远程主机‘"+task.getRunServer() + "’响应超时"); +// return false; +// } +// } +// if(isSuccess){ +// /*task.setIsEffect("1"); +// task.setIsStart("1"); +// timeTaskService.updateEntitie(task);*/ +// systemService.addLog(("立即生效开启任务成功,任务ID:") + task.getTaskId(), Globals.Log_Type_UPDATE, Globals.Log_Leavel_INFO); +// log.info(("立即生效开启任务成功,任务ID:") + "-------TaskId:" + task.getTaskId() + "-------Describe:" + task.getTaskDescribe() + "-----ClassName:" + task.getClassName() ); +// return true; +// }else{ +// systemService.addLog(("立即生效开启任务失败,任务ID:") + task.getTaskId(), Globals.Log_Type_UPDATE, Globals.Log_Leavel_INFO); +// log.info(("立即生效开启任务失败,任务ID:") + "-------TaskId:" + task.getTaskId() + "-------Describe:" + task.getTaskDescribe() + "-----ClassName:" + task.getClassName() ); +// return false; +// } +// } +// } catch (SchedulerException e) { +// log.error("updateCronExpression SchedulerException" + " cron_" + task.getId() + e.getMessage()); +// } +// +// return false; +// } + + + /** + * 注册 定时任务 + * @param task 定时任务对象 + * @throws SchedulerException + */ + private void scheduleJob(Timetask task) throws SchedulerException { + //build 要执行的任务 + JobDetail jobDetail = JobBuilder.newJob(MyClassLoader.getClassByScn(task.getClassName())) + .withIdentity(task.getId()) + .storeDurably() + .requestRecovery() + .build(); + //根据Cron表达式 build 触发时间对象 + CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(task.getCronExpression()); + //build 任务触发器 + CronTrigger cronTrigger = TriggerBuilder.newTrigger() + .withIdentity("cron_" + task.getId()) + .withSchedule(cronScheduleBuilder)//标明触发时间 + .build(); + //向调度器注册 定时任务 + schedulerFactory.scheduleJob(jobDetail, cronTrigger); + } + +} diff --git a/admin-console/src/main/java/com/ibeetl/admin/quartz/service/QuartzTask.java b/admin-console/src/main/java/com/ibeetl/admin/quartz/service/QuartzTask.java new file mode 100644 index 0000000000000000000000000000000000000000..05088084cbe0d3011a85603a89d40e5c2ad89613 --- /dev/null +++ b/admin-console/src/main/java/com/ibeetl/admin/quartz/service/QuartzTask.java @@ -0,0 +1,389 @@ +package com.ibeetl.admin.quartz.service; + +import com.ibeetl.admin.quartz.entity.ScheduleBean; +import org.quartz.*; +import org.quartz.impl.matchers.GroupMatcher; +import org.springframework.stereotype.Component; + +import java.util.Date; +import java.util.Map; +import java.util.Set; + +import static org.quartz.JobBuilder.newJob; +import static org.quartz.SimpleScheduleBuilder.simpleSchedule; +import static org.quartz.TriggerBuilder.newTrigger; + +/** + * Quartz Base Task + * + *
    + *
  • 开启定时任务
  • + *
  • 暂停定时任务
  • + *
  • 恢复定时任务
  • + *
  • 停止定时任务
  • + *
+ * + *

+ * 暂停定时任务:暂停所有定时任务,根据job暂停定时任务,根据trigger暂停定时任务 + *

+ * + *

+ * 停止定时任务后,不能再启动 + *

+ * @author Wenyi Feng + */ +@Component +public class QuartzTask { + + /** Scheduler对象 */ + private static Scheduler scheduler; + + /** + * 开启一个定时任务(如果定时任务正在运行,则开启失败) + * @param scheduleBean schedule bean + * @return 定时任务开启是否成功:true,开启成功;false:开启失败 + * @throws SchedulerException 异常 + */ + public boolean start(ScheduleBean scheduleBean) + throws SchedulerException { + + // 如果定时器以及启动,那么将无法再次启动 + if (!status()) { + + // 如果不给参数,我们将无法开启定时任务,因为Scheduler对象将变得不可控 + if (scheduleBean == null) + return false; + + // jobDetail + JobDetail jobDetail = getJobDetail(scheduleBean); + + // time type + TimeTypeEnum timeTypeEnum = scheduleBean.getTimeType(); + + // trigger + Trigger trigger = null; + if (timeTypeEnum == null) { + + // TimeTypeEnum.SIMPLE.getCode() + switch (timeTypeEnum.getCode()) { + case 1: // simple + trigger = getTriggerBySimple(scheduleBean); + break; + case 2: // atTime + trigger = getTriggerByAtTime(scheduleBean); + break; + case 3: // cron + trigger = getTriggerByCron(scheduleBean); + break; + default: + trigger = getTrigger(scheduleBean); + break; + } + + } else { + trigger = getTrigger(scheduleBean); + } + + if (scheduler == null) + scheduler = scheduleBean.getScheduler(); + + if (jobDetail != null && trigger != null) { + // 参数 + paramJob(jobDetail, scheduleBean.getParamJobMap()); + paramTrigger(trigger, scheduleBean.getParamTriggerMap()); + + scheduler.scheduleJob(jobDetail, trigger); + } + + return true; + } + return false; + } + + /** + * 查询定时任务状态 + * @return 定时任务当前状态:true,运行中;false:已停止 + * @throws SchedulerException 异常 + */ + public boolean status() throws SchedulerException { + if (scheduler != null) { + return scheduler.isStarted(); + } + return false; + } + + /** + * 停止定时任务 + * @return 定时任务是否成功关闭:true,已关闭;false:关闭失败 + * 可通过调用{#link status()}方法查看定时任务当前状态 + * @throws SchedulerException 异常 + */ + public boolean stop() throws SchedulerException { + if (scheduler != null) { + scheduler.shutdown(); + return true; + } + return false; + } + + /** + * 暂停所有定时任务 + * @return true:成功;false:失败 + * @throws SchedulerException 异常 + */ + public boolean pauseAll() throws SchedulerException { + if (scheduler != null) { + scheduler.pauseAll(); + return true; + } + return false; + } + + /** + * 根据JobKey暂停定时任务 + * @return true:成功;false:失败 + * @throws SchedulerException 异常 + */ + public boolean pauseByJobKey(JobKey jobKey) throws SchedulerException { + if (scheduler != null) { + scheduler.pauseJob(jobKey); + return true; + } + return false; + } + + /** + * 根据JobKeys暂停定时任务 + * @return true:成功;false:失败 + * @throws SchedulerException 异常 + */ + public boolean pauseByJobKeys(GroupMatcher jobKeys) throws SchedulerException { + if (scheduler != null) { + scheduler.pauseJobs(jobKeys); + return true; + } + return false; + } + + /** + * 根据TriggerKey暂停定时任务 + * @return true:成功;false:失败 + * @throws SchedulerException 异常 + */ + public boolean pauseByTriggerKey(TriggerKey triggerKey) throws SchedulerException { + if (scheduler != null) { + scheduler.pauseTrigger(triggerKey); + return true; + } + return false; + } + + /** + * 根据TriggerKeys暂停定时任务 + * @return true:成功;false:失败 + * @throws SchedulerException 异常 + */ + public boolean pauseByTriggerKeys(GroupMatcher triggerKeys) throws SchedulerException { + if (scheduler != null) { + scheduler.pauseTriggers(triggerKeys); + return true; + } + return false; + } + + //-------------------------------------------------------private method test + + /** + * 获取 JobDetail 对象 + * @param scheduleBean + * @return + */ + private JobDetail getJobDetail(ScheduleBean scheduleBean) { + return newJob(scheduleBean.getClazz()) + .withIdentity(scheduleBean.getJobName(), + scheduleBean.getJobGroup()) + .build(); + } + + /** + * 将参数封装到JobDetail对象中 + * @param obj jobDetail + * @param paramMap + */ + private void paramJob(JobDetail obj, Map paramMap) { + if (paramMap != null && !paramMap.isEmpty()) { + Set keys = paramMap.keySet(); + for (String key : keys) { + obj.getJobDataMap().put(key, paramMap.get(key)); + } + } + } + + /** + * 将参数封装到Trigger对象中 + * @param obj trigger + * @param paramMap + */ + private void paramTrigger(Trigger obj, Map paramMap) { + if (paramMap != null && !paramMap.isEmpty()) { + Set keys = paramMap.keySet(); + for (String key : keys) { + obj.getJobDataMap().put(key, paramMap.get(key)); + } + } + } + + /** + * 获取trigger(simpleSchedule) + * @param scheduleBean + * @return + */ + private Trigger getTriggerSimple(ScheduleBean scheduleBean) { + return newTrigger() + .withIdentity(scheduleBean.getTriggerName(), scheduleBean.getTriggerGroup()) + .startNow() + + .withSchedule(simpleSchedule() // simple + .withIntervalInSeconds(scheduleBean.getTime()) // 秒钟 + .repeatForever() // 重复 + ) + .build(); + } + + /** + * 获取trigger(atTime) + * @param scheduleBean + * @return + */ + private Trigger getTriggerAtTime(ScheduleBean scheduleBean) { + return newTrigger() + .withIdentity(scheduleBean.getTriggerName(), + scheduleBean.getTriggerGroup()) + .startAt(new Date(scheduleBean.getAtTime())) + .build(); + } + + /** + * 获取trigger(cron 表达式) + * @param scheduleBean + * @return + */ + private Trigger getTriggerCron(ScheduleBean scheduleBean) { + CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleBean.getCron()); + return newTrigger() + .withIdentity(scheduleBean.getTriggerName(), + scheduleBean.getTriggerGroup()) + .withSchedule(scheduleBuilder) + .build(); + } + + /** + * 通过策略获取Trigger + * + * 策略: + * 如果你没有指定,则看你传的参数 + * cron->atTime->simple + * 检查顺序如上,后者会覆盖前者 + * 简言之, 执行顺序:simple > atTime > cron + * + * 如果你指定了类型,那么就按你指定的类型进行封装 + * 如果你指定的类型没有值,依旧采用上面的策略进行处理 + * @param scheduleBean + * @return + */ + private Trigger getTrigger(ScheduleBean scheduleBean) { + Trigger trigger = null; + + // cron + String cron = scheduleBean.getCron(); + if (null != cron + && !"".equals(cron.trim()) + && cron.length() > 0) + trigger = getTriggerCron(scheduleBean); + + // at time + Long atTime = scheduleBean.getAtTime(); + if (null != atTime && atTime > 0) + trigger = getTriggerAtTime(scheduleBean); + + // simple + Integer time = scheduleBean.getTime(); + if (null != time && time > 0) + trigger = getTriggerSimple(scheduleBean); + + // 下而上覆盖 + + return trigger; + } + + /** + * 通过策略获取Trigger + * @param scheduleBean + * @return + */ + private Trigger getTriggerBySimple(ScheduleBean scheduleBean) { + return getTrigger(scheduleBean); + } + + /** + * 通过策略获取Trigger + * @param scheduleBean + * @return + */ + private Trigger getTriggerByAtTime(ScheduleBean scheduleBean) { + Trigger trigger = null; + + // cron + String cron = scheduleBean.getCron(); + if (null != cron + && !"".equals(cron.trim()) + && cron.length() > 0) + trigger = getTriggerCron(scheduleBean); + + // simple + Integer time = scheduleBean.getTime(); + if (null != time && time > 0) + trigger = getTriggerSimple(scheduleBean); + + // at time + Long atTime = scheduleBean.getAtTime(); + if (null != atTime && atTime > 0) + trigger = getTriggerAtTime(scheduleBean); + + // 下而上覆盖 + + return trigger; + } + + /** + * 通过策略获取Trigger + * @param scheduleBean + * @return + */ + private Trigger getTriggerByCron(ScheduleBean scheduleBean) { + Trigger trigger = null; + + // at time + Long atTime = scheduleBean.getAtTime(); + if (null != atTime && atTime > 0) + trigger = getTriggerAtTime(scheduleBean); + + // simple + Integer time = scheduleBean.getTime(); + if (null != time && time > 0) + trigger = getTriggerSimple(scheduleBean); + + // cron + String cron = scheduleBean.getCron(); + if (null != cron + && !"".equals(cron.trim()) + && cron.length() > 0) + trigger = getTriggerCron(scheduleBean); + + // 下而上覆盖 + + return trigger; + } + + //-------------------------------------------------------private method end +} diff --git a/admin-console/src/main/java/com/ibeetl/admin/quartz/service/TimeTypeEnum.java b/admin-console/src/main/java/com/ibeetl/admin/quartz/service/TimeTypeEnum.java new file mode 100644 index 0000000000000000000000000000000000000000..d06d870eba23f8c2247ac908e965dfdc2466edc7 --- /dev/null +++ b/admin-console/src/main/java/com/ibeetl/admin/quartz/service/TimeTypeEnum.java @@ -0,0 +1,51 @@ +package com.ibeetl.admin.quartz.service; + + +/** + * 定时任务执行类型(枚举) + * @author Wenyi Feng + */ +public enum TimeTypeEnum { + + /** 简单的定时任务(循环)*/ + SIMPLE(1, "simpleSchedule"), + + /** 指定一个时间点执行(毫秒数[Long]) */ + AT_TIME(2, "at time"), + + /** 使用cron表达式(时间点、循环、自定义时间) */ + CRON(3, "cron expression") + ; + + /** 代码 */ + private Integer code; + + /** 描述 */ + private String msg; + + /** + * 通过构造方法初始化 + * @param code 代码 + * @param msg 描述 + */ + TimeTypeEnum(Integer code, String msg) { + this.code = code; + this.msg = msg; + } + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } +} diff --git a/admin-console/src/main/java/com/ibeetl/admin/quartz/service/TimetaskService.java b/admin-console/src/main/java/com/ibeetl/admin/quartz/service/TimetaskService.java new file mode 100644 index 0000000000000000000000000000000000000000..cd6a180ea322a09abe99aefae30971c91e292c78 --- /dev/null +++ b/admin-console/src/main/java/com/ibeetl/admin/quartz/service/TimetaskService.java @@ -0,0 +1,44 @@ +package com.ibeetl.admin.quartz.service; + +import java.util.List; + +import org.beetl.sql.core.engine.PageQuery; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.ibeetl.admin.core.util.PlatformException; + +import com.ibeetl.admin.quartz.dao.TimetaskDao; +import com.ibeetl.admin.quartz.entity.Timetask; +import com.ibeetl.admin.core.service.BaseService; + +/** + * Timetask Service + */ + +@Service +@Transactional +public class TimetaskService extends BaseService{ + + @Autowired + private TimetaskDao timetaskDao; + + public PageQueryqueryByCondition(PageQuery query){ + PageQuery ret = timetaskDao.queryByCondition(query); + queryListAfter(ret.getList()); + return ret; + } + + public void batchDelTimetask(List ids){ + try { + timetaskDao.batchDelTimetaskByIds(ids); + } catch (Exception e) { + throw new PlatformException("批量删除Timetask失败", e); + } + } + + public List queryList(){ + return timetaskDao.queryList(); + } +} \ No newline at end of file diff --git a/admin-console/src/main/java/com/ibeetl/admin/quartz/test/testJob.java b/admin-console/src/main/java/com/ibeetl/admin/quartz/test/testJob.java new file mode 100644 index 0000000000000000000000000000000000000000..48686085dce39fa89cd23d2896c1f459e092891f --- /dev/null +++ b/admin-console/src/main/java/com/ibeetl/admin/quartz/test/testJob.java @@ -0,0 +1,17 @@ +package com.ibeetl.admin.quartz.test; + +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.springframework.scheduling.quartz.QuartzJobBean; + +import java.util.Date; + +/** + * @author Wenyi Feng + */ +public class testJob extends QuartzJobBean { + @Override + protected void executeInternal(JobExecutionContext context) throws JobExecutionException { + System.out.println("定时任务testjob1正在运行 : " + new Date()); + } +} diff --git a/admin-console/src/main/java/com/ibeetl/admin/quartz/test/testJob2.java b/admin-console/src/main/java/com/ibeetl/admin/quartz/test/testJob2.java new file mode 100644 index 0000000000000000000000000000000000000000..d82e83f16592789acb61d1155ccb0059ecf435ca --- /dev/null +++ b/admin-console/src/main/java/com/ibeetl/admin/quartz/test/testJob2.java @@ -0,0 +1,17 @@ +package com.ibeetl.admin.quartz.test; + +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.springframework.scheduling.quartz.QuartzJobBean; + +import java.util.Date; + +/** + * @author Wenyi Feng + */ +public class testJob2 extends QuartzJobBean { + @Override + protected void executeInternal(JobExecutionContext context) throws JobExecutionException { + System.out.println("定时任务testjob2正在运行 : " + new Date()); + } +} diff --git a/admin-console/src/main/java/com/ibeetl/admin/quartz/web/TimetaskController.java b/admin-console/src/main/java/com/ibeetl/admin/quartz/web/TimetaskController.java new file mode 100644 index 0000000000000000000000000000000000000000..63afd6b055c623b40fed5460835d9c6344e6e09c --- /dev/null +++ b/admin-console/src/main/java/com/ibeetl/admin/quartz/web/TimetaskController.java @@ -0,0 +1,202 @@ +package com.ibeetl.admin.quartz.web; + +import java.util.Date; +import java.util.List; +import cn.hutool.core.util.StrUtil; +import com.ibeetl.admin.core.service.CorePlatformService; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.beetl.sql.core.engine.PageQuery; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; + +import com.ibeetl.admin.core.annotation.Function; +import com.ibeetl.admin.core.file.FileService; +import com.ibeetl.admin.core.web.JsonResult; +import com.ibeetl.admin.core.util.*; +import com.ibeetl.admin.quartz.entity.*; +import com.ibeetl.admin.quartz.service.*; +import com.ibeetl.admin.quartz.web.query.*; + +/** + * Timetask 接口 + */ +@Controller +public class TimetaskController{ + + private final Log log = LogFactory.getLog(this.getClass()); + private static final String MODEL = "/quartz/timetask"; + + private static final long IS_EFFECT_N = 0; + private static final long IS_EFFECT_Y = 1; + private static final long IS_START_N = 0; + private static final long IS_START_Y = 1; + + @Autowired + private TimetaskService timetaskService; + + @Autowired + FileService fileService; + + @Autowired + private Scheduler scheduler; + + @Autowired + private QuartzTask quartztask; + + @Autowired + DynamicTask dynamicTask; + + @Autowired + CorePlatformService platformService; + + /* 页面 */ + + @GetMapping(MODEL + "/index.do") + @Function("quartz.timetask.query") + @ResponseBody + public ModelAndView index() { + ModelAndView view = new ModelAndView("/quartz/timetask/index.html") ; + view.addObject("search", TimetaskQuery.class.getName()); + return view; + } + + @GetMapping(MODEL + "/edit.do") + @Function("quartz.timetask.edit") + @ResponseBody + public ModelAndView edit(String id) { + ModelAndView view = new ModelAndView("/quartz/timetask/edit.html"); + Timetask timetask = timetaskService.queryById(id); + view.addObject("timetask", timetask); + return view; + } + + @GetMapping(MODEL + "/add.do") + @Function("quartz.timetask.add") + @ResponseBody + public ModelAndView add() { + ModelAndView view = new ModelAndView("/quartz/timetask/add.html"); + return view; + } + + /* ajax json */ + + @PostMapping(MODEL + "/list.json") + @Function("quartz.timetask.query") + @ResponseBody + public JsonResult list(TimetaskQuery condtion){ + PageQuery page = condtion.getPageQuery(); + timetaskService.queryByCondition(page); + return JsonResult.success(page); + } + + @PostMapping(MODEL + "/add.json") + @Function("quartz.timetask.add") + @ResponseBody + public JsonResult add(@Validated(ValidateConfig.ADD.class)Timetask timetask){ + timetask.setCreateBy(platformService.getCurrentUser().getId().toString()); + timetask.setCreateName(platformService.getCurrentUser().getName()); + timetask.setCreateDate(new Date()); + timetask.setIsEffect(IS_EFFECT_Y); + timetask.setIsStart(IS_START_N); + timetaskService.save(timetask); + return new JsonResult().success(); + } + + @PostMapping(MODEL + "/update.json") + @Function("quartz.timetask.update") + @ResponseBody + public JsonResult update(@Validated(ValidateConfig.UPDATE.class) Timetask timetask) { + timetask.setUpdateBy(platformService.getCurrentUser().getId().toString()); + timetask.setUpdateName(platformService.getCurrentUser().getName()); + timetask.setUpdateDate(new Date()); + boolean success = timetaskService.update(timetask); + if (success) { + return new JsonResult().success(); + } else { + return JsonResult.failMessage("保存失败"); + } + } + + + @GetMapping(MODEL + "/view.json") + @Function("quartz.timetask.query") + @ResponseBody + public JsonResultqueryInfo(String id) { + Timetask timetask = timetaskService.queryById( id); + return JsonResult.success(timetask); + } + + @PostMapping(MODEL + "/delete.json") + @Function("quartz.timetask.delete") + @ResponseBody + public JsonResult delete(String ids) { + if (ids.endsWith(",")) { + ids = StringUtils.substringBeforeLast(ids, ","); + } + List idList = ConvertUtil.str2list(ids); + timetaskService.batchDelTimetask(idList); + return new JsonResult().success(); + } + + @PostMapping(MODEL + "/start.json") + @Function("quartz.timetask.start") + @ResponseBody + public JsonResult jobStart(String id) { + Timetask timetask = timetaskService.queryById(id); + if(IS_EFFECT_Y==timetask.getIsEffect()){ + boolean rs = false; + try { + rs = dynamicTask.startOrStop(timetask,true); + if(rs){ + timetask.setIsStart(IS_START_Y); + timetaskService.update(timetask); + return new JsonResult().success(); + }else{ + System.out.println("任务ID:" + timetask.getTaskId() +"在"+new Date()+ "启动失败! "); + return JsonResult.failMessage("启动失败!"); + } + } catch (Exception e) { + e.printStackTrace(); + return JsonResult.failMessage("异常错误!"); + } + }else{ + return JsonResult.failMessage("任务没有生效!"); + } + + } + + @PostMapping(MODEL + "/stop.json") + @Function("quartz.timetask.stop") + @ResponseBody + public JsonResult jobStop(String id) { + Timetask timetask = timetaskService.queryById(id); + if(IS_EFFECT_Y==timetask.getIsEffect()&&IS_START_Y==timetask.getIsStart()){ + boolean rs = false; + try { + rs = dynamicTask.startOrStop(timetask,false); + if(rs){ + timetask.setIsStart(IS_START_N); + timetaskService.update(timetask); + return new JsonResult().success(); + }else{ + System.out.println("任务ID:" + timetask.getTaskId() +"在"+new Date()+ "暂停失败! "); + return JsonResult.failMessage("启动失败!"); + } + } catch (Exception e) { + e.printStackTrace(); + return JsonResult.failMessage("异常错误!"); + } + }else{ + return JsonResult.failMessage("该任务没有运行,请检查!"); + } + + } + +} diff --git a/admin-console/src/main/java/com/ibeetl/admin/quartz/web/query/TimetaskQuery.java b/admin-console/src/main/java/com/ibeetl/admin/quartz/web/query/TimetaskQuery.java new file mode 100644 index 0000000000000000000000000000000000000000..109627c960305233d663c38ff9f2b8e3bd782e1e --- /dev/null +++ b/admin-console/src/main/java/com/ibeetl/admin/quartz/web/query/TimetaskQuery.java @@ -0,0 +1,52 @@ +package com.ibeetl.admin.quartz.web.query; + +import com.ibeetl.admin.core.annotation.Query; +import com.ibeetl.admin.core.util.enums.CoreDictType; +import com.ibeetl.admin.core.web.query.PageParam; +import java.util.Date; +/** + *Timetask查询 + */ +public class TimetaskQuery extends PageParam { + @Query(name = "是否生效", display = true) + private Long isEffect; + @Query(name = "是否运行", display = true) + private Long isStart; + @Query(name = "任务描述", display = true) + private String taskDescribe; + @Query(name = "任务ID", display = true) + private String taskId; + @Query(name = "任务类名", display = true) + private String className; + public Long getIsEffect(){ + return isEffect; + } + public void setIsEffect(Long isEffect ){ + this.isEffect = isEffect; + } + public Long getIsStart(){ + return isStart; + } + public void setIsStart(Long isStart ){ + this.isStart = isStart; + } + public String getTaskDescribe(){ + return taskDescribe; + } + public void setTaskDescribe(String taskDescribe ){ + this.taskDescribe = taskDescribe; + } + public String getTaskId(){ + return taskId; + } + public void setTaskId(String taskId ){ + this.taskId = taskId; + } + public String getClassName(){ + return className; + } + public void setClassName(String className ){ + this.className = className; + } + +} diff --git a/admin-console/src/main/resources/application.properties b/admin-console/src/main/resources/application.properties index 01a4f1a4358468c111a795448f50a9aed79b0324..fa4bf773cd263a1b818c887a33ba7fa90cdcd440 100644 --- a/admin-console/src/main/resources/application.properties +++ b/admin-console/src/main/resources/application.properties @@ -1,41 +1,52 @@ -spring.datasource.url=jdbc:mysql://127.0.0.1:3306/starter?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false -spring.datasource.username=root -spring.datasource.password=123456 -spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +spring.datasource.url=jdbc:oracle:thin:@192.168.112.198:1521:xe +spring.datasource.username=springboot +spring.datasource.password=springboot +spring.datasource.driver-class-name=oracle.jdbc.OracleDriver +beetlsql.ds.dataSource.dbStyle=org.beetl.sql.core.db.OracleStyle +## 最小空闲连接数量 +spring.datasource.minimumIdle=2 +## 空闲连接存活最大时间,默认600000(10分钟) +spring.datasource.idle-timeout=180000 +## 连接池最大连接数,默认是10 +spring.datasource.maximumPoolSize=5 +## 数据库连接超时时间,默认30秒,即30000 +spring.datasource.connection-timeout=30000 + + +spring.datasource.cas.url=jdbc:oracle:thin:@192.168.112.180:1521:orcl +spring.datasource.cas.username=idc_u_uniauth +spring.datasource.cas.password=kingstar +spring.datasource.cas.driver-class-name=oracle.jdbc.OracleDriver -#spring.datasource.url=jdbc:oracle:thin:@127.0.0.1:1521:orcl -#spring.datasource.username=starter2 -#spring.datasource.password=starter2 -#spring.datasource.driver-class-name=oracle.jdbc.OracleDriver beetlsql.ds.dataSource.basePackage=com -beetlsql.ds.dataSource.dbStyle=org.beetl.sql.core.db.MySqlStyle #有一个数据源命名为dataSource beetlsql.mutiple.datasource=dataSource -# 1,1 是管理员密码,相当于启动后就登录,方便测试,系统需要取消这俩个配置 -user.id=1 -user.orgId=1 #打开审计功能,开发模式应该关闭 audit.enable=false #单机情况下使用hashmap存放回话,集群下可以参考springboot 使用redis -spring.session.store-type=HASH_MAP +spring.session.store-type=NONE #spring.cache.type= spring.cache.type=SIMPLE logging.level.root=info logging.level.org.springframework.web.servlet.mvc.method.annotation=warn #logging.file = my.log -server.port=8080 +server.port=9101 #html视图交给beetl渲染 -beetl.suffix=html -beetlsql.dataSource.dbStyle=org.beetl.sql.core.db.MySqlStyle -#beetlsql.basePackage=com.ibeetl,com.xxx.yourpackage +beetl.suffix=html +beetlsql.dataSource.dbStyle=org.beetl.sql.core.db.OracleStyle beetlsql.basePackage=com app.name=SpringBoot-Plus logging.pattern.console=%-4relative [%thread] %-5level %logger{256} %M %L - %msg%n -spring.devtools.restart.exclude=static/**,templates/** -#文档预览服务的调用地址,参考https://gitee.com/kekingcn/file-online-preview 安装,没有如下配置无法使用预览功能 -file.previewURL=http://localhost:8012/onlinePreview +spring.devtools.restart.exclude=templates/** + +#swagger开关 +swagger.show=true +swagger.scanPackage=com.ibeetl.admin.console.web +#cas配置 +cas.enableCas=false +cas.casBasePath=http://cas.newcapec.cn/cas diff --git a/admin-console/src/main/resources/sql/console/function.md b/admin-console/src/main/resources/sql/console/function.md index e0d46cbe1a5ba6396436764c02ff1bd1ce93fef3..7303e7b430b5a2f6c707d5764eea7c2253bade6f 100644 --- a/admin-console/src/main/resources/sql/console/function.md +++ b/admin-console/src/main/resources/sql/console/function.md @@ -20,8 +20,9 @@ queryByCondtion @} @if(!isEmpty(parentFunctionId)){ and f.parent_id = #parentFunctionId# + @} + @pageIgnoreTag(){ + order by f.create_time desc ,id @} - @pageIgnoreTag(){ - order by id - @} + diff --git a/admin-console/src/main/resources/sql/console/menu.md b/admin-console/src/main/resources/sql/console/menu.md index 26b6f8a649512885398996f79a85adecd85f0c50..f2c802d298aa0215a40e03fbc614ca1c0b34e77c 100644 --- a/admin-console/src/main/resources/sql/console/menu.md +++ b/admin-console/src/main/resources/sql/console/menu.md @@ -27,7 +27,7 @@ queryByCondtion @} @pageIgnoreTag(){ - order by m.id + order by m.seq , m.id @} diff --git a/admin-console/src/main/resources/sql/console/role.md b/admin-console/src/main/resources/sql/console/role.md index 647841089db36889da56868fb4d62793fde93857..4b84c9e178625480401377df2a2d9510eee53529 100644 --- a/admin-console/src/main/resources/sql/console/role.md +++ b/admin-console/src/main/resources/sql/console/role.md @@ -49,19 +49,19 @@ batchDelByIds * 批量删除角色,同时也参考batchDeleteRoleFunction,batchDeleteRoleMenu等方法删除其他关联数据 - delete from core_role where id in( #join(ids)#); + delete from core_role where id in( #join(ids)#) batchDeleteRoleFunction === - delete from core_role_function where role_id in( #join(ids)#); + delete from core_role_function where role_id in( #join(ids)#) batchDeleteRoleMenu === - delete from core_role_menu where role_id in( #join(ids)#); + delete from core_role_menu where role_id in( #join(ids)#) batchDeleteUserRole === - delete from core_user_role where role_id in( #join(ids)#); + delete from core_user_role where role_id in( #join(ids)#) queryAllByDelflag diff --git a/admin-console/src/main/resources/sql/console/user.md b/admin-console/src/main/resources/sql/console/user.md index 8137df5150694d5d2fee5bdb04d86abbf494aacf..9178107f7ed97be00038bfc7b85e83a98e238ace 100644 --- a/admin-console/src/main/resources/sql/console/user.md +++ b/admin-console/src/main/resources/sql/console/user.md @@ -27,9 +27,7 @@ queryByCondtion @if(!isEmpty(jobType0)){ and u.job_type0= #jobType0# @} - @if(!isEmpty(jobType1)){ - and u.job_type1= #jobType1# - @} + @if(!isEmpty(createDateMin)){ and u.create_time>= #createDateMin# @} diff --git a/admin-console/src/main/resources/sql/quartz/timetask.md b/admin-console/src/main/resources/sql/quartz/timetask.md new file mode 100644 index 0000000000000000000000000000000000000000..356c94b2c623b96dcd610a84e9836f58d225c6d9 --- /dev/null +++ b/admin-console/src/main/resources/sql/quartz/timetask.md @@ -0,0 +1,41 @@ +queryByCondition +=== + + + select + @pageTag(){ + t.* + @} + from timetask t + where + @//数据权限,该sql语句功能点 + #function("timetask.query")# + @if(!isEmpty(isEffect)){ + and t.IS_EFFECT =#isEffect# + @} + @if(!isEmpty(isStart)){ + and t.IS_START =#isStart# + @} + @if(!isEmpty(taskDescribe)){ + and t.TASK_DESCRIBE =#taskDescribe# + @} + @if(!isEmpty(taskId)){ + and t.TASK_ID =#taskId# + @} + @if(!isEmpty(className)){ + and t.CLASS_NAME =#className# + @} + + + + +batchDelTimetaskByIds +=== + +* 批量逻辑删除 + + delete from timetask where ID in( #join(ids)#) + +queryList +=== + select * from timetask diff --git a/admin-console/src/main/resources/static/js/admin/function/add.js b/admin-console/src/main/resources/static/js/admin/function/add.js index 032e8fa3a0fd7cf5b5b301071a7f8c8a0ee00c4c..cc496edd5382922817c33357e50956f83e97f056 100644 --- a/admin-console/src/main/resources/static/js/admin/function/add.js +++ b/admin-console/src/main/resources/static/js/admin/function/add.js @@ -11,10 +11,11 @@ layui.define([ 'form', 'laydate', 'table','functionApi'], function(exports) { $("#saveFunction").click(function(){ form.on('submit(form)', function(){ functionApi.addFunction(function(){ + parent.window.dataReload(); Common.info("添加成功"); Lib.closeFrame(); }); - parent.window.dataReload(); + //parent.window.dataReload(); }); }); diff --git a/admin-console/src/main/resources/static/js/admin/function/edit.js b/admin-console/src/main/resources/static/js/admin/function/edit.js index 0704b80d596ddd2fc003b3a0245dd9f2de7b35f6..eba1e8e18266df7eba045b3b4cd5021c8e9e4799 100644 --- a/admin-console/src/main/resources/static/js/admin/function/edit.js +++ b/admin-console/src/main/resources/static/js/admin/function/edit.js @@ -11,10 +11,11 @@ layui.define([ 'form', 'laydate', 'table','functionApi'], function(exports) { $("#saveFunction").click(function(){ form.on('submit(form)', function(){ functionApi.updateFunction(function(){ + parent.window.dataReload(); Common.info("更新成功"); Lib.closeFrame(); }); - parent.window.dataReload(); + //parent.window.dataReload(); }); }); diff --git a/admin-console/src/main/resources/static/js/admin/menu/add.js b/admin-console/src/main/resources/static/js/admin/menu/add.js index fa76eddf964af9be6f916c5d3a44bdc897627261..8d7d27cabba1eaeb9533f0553b28d334c9f053a2 100644 --- a/admin-console/src/main/resources/static/js/admin/menu/add.js +++ b/admin-console/src/main/resources/static/js/admin/menu/add.js @@ -1,27 +1,44 @@ -layui.define([ 'form', 'laydate', 'table','menuApi'], function(exports) { +layui.define([ 'form', 'laydate', 'table','menuApi','iconPicker'], function(exports) { var form = layui.form; var menuApi = layui.menuApi; var index = layui.index; + var iconPicker = layui.iconPicker; var view = { init:function(){ Lib.initGenrealForm($("#addForm"),form); + this.initIcon(); this.initSubmit(); $('#parentMenuId').val(0); $('#seq').val(1); }, + initIcon:function () { + + iconPicker.render({ + // 选择器,推荐使用input + elem: '#iconPicker', + // 数据类型:fontClass/unicode,推荐使用fontClass + type: 'fontClass', + // 是否开启搜索:true/false + search: true, + // 点击回调 + click: function (data) { + console.log(data); + } + }); + }, initSubmit:function(){ $("#saveMenu").click(function(){ //默认值 if(!$('#parentMenuId').val()){ $('#parentMenuId').val(0); } - - menuApi.addMenu(function(){ - Common.info("添加成功"); - parent.window.dataReload(); - Lib.closeFrame(); - }); - + form.on('submit(form)', function(){ + menuApi.addMenu(function(){ + Common.info("添加成功"); + parent.window.dataReload(); + Lib.closeFrame(); + }); + }); }); diff --git a/admin-console/src/main/resources/static/js/admin/menu/edit.js b/admin-console/src/main/resources/static/js/admin/menu/edit.js index ddbb72e142db61d2a5f9ee621537a8b38657c3ed..b71be2d23cab54ee9227bc85aade00b38a25446c 100644 --- a/admin-console/src/main/resources/static/js/admin/menu/edit.js +++ b/admin-console/src/main/resources/static/js/admin/menu/edit.js @@ -13,14 +13,13 @@ layui.define([ 'form', 'laydate', 'table','menuApi'], function(exports) { if(!$('#parentMenuId').val()){ $('#parentMenuId').val(0); } - - menuApi.updateMenu(function(){ - Common.info("更新成功"); - Lib.closeFrame(); - parent.window.dataReload(); - }); - - + form.on('submit(form)', function(){ + menuApi.updateMenu(function(){ + Common.info("更新成功"); + Lib.closeFrame(); + parent.window.dataReload(); + }); + }); }); $("#saveMenu-cancel").click(function(){ diff --git a/admin-console/src/main/resources/static/js/admin/menu/iconPicker.js b/admin-console/src/main/resources/static/js/admin/menu/iconPicker.js new file mode 100644 index 0000000000000000000000000000000000000000..276e7fd3b4fb256aa2e217df3c97f39cbda748f7 --- /dev/null +++ b/admin-console/src/main/resources/static/js/admin/menu/iconPicker.js @@ -0,0 +1,327 @@ + +layui.define(['laypage', 'form'], function (exports) { + "use strict"; + + var IconPicker =function () { + this.v = '0.1.beta'; + }, _MOD = 'iconPicker', + _this = this, + $ = layui.jquery, + laypage = layui.laypage, + form = layui.form, + BODY = 'body', + TIPS = '请选择图标'; + + /** + * 渲染组件 + */ + IconPicker.prototype.render = function(options){ + var opts = options, + // DOM选择器 + elem = opts.elem, + // 数据类型:fontClass/unicode + type = opts.type == null ? 'fontClass' : opts.type, + // 是否分页:true/false + page = opts.page, + // 每页显示数量 + limit = limit == null ? 12 : opts.limit, + // 是否开启搜索:true/false + search = opts.search == null ? true : opts.search, + // 点击回调 + click = opts.click, + // json数据 + data = {}, + // 唯一标识 + tmp = new Date().getTime(), + // 是否使用的class数据 + isFontClass = opts.type === 'fontClass', + TITLE = 'layui-select-title', + TITLE_ID = 'layui-select-title-' + tmp, + ICON_BODY = 'layui-iconpicker-' + tmp, + PICKER_BODY = 'layui-iconpicker-body-' + tmp, + PAGE_ID = 'layui-iconpicker-page-' + tmp, + LIST_BOX = 'layui-iconpicker-list-box', + selected = 'layui-form-selected', + unselect = 'layui-unselect'; + + var a = { + init: function () { + data = common.getData[type](); + + a.hideElem().createSelect().createBody().toggleSelect(); + common.loadCss(); + return a; + }, + /** + * 隐藏elem + */ + hideElem: function () { + $(elem).hide(); + return a; + }, + /** + * 绘制select下拉选择框 + */ + createSelect: function () { + var selectHtml = '
' + + '
' + + '
'+ + '' + + '' + + ''+ + '' + + '
'+ + '
' + + '
' + + '123' + + '
'; + $(elem).after(selectHtml); + return a; + }, + /** + * 展开/折叠下拉框 + */ + toggleSelect: function () { + var item = '#' + TITLE_ID + ' .layui-iconpicker-item,#' + TITLE_ID + ' .layui-iconpicker-item .layui-edge'; + a.event('click', item, function (e) { + console.log('xxxx'); + var $icon = $('#' + ICON_BODY); + if ($icon.hasClass(selected)) { + $icon.removeClass(selected).addClass(unselect); + } else { + $icon.addClass(selected).removeClass(unselect); + } + e.stopPropagation(); + }); + return a; + }, + /** + * 绘制主体部分 + */ + createBody: function () { + // 获取数据 + var searchHtml = ''; + + if (search) { + searchHtml = ''; + } + + // 组合dom + var bodyHtml = '
' + + searchHtml + + '
'+ + '
'; + $('#' + ICON_BODY).find('.layui-anim').eq(0).html(bodyHtml); + a.search().createList().check().page(); + + return a; + }, + /** + * 绘制图标列表 + * @param text 模糊查询关键字 + * @returns {string} + */ + createList: function (text) { + var d = data, + l = d.length, + pageHtml = '', + listHtml = $('
')//'
'; + + // 计算分页数据 + var _limit = limit, // 每页显示数量 + _pages = l % _limit === 0 ? l / _limit : parseInt(l / _limit + 1), // 总计多少页 + _id = PAGE_ID; + + // 图标列表 + var icons = []; + + for (var i = 0; i < l; i++) { + var obj = d[i]; + + // 判断是否模糊查询 + if (text && obj.indexOf(text) === -1) { + continue; + } + + // 每个图标dom + var icon = '
'; + if (isFontClass){ + icon += ''; + } else { + icon += ''+ obj.replace('amp;', '') +''; + } + icon += '
'; + + icons.push(icon); + } + + // 查询出图标后再分页 + l = icons.length; + _pages = l % _limit === 0 ? l / _limit : parseInt(l / _limit + 1); + for (var i = 0; i < _pages; i++) { + // 按limit分块 + var lm = $('
'); + + for (var j = i * _limit; j < (i+1) * _limit && j < l; j++) { + lm.append(icons[j]); + } + + listHtml.append(lm); + } + + // 无数据 + if (l === 0) { + listHtml.append('

无数据

'); + } + + // 判断是否分页 + if (page){ + $('#' + PICKER_BODY).addClass('layui-iconpicker-body-page'); + pageHtml = '
' + + '
' + + '1/' + + ''+ _pages +'' + + ' ('+ l +')' + + '
' + + '
' + + ' ' + + ' ' + + '
' + + '
'; + } + + + $('#' + ICON_BODY).find('.layui-anim').find('.' + LIST_BOX).html('').append(listHtml).append(pageHtml); + return a; + }, + // 分页 + page: function () { + var icon = '#' + PAGE_ID + ' .layui-iconpicker-page-operate .layui-icon'; + + $(icon).unbind('click'); + a.event('click', icon, function (e) { + var elem = e.currentTarget, + total = parseInt($('#' +PAGE_ID + '-pages').html()), + isPrev = $(elem).attr('prev') !== undefined, + // 按钮上标的页码 + index = parseInt($(elem).attr('data-index')), + $cur = $('#' +PAGE_ID + '-current'), + // 点击时正在显示的页码 + current = parseInt($cur.html()); + + // 分页数据 + if (isPrev && current > 1) { + current=current-1; + $(icon + '[prev]').attr('data-index', current); + } else if (!isPrev && current < total){ + current=current+1; + $(icon + '[next]').attr('data-index', current); + } + $cur.html(current); + + // 图标数据 + $('.layui-iconpicker-icon-limit').hide(); + $('#layui-iconpicker-icon-limit-' + current).show(); + e.stopPropagation(); + }); + return a; + }, + /** + * 搜索 + */ + search: function () { + var item = '#' + PICKER_BODY + ' .layui-iconpicker-search .layui-input'; + a.event('input propertychange', item, function (e) { + var elem = e.target, + t = $(elem).val(); + a.createList(t); + }); + a.event('click', item, function (e) { + e.stopPropagation(); + }); + return a; + }, + /** + * 点击选中图标 + */ + check: function () { + var item = '#' + PICKER_BODY + ' .layui-iconpicker-icon-item'; + a.event('click', item, function (e) { + var el = $(e.currentTarget).find('.layui-icon'), + icon = ''; + if (isFontClass) { + var clsArr = el.attr('class').split(/[\s\n]/), + cls = clsArr[1], + icon = cls; + $('#' + TITLE_ID).find('.layui-iconpicker-item .layui-icon').html('').attr('class', clsArr.join(' ')); + } else { + var cls = el.html(), + icon = cls; + $('#' + TITLE_ID).find('.layui-iconpicker-item .layui-icon').html(icon); + } + + $('#' + ICON_BODY).removeClass(selected).addClass(unselect); + $(elem).attr('value', icon); + // 回调 + if (click) { + click({ + icon: icon + }); + } + + }); + return a; + }, + event: function (evt, el, fn) { + $(BODY).on(evt, el, fn); + } + }; + + var common = { + /** + * 加载样式表 + */ + loadCss: function () { + var css = '.layui-iconpicker {max-width: 280px;}.layui-iconpicker .layui-anim{display:none;position:absolute;left:0;top:42px;padding:5px 0;z-index:899;min-width:100%;border:1px solid #d2d2d2;max-height:300px;overflow-y:auto;background-color:#fff;border-radius:2px;box-shadow:0 2px 4px rgba(0,0,0,.12);box-sizing:border-box;}.layui-iconpicker-item{border:1px solid #e6e6e6;width:90px;height:38px;border-radius:4px;cursor:pointer;position:relative;}.layui-iconpicker-icon{border-right:1px solid #e6e6e6;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;width:60px;height:100%;float:left;text-align:center;background:#fff;transition:all .3s;}.layui-iconpicker-icon i{line-height:38px;font-size:18px;}.layui-iconpicker-item > .layui-edge{left:70px;}.layui-iconpicker-item:hover{border-color:#D2D2D2!important;}.layui-iconpicker-item:hover .layui-iconpicker-icon{border-color:#D2D2D2!important;}.layui-iconpicker.layui-form-selected .layui-anim{display:block;}.layui-iconpicker-body{padding:6px;}.layui-iconpicker .layui-iconpicker-list{background-color:#fff;border:1px solid #ccc;border-radius:4px;}.layui-iconpicker .layui-iconpicker-icon-item{display:inline-block;width:21.1%;line-height:36px;text-align:center;cursor:pointer;vertical-align:top;height:36px;margin:4px;border:1px solid #ddd;border-radius:2px;transition:300ms;}.layui-iconpicker .layui-iconpicker-icon-item i.layui-icon{font-size:17px;}.layui-iconpicker .layui-iconpicker-icon-item:hover{background-color:#eee;border-color:#ccc;-webkit-box-shadow:0 0 2px #aaa,0 0 2px #fff inset;-moz-box-shadow:0 0 2px #aaa,0 0 2px #fff inset;box-shadow:0 0 2px #aaa,0 0 2px #fff inset;text-shadow:0 0 1px #fff;}.layui-iconpicker-search{position:relative;margin:0 0 6px 0;border:1px solid #e6e6e6;border-radius:2px;transition:300ms;}.layui-iconpicker-search:hover{border-color:#D2D2D2!important;}.layui-iconpicker-search .layui-input{cursor:text;display:inline-block;width:86%;border:none;padding-right:0;margin-top:1px;}.layui-iconpicker-search .layui-icon{position:absolute;top:11px;right:4%;}.layui-iconpicker-tips{text-align:center;padding:8px 0;cursor:not-allowed;}.layui-iconpicker-page{margin-top:6px;margin-bottom:-6px;font-size:12px;padding:0 2px;}.layui-iconpicker-page-count{display:inline-block;}.layui-iconpicker-page-operate{display:inline-block;float:right;cursor:default;}.layui-iconpicker-page-operate .layui-icon{font-size:12px;cursor:pointer;}.layui-iconpicker-body-page .layui-iconpicker-icon-limit{display:none;}.layui-iconpicker-body-page .layui-iconpicker-icon-limit:first-child{display:block;}'; + $('head').append(''); + }, + /** + * 获取数据 + */ + getData: { + fontClass: function () { + var arr = ["layui-icon-rate-half","layui-icon-rate","layui-icon-rate-solid","layui-icon-cellphone","layui-icon-vercode","layui-icon-login-wechat","layui-icon-login-qq","layui-icon-login-weibo","layui-icon-password","layui-icon-username","layui-icon-refresh-3","layui-icon-auz","layui-icon-spread-left","layui-icon-shrink-right","layui-icon-snowflake","layui-icon-tips","layui-icon-note","layui-icon-home","layui-icon-senior","layui-icon-refresh","layui-icon-refresh-1","layui-icon-flag","layui-icon-theme","layui-icon-notice","layui-icon-website","layui-icon-console","layui-icon-face-surprised","layui-icon-set","layui-icon-template-1","layui-icon-app","layui-icon-template","layui-icon-praise","layui-icon-tread","layui-icon-male","layui-icon-female","layui-icon-camera","layui-icon-camera-fill","layui-icon-more","layui-icon-more-vertical","layui-icon-rmb","layui-icon-dollar","layui-icon-diamond","layui-icon-fire","layui-icon-return","layui-icon-location","layui-icon-read","layui-icon-survey","layui-icon-face-smile","layui-icon-face-cry","layui-icon-cart-simple","layui-icon-cart","layui-icon-next","layui-icon-prev","layui-icon-upload-drag","layui-icon-upload","layui-icon-download-circle","layui-icon-component","layui-icon-file-b","layui-icon-user","layui-icon-find-fill","layui-icon-loading","layui-icon-loading-1","layui-icon-add-1","layui-icon-play","layui-icon-pause","layui-icon-headset","layui-icon-video","layui-icon-voice","layui-icon-speaker","layui-icon-fonts-del","layui-icon-fonts-code","layui-icon-fonts-html","layui-icon-fonts-strong","layui-icon-unlink","layui-icon-picture","layui-icon-link","layui-icon-face-smile-b","layui-icon-align-left","layui-icon-align-right","layui-icon-align-center","layui-icon-fonts-u","layui-icon-fonts-i","layui-icon-tabs","layui-icon-radio","layui-icon-circle","layui-icon-edit","layui-icon-share","layui-icon-delete","layui-icon-form","layui-icon-cellphone-fine","layui-icon-dialogue","layui-icon-fonts-clear","layui-icon-layer","layui-icon-date","layui-icon-water","layui-icon-code-circle","layui-icon-carousel","layui-icon-prev-circle","layui-icon-layouts","layui-icon-util","layui-icon-templeate-1","layui-icon-upload-circle","layui-icon-tree","layui-icon-table","layui-icon-chart","layui-icon-chart-screen","layui-icon-engine","layui-icon-triangle-d","layui-icon-triangle-r","layui-icon-file","layui-icon-set-sm","layui-icon-add-circle","layui-icon-404","layui-icon-about","layui-icon-up","layui-icon-down","layui-icon-left","layui-icon-right","layui-icon-circle-dot","layui-icon-search","layui-icon-set-fill","layui-icon-group","layui-icon-friends","layui-icon-reply-fill","layui-icon-menu-fill","layui-icon-log","layui-icon-picture-fine","layui-icon-face-smile-fine","layui-icon-list","layui-icon-release","layui-icon-ok","layui-icon-help","layui-icon-chat","layui-icon-top","layui-icon-star","layui-icon-star-fill","layui-icon-close-fill","layui-icon-close","layui-icon-ok-circle","layui-icon-add-circle-fine"]; + return arr; + }, + unicode: function () { + return ["&#xe6c9;","&#xe67b;","&#xe67a;","&#xe678;","&#xe679;","&#xe677;","&#xe676;","&#xe675;","&#xe673;","&#xe66f;","&#xe9aa;","&#xe672;","&#xe66b;","&#xe668;","&#xe6b1;","&#xe702;","&#xe66e;","&#xe68e;","&#xe674;","&#xe669;","&#xe666;","&#xe66c;","&#xe66a;","&#xe667;","&#xe7ae;","&#xe665;","&#xe664;","&#xe716;","&#xe656;","&#xe653;","&#xe663;","&#xe6c6;","&#xe6c5;","&#xe662;","&#xe661;","&#xe660;","&#xe65d;","&#xe65f;","&#xe671;","&#xe65e;","&#xe659;","&#xe735;","&#xe756;","&#xe65c;","&#xe715;","&#xe705;","&#xe6b2;","&#xe6af;","&#xe69c;","&#xe698;","&#xe657;","&#xe65b;","&#xe65a;","&#xe681;","&#xe67c;","&#xe601;","&#xe857;","&#xe655;","&#xe770;","&#xe670;","&#xe63d;","&#xe63e;","&#xe654;","&#xe652;","&#xe651;","&#xe6fc;","&#xe6ed;","&#xe688;","&#xe645;","&#xe64f;","&#xe64e;","&#xe64b;","&#xe62b;","&#xe64d;","&#xe64a;","&#xe64c;","&#xe650;","&#xe649;","&#xe648;","&#xe647;","&#xe646;","&#xe644;","&#xe62a;","&#xe643;","&#xe63f;","&#xe642;","&#xe641;","&#xe640;","&#xe63c;","&#xe63b;","&#xe63a;","&#xe639;","&#xe638;","&#xe637;","&#xe636;","&#xe635;","&#xe634;","&#xe633;","&#xe632;","&#xe631;","&#xe630;","&#xe62f;","&#xe62e;","&#xe62d;","&#xe62c;","&#xe629;","&#xe628;","&#xe625;","&#xe623;","&#xe621;","&#xe620;","&#xe61f;","&#xe61c;","&#xe60b;","&#xe619;","&#xe61a;","&#xe603;","&#xe602;","&#xe617;","&#xe615;","&#xe614;","&#xe613;","&#xe612;","&#xe611;","&#xe60f;","&#xe60e;","&#xe60d;","&#xe60c;","&#xe60a;","&#xe609;","&#xe605;","&#xe607;","&#xe606;","&#xe604;","&#xe600;","&#xe658;","&#x1007;","&#x1006;","&#x1005;","&#xe608;"]; + } + } + }; + + a.init(); + return new IconPicker(); + }; + + /** + * 选中图标 + * @param filter lay-filter + * @param iconName 图标名称,自动识别fontClass/unicode + */ + IconPicker.prototype.checkIcon = function (filter, iconName){ + var p = $('*[lay-filter='+ filter +']').next().find('.layui-iconpicker-item .layui-icon'), + c = iconName; + + if (c.indexOf('#xe') > 0){ + p.html(c); + } else { + p.html('').attr('class', 'layui-icon ' + c); + } + }; + + var iconPicker = new IconPicker(); + exports(_MOD, iconPicker); +}); \ No newline at end of file diff --git a/admin-console/src/main/resources/static/js/admin/menu/index.js b/admin-console/src/main/resources/static/js/admin/menu/index.js index dd5c0f3c2e0014e3e4047bcb595077663ce27cfd..f834a7f426305125b58e84280b54a84b108e4f3a 100644 --- a/admin-console/src/main/resources/static/js/admin/menu/index.js +++ b/admin-console/src/main/resources/static/js/admin/menu/index.js @@ -18,7 +18,7 @@ layui.define([ 'form', 'laydate', 'table' ], function(exports) { initTable:function(){ menuTable = table.render({ elem : '#menuTable', - height : 'full-280', + height : 'full-250', method : 'post', url : Common.ctxPath + '/admin/menu/list.json' //数据接口 ,page : {"layout":['count','prev', 'page', 'next']} //开启分页 diff --git a/admin-console/src/main/resources/static/js/admin/user/changePassword.js b/admin-console/src/main/resources/static/js/admin/user/changePassword.js index 55a799954a174a2afd0ced4a093ac072c5751736..5914879f4a8c886083d5999a8e1ad7a45259f7e2 100644 --- a/admin-console/src/main/resources/static/js/admin/user/changePassword.js +++ b/admin-console/src/main/resources/static/js/admin/user/changePassword.js @@ -9,6 +9,20 @@ layui.define([ 'form', 'table','userApi'], function(exports) { }, initSubmit:function(){ $("#savePassword").click(function(){ + var password = $("#password").val(); + if(password==""){ + Common.info("密码不能为空"); + return false; + } + var password2 = $("#password2").val(); + if(password2==""){ + Common.info("确认密码不能为空"); + return false; + } + if(password!=password2){ + Common.info("密码和确认密码不一致"); + return false; + } userApi.changePassword($('#changePasswordForm'),function(){ Common.info("密码更改成功"); Lib.closeFrame(); diff --git a/admin-console/src/main/resources/static/js/admin/user/index.js b/admin-console/src/main/resources/static/js/admin/user/index.js index d3e9769a8b85f9ef37724ee09d8fd9b7843b457b..f833b0937f14d44f5ee967bd863e8bbe15f6b339 100644 --- a/admin-console/src/main/resources/static/js/admin/user/index.js +++ b/admin-console/src/main/resources/static/js/admin/user/index.js @@ -61,12 +61,7 @@ layui.define([ 'form', 'laydate', 'table','userApi' ], function(exports) { width : 120, sort : true }, - { - field : 'jobType1Text', - title : '职位明细', - width : 80, - sort : true - }, + { field : 'createTime', title : '创建时间', diff --git a/admin-console/src/main/resources/static/js/quartz/timetask/add.js b/admin-console/src/main/resources/static/js/quartz/timetask/add.js new file mode 100644 index 0000000000000000000000000000000000000000..f383e398dd738045715d9746e41c58dd62541f5e --- /dev/null +++ b/admin-console/src/main/resources/static/js/quartz/timetask/add.js @@ -0,0 +1,28 @@ +layui.define([ 'form', 'laydate', 'table','timetaskApi'], function(exports) { + var form = layui.form; + var timetaskApi = layui.timetaskApi; + var index = layui.index; + var view = { + init:function(){ + Lib.initGenrealForm($("#addForm"),form); + this.initSubmit(); + }, + initSubmit:function(){ + $("#addButton").click(function(){ + form.on('submit(form)', function(){ + timetaskApi.addTimetask($('#addForm'),function(){ + parent.window.dataReload(); + Common.info("添加成功"); + Lib.closeFrame(); + }); + }); + }); + + $("#addButton-cancel").click(function(){ + Lib.closeFrame(); + }); + } + + } + exports('add',view); +}); \ No newline at end of file diff --git a/admin-console/src/main/resources/static/js/quartz/timetask/del.js b/admin-console/src/main/resources/static/js/quartz/timetask/del.js new file mode 100644 index 0000000000000000000000000000000000000000..a6d44a7f635a614d35a48c57cfc9fb149439667d --- /dev/null +++ b/admin-console/src/main/resources/static/js/quartz/timetask/del.js @@ -0,0 +1,23 @@ +layui.define(['table', 'timetaskApi'], function(exports) { + var timetaskApi = layui.timetaskApi; + var table=layui.table; + var view = { + init:function(){ + }, + delBatch:function(){ + var data = Common.getMoreDataFromTable(table,"timetaskTable"); + if(data==null){ + return ; + } + Common.openConfirm("确认要删除这些Timetask?",function(){ + var ids =Common.concatBatchId(data,"id"); + timetaskApi.del(ids,function(){ + Common.info("删除成功"); + dataReload(); + }) + }) + } + } + exports('del',view); + +}); \ No newline at end of file diff --git a/admin-console/src/main/resources/static/js/quartz/timetask/edit.js b/admin-console/src/main/resources/static/js/quartz/timetask/edit.js new file mode 100644 index 0000000000000000000000000000000000000000..35b7fad2dcb643bf99f50428354179cf73f62806 --- /dev/null +++ b/admin-console/src/main/resources/static/js/quartz/timetask/edit.js @@ -0,0 +1,28 @@ +layui.define([ 'form', 'laydate', 'table','timetaskApi'], function(exports) { + var form = layui.form; + var timetaskApi = layui.timetaskApi; + var index = layui.index; + var view = { + init:function(){ + Lib.initGenrealForm($("#updateForm"),form); + this.initSubmit(); + }, + initSubmit:function(){ + $("#updateButton").click(function(){ + form.on('submit(form)', function(){ + timetaskApi.updateTimetask($('#updateForm'),function(){ + parent.window.dataReload(); + Common.info("更新成功"); + Lib.closeFrame(); + }); + }); + }); + $("#updateButton-cancel").click(function(){ + Lib.closeFrame(); + }); + } + + } + exports('edit',view); + +}); \ No newline at end of file diff --git a/admin-console/src/main/resources/static/js/quartz/timetask/index.js b/admin-console/src/main/resources/static/js/quartz/timetask/index.js new file mode 100644 index 0000000000000000000000000000000000000000..fc3a2fd8cf9e906351c02fb16dfbaaa40157893c --- /dev/null +++ b/admin-console/src/main/resources/static/js/quartz/timetask/index.js @@ -0,0 +1,146 @@ +layui.define([ 'form', 'laydate', 'table' ], function(exports) { + var form = layui.form; + var laydate = layui.laydate; + var table = layui.table; + var timetaskTable = null; + var view ={ + init:function(){ + this.initTable(); + this.initSearchForm(); + this.initToolBar(); + window.dataReload = function(){ + Lib.doSearchForm($("#searchForm"),timetaskTable) + } + }, + initTable:function(){ + timetaskTable = table.render({ + elem : '#timetaskTable', + height : Lib.getTableHeight(1), + cellMinWidth: 100, + method : 'post', + url : Common.ctxPath + '/quartz/timetask/list.json' // 数据接口 + ,page : Lib.tablePage // 开启分页 + ,limit : 10, + cols : [ [ // 表头 + { + type : 'checkbox', + fixed:'left', + }, + { + + field : 'taskId', + title : '任务ID', + width: 100, + }, + { + + field : 'className', + title : '任务类名', + }, + { + + field : 'cronExpression', + title : 'cron表达式', + }, + { + + field : 'taskDescribe', + title : '任务描述', + }, + + { + field : 'runServerIp', + title : '服务器', + width: 100, + }, + { + field : 'runServer', + title : '远程主机', + width: 100, + }, + { + field : 'isEffect', + title : '是否生效', + width: 100, + templet: '#isEffect', + }, + { + field : 'isStart', + title : '运行状态', + width: 100, + templet: '#isStart', + }, + {title : '操作',fixed: 'right', width: 165, align:'center', toolbar: '#barDemo'} + + ] ] + + }); + + table.on('checkbox(timetaskTable)', function(obj){ + var timetask = obj.data; + if(obj.checked){ + //按钮逻辑Lib.buttonEnable() + }else{ + + } + }); + + table.on('tool(timetaskTable)', function (obj) { //注:tool 是工具条事件名,test 是 table 原始容器的属性 lay-filter="对应的值" + var data = obj.data //获得当前行数据 + , layEvent = obj.event; //获得 lay-event 对应的值 + if (layEvent === 'detail') { + layer.msg('查看操作'); + } else if (layEvent === 'start') { + Common.openConfirm("确认要启动此任务?",function(){ + Common.post("/quartz/timetask/start.json",{"id":data.id},function(){ + Common.info("任务启动成功"); + dataReload(); + }) + + }); + } else if (layEvent === 'stop') { + Common.openConfirm("确认要暂停此任务?",function(){ + Common.post("/quartz/timetask/stop.json",{"id":data.id},function(){ + Common.info("任务暂停成功"); + dataReload(); + }) + + }) + } + }); + + }, + + initSearchForm:function(){ + Lib.initSearchForm( $("#searchForm"),timetaskTable,form); + }, + initToolBar:function(){ + toolbar = { + add : function() { // 获取选中数据 + var url = "/quartz/timetask/add.do"; + Common.openMinDlg(url,"定时任务管理>新增"); + }, + edit : function() { // 获取选中数目 + var data = Common.getOneFromTable(table,"timetaskTable"); + if(data==null){ + return ; + } + var url = "/quartz/timetask/edit.do?id="+data.id; + Common.openMinDlg(url,"定时任务管理>编辑"); + }, + del : function() { + layui.use(['del'], function(){ + var delView = layui.del + delView.delBatch(); + }); + } + }; + $('.ext-toolbar').on('click', function() { + var type = $(this).data('type'); + toolbar[type] ? toolbar[type].call(this) : ''; + }); + } + } + exports('index',view); + +}); \ No newline at end of file diff --git a/admin-console/src/main/resources/static/js/quartz/timetask/timetaskApi.js b/admin-console/src/main/resources/static/js/quartz/timetask/timetaskApi.js new file mode 100644 index 0000000000000000000000000000000000000000..cee7733fb045e20a734fcd3e171b48212c36119e --- /dev/null +++ b/admin-console/src/main/resources/static/js/quartz/timetask/timetaskApi.js @@ -0,0 +1,18 @@ +/*访问后台的代码*/ +layui.define([], function(exports) { + var api={ + updateTimetask:function(form,callback){ + Lib.submitForm("/quartz/timetask/update.json",form,{},callback) + }, + addTimetask:function(form,callback){ + Lib.submitForm("/quartz/timetask/add.json",form,{},callback) + }, + del:function(ids,callback){ + Common.post("/quartz/timetask/delete.json",{"ids":ids},function(){ + callback(); + }) + } + + }; + exports('timetaskApi',api); +}); \ No newline at end of file diff --git a/admin-console/src/main/resources/templates/admin/menu/add.html b/admin-console/src/main/resources/templates/admin/menu/add.html index 89ecb492ecbe684cc3d500bd805c47006a50f36e..106ce98040084c76e41f81c43253b7b41a8d4a04 100644 --- a/admin-console/src/main/resources/templates/admin/menu/add.html +++ b/admin-console/src/main/resources/templates/admin/menu/add.html @@ -5,8 +5,8 @@
- +
@@ -37,10 +37,11 @@
-
- + +
@@ -58,7 +59,7 @@
-
@@ -78,3 +79,4 @@ layui.use(['add'], function(){ + diff --git a/admin-console/src/main/resources/templates/admin/menu/edit.html b/admin-console/src/main/resources/templates/admin/menu/edit.html index 7b787773d0c69fd1a4e4fad194bc3a3b09a1031c..042e3bfec4f0e0df778cc4aa6d400e66549606b6 100644 --- a/admin-console/src/main/resources/templates/admin/menu/edit.html +++ b/admin-console/src/main/resources/templates/admin/menu/edit.html @@ -5,7 +5,7 @@
-
@@ -38,7 +38,7 @@
-
@@ -58,7 +58,7 @@
-
diff --git a/admin-console/src/main/resources/templates/admin/user/add.html b/admin-console/src/main/resources/templates/admin/user/add.html index f1475b31d728ebe3d631927293b84354ba77da9d..d82ada4303295fd15d942ea1a04ab5bf0982b2fd 100644 --- a/admin-console/src/main/resources/templates/admin/user/add.html +++ b/admin-console/src/main/resources/templates/admin/user/add.html @@ -1,7 +1,9 @@ -
+ +
@@ -19,6 +21,16 @@
+
+
+ +
+ +
+
+
@@ -29,20 +41,19 @@
+
+
-
- - -
+
+ + +
-
-
-
@@ -52,15 +63,6 @@
- -
-
- - -
-
-
diff --git a/admin-console/src/main/resources/templates/admin/user/changePassword.html b/admin-console/src/main/resources/templates/admin/user/changePassword.html index 286b278bd5d960160acc9059d696976dabe7174e..329ab66f777e2efc3d513b572f798b0cdb3f6b27 100644 --- a/admin-console/src/main/resources/templates/admin/user/changePassword.html +++ b/admin-console/src/main/resources/templates/admin/user/changePassword.html @@ -23,14 +23,14 @@
-
-
diff --git a/admin-console/src/main/resources/templates/admin/user/edit.html b/admin-console/src/main/resources/templates/admin/user/edit.html index 3fa3a33c4616a3e1a8ebf7417e2e74c81a427918..3c6df8f1aa38546b69b4bb4232f88bed2a6684e9 100644 --- a/admin-console/src/main/resources/templates/admin/user/edit.html +++ b/admin-console/src/main/resources/templates/admin/user/edit.html @@ -29,17 +29,17 @@
+
+
-
- - -
+
+ + +
-
-
@@ -53,14 +53,6 @@
-
-
- - -
-
-
diff --git a/admin-console/src/main/resources/templates/quartz/timetask/add.html b/admin-console/src/main/resources/templates/quartz/timetask/add.html new file mode 100644 index 0000000000000000000000000000000000000000..6063de5b0358d5e6275a327e1adcc1c0f70dd3e6 --- /dev/null +++ b/admin-console/src/main/resources/templates/quartz/timetask/add.html @@ -0,0 +1,78 @@ + + + +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ + +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ + + + + diff --git a/admin-console/src/main/resources/templates/quartz/timetask/edit.html b/admin-console/src/main/resources/templates/quartz/timetask/edit.html new file mode 100644 index 0000000000000000000000000000000000000000..b4d6ec15bf9e0134c0f94556146b20d0a4d587f0 --- /dev/null +++ b/admin-console/src/main/resources/templates/quartz/timetask/edit.html @@ -0,0 +1,82 @@ + + +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ + + + + + + diff --git a/admin-console/src/main/resources/templates/quartz/timetask/index.html b/admin-console/src/main/resources/templates/quartz/timetask/index.html new file mode 100644 index 0000000000000000000000000000000000000000..82c06a530498623a18933155a532194223ed1949 --- /dev/null +++ b/admin-console/src/main/resources/templates/quartz/timetask/index.html @@ -0,0 +1,41 @@ + + + +
+ 增加 + 编辑 + + + 删除 +
+ +
+ + + + + diff --git a/admin-console/src/test/java/Demo.java b/admin-console/src/test/java/Demo.java new file mode 100644 index 0000000000000000000000000000000000000000..f4e16ca7a5a512d2f41e95e51e3fd9c2801f928a --- /dev/null +++ b/admin-console/src/test/java/Demo.java @@ -0,0 +1,14 @@ +import cn.hutool.core.codec.Base64; + +public class Demo { + + public static void main(String[] args) { + String a = "系统注册过期,请联系管理员"; + String b = "2018-09-30"; + System.out.println(Base64.encode(Base64.encode(a)).replaceAll("=", "")); + System.out.println(Base64.encode(Base64.encode(b)).replaceAll("=", "")); + + System.out.println(Base64.decodeStr(Base64.decodeStr("TWpBeE9DMHdPQzB6TVE9PQ"))); + } + +} diff --git a/admin-core/pom.xml b/admin-core/pom.xml index 7fbef3b68daf5dceaa6ac816137a9a5441bb1544..297a356cac08e265800b50435bd17fb976817d44 100644 --- a/admin-core/pom.xml +++ b/admin-core/pom.xml @@ -1,103 +1,163 @@ - - 4.0.0 - admin-core - jar - - com.ibeetl - admin - ${plus.version} - ../pom.xml - - - true - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-tomcat - - - - org.springframework.boot - spring-boot-starter-jdbc - - - org.springframework.boot - spring-boot-starter-aop - - - - org.springframework.boot - spring-boot-starter-cache - - - org.springframework.boot - spring-boot-starter-data-redis - - - - - com.ibeetl - beetl-framework-starter - 1.1.68.RELEASE - - - - com.zaxxer - HikariCP - - - mysql - mysql-connector-java - 6.0.5 - - - - - org.jxls - jxls-reader - 2.0.3 - - - - org.jxls - jxls - 2.4.3 - - - org.jxls - jxls-poi - 1.0.14 - - - org.apache.commons - commons-lang3 - 3.3.2 - - - - org.apache.poi - poi - 3.17 - - - org.apache.poi - poi-ooxml - 3.17 - - - - - - - - + + 4.0.0 + admin-core + jar + + com.ibeetl + admin + ${plus.version} + ../pom.xml + + + true + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-tomcat + + + + org.springframework.boot + spring-boot-starter-jdbc + + + org.springframework.boot + spring-boot-starter-aop + + + + org.springframework.boot + spring-boot-starter-cache + + + org.springframework.boot + spring-boot-starter-data-redis + + + org.springframework.boot + spring-boot-configuration-processor + + + + com.ibeetl + beetl-framework-starter + 1.1.59.RELEASE + + + + com.zaxxer + HikariCP + + + + com.oracle + ojdbc6 + 11.2.0 + + + org.jxls + jxls-reader + 2.0.3 + + + + org.jxls + jxls + 2.4.3 + + + org.jxls + jxls-poi + 1.0.14 + + + org.apache.commons + commons-lang3 + + + + org.apache.poi + poi + 3.17 + + + org.apache.poi + poi-ooxml + 3.17 + + + + cn.hutool + hutool-all + 4.1.3 + + + + + com.baomidou + kaptcha-spring-boot-starter + 1.1.0 + + + + com.bstek.ureport + ureport2-console + 2.2.9 + + + + + io.springfox + springfox-swagger2 + 2.9.2 + + + + io.springfox + springfox-swagger-ui + 2.9.2 + + + com.github.xiaoymin + swagger-bootstrap-ui + 1.6 + + + + org.springframework.boot + spring-boot-starter-quartz + + + + + + com.github.binarywang + weixin-java-cp + 3.2.0 + + + + com.github.binarywang + weixin-java-mp + 3.2.0 + + + + com.github.binarywang + weixin-java-pay + 3.2.0 + + + + com.github.binarywang + weixin-java-miniapp + 3.2.0 + + + diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/conf/BeetlConf.java b/admin-core/src/main/java/com/ibeetl/admin/core/conf/BeetlConf.java index 3c19f7b376a5ec10e3942cfb219babbca8ca45e8..28dc6d871d4880c44dae61195810edf818fbab6d 100644 --- a/admin-core/src/main/java/com/ibeetl/admin/core/conf/BeetlConf.java +++ b/admin-core/src/main/java/com/ibeetl/admin/core/conf/BeetlConf.java @@ -1,182 +1,195 @@ -package com.ibeetl.admin.core.conf; - -import java.io.UnsupportedEncodingException; -import java.util.List; - -import javax.servlet.http.HttpServletRequest; - -import org.beetl.core.Context; -import org.beetl.core.Function; -import org.beetl.core.GroupTemplate; -import org.beetl.ext.simulate.WebSimulate; -import org.beetl.sql.core.InterceptorContext; -import org.beetl.sql.ext.DebugInterceptor; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.env.Environment; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.ibeetl.admin.core.rbac.DataAccess; -import com.ibeetl.admin.core.rbac.DataAccessFactory; -import com.ibeetl.admin.core.service.CorePlatformService; -import com.ibeetl.admin.core.util.beetl.DictQueryFunction; -import com.ibeetl.admin.core.util.beetl.FileFunction; -import com.ibeetl.admin.core.util.beetl.FunAccessUrlFunction; -import com.ibeetl.admin.core.util.beetl.FunFunction; -import com.ibeetl.admin.core.util.beetl.MenuFunction; -import com.ibeetl.admin.core.util.beetl.OrgFunction; -import com.ibeetl.admin.core.util.beetl.RoleFunction; -import com.ibeetl.admin.core.util.beetl.SearchCondtionFunction; -import com.ibeetl.admin.core.util.beetl.SysFunctionTreeFunction; -import com.ibeetl.admin.core.util.beetl.UUIDFunction; -import com.ibeetl.admin.core.util.beetl.XXSDefenderFormat; -import com.ibeetl.admin.core.web.query.QueryParser; -import com.ibeetl.starter.BeetlTemplateCustomize; -import com.ibeetl.starter.ObjectMapperJsonUtil; - -@Configuration -@AutoConfigureAfter(JasonConfig.class) -public class BeetlConf { - @Autowired - Environment env; - @Autowired - CorePlatformService platFormService; - - @Autowired - OrgFunction orgFunction; - - @Autowired - SysFunctionTreeFunction sysFunctionTreeFunction; - - @Autowired - DictQueryFunction dictDownQueryFunction; - - - - @Autowired - RoleFunction roleFunction; - @Autowired - FileFunction fileFunction; - - @Autowired - SearchCondtionFunction searchCondtionFunction; - - @Autowired - DataAccessFactory dataAccessFactory; - - @Autowired - ApplicationContext applicationContext; - - @Autowired - FunFunction funFunction; - - @Autowired - FunAccessUrlFunction funAccessUrlFunction; - - @Autowired - MenuFunction menuFunction; - - @Bean - public WebSimulate getWebSimulate(GroupTemplate gt, ObjectMapper objectMapper) { - return new WebSimulate(gt, new ObjectMapperJsonUtil(objectMapper)) { - protected String getRenderPath(HttpServletRequest request) { - String defaultRenderPath = request.getServletPath(); - return defaultRenderPath.replace(".do", ".html"); - } - }; - } - - @Bean - public BeetlTemplateCustomize beetlTemplateCustomize() { - return new BeetlTemplateCustomize() { - public void customize(GroupTemplate groupTemplate) { - groupTemplate.registerFunctionPackage("platform", platFormService); - groupTemplate.registerFunctionPackage("queryCondtion", new QueryParser()); - groupTemplate.registerFunction("core.orgName", orgFunction); - groupTemplate.registerFunction("core.functionName", funFunction); - groupTemplate.registerFunction("core.funAccessUrl", funAccessUrlFunction); - groupTemplate.registerFunction("core.menuName", menuFunction); - groupTemplate.registerFunction("core.searchCondtion", searchCondtionFunction); - groupTemplate.registerFunction("core.roles", roleFunction); - groupTemplate.registerFunction("core.file", fileFunction); - groupTemplate.registerFormat("xss", new XXSDefenderFormat()); - groupTemplate.registerFunction("uuid", new UUIDFunction()); - groupTemplate.registerFunctionPackage("dict", dictDownQueryFunction); - // 模板页面判断是否有按钮权限,比如canAccess - groupTemplate.registerFunction("canAccess", new Function() { - - @Override - public Boolean call(Object[] paras, Context ctx) { - Long userId = platFormService.getCurrentUser().getId(); - Long orgId = platFormService.getCurrentOrgId(); - String functionCode = (String) paras[0]; - return platFormService.canAcessFunction(userId, orgId, functionCode); - } - - }); - - groupTemplate.registerFunction("abcd", new Function() { - - @Override - public Boolean call(Object[] paras, Context ctx) { - return true; - } - - }); - - groupTemplate.registerFunction("env", new Function() { - - @Override - public String call(Object[] paras, Context ctx) { - String key = (String)paras[0]; - String value = env.getProperty(key); - if(value!=null) { - return getStr(value); - } - if(paras.length==2) { - return (String)paras[1]; - } - return null; - } - - protected String getStr(String str) { - try { - return new String(str.getBytes("iso8859-1"),"UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - } - - }); - - groupTemplate.registerFunction("dataAccessList", new Function() { - - @Override - public List call(Object[] paras, Context ctx) { - return dataAccessFactory.all(); - } - - }); - - } - }; - } - - static class StarterDebugInterceptor extends DebugInterceptor { - protected boolean isSimple(String sqlId) { - if (sqlId.indexOf("_gen_") != -1) { - return true; - } else { - return false; - } - } - - protected void simpleOut(InterceptorContext ctx) { - return; - } - } - -} +package com.ibeetl.admin.core.conf; + +import java.io.UnsupportedEncodingException; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; + +import org.beetl.core.Context; +import org.beetl.core.Function; +import org.beetl.core.GroupTemplate; +import org.beetl.ext.simulate.WebSimulate; +import org.beetl.ext.spring.BeetlSpringViewResolver; +import org.beetl.sql.core.InterceptorContext; +import org.beetl.sql.ext.DebugInterceptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.ibeetl.admin.core.rbac.DataAccess; +import com.ibeetl.admin.core.rbac.DataAccessFactory; +import com.ibeetl.admin.core.service.CorePlatformService; +import com.ibeetl.admin.core.util.beetl.CategoryDictFunction; +import com.ibeetl.admin.core.util.beetl.DictQueryFunction; +import com.ibeetl.admin.core.util.beetl.FileFunction; +import com.ibeetl.admin.core.util.beetl.FunAccessUrlFunction; +import com.ibeetl.admin.core.util.beetl.FunFunction; +import com.ibeetl.admin.core.util.beetl.MenuFunction; +import com.ibeetl.admin.core.util.beetl.OrgFunction; +import com.ibeetl.admin.core.util.beetl.RoleFunction; +import com.ibeetl.admin.core.util.beetl.SearchCondtionFunction; +import com.ibeetl.admin.core.util.beetl.SysFunctionTreeFunction; +import com.ibeetl.admin.core.util.beetl.UUIDFunction; +import com.ibeetl.admin.core.util.beetl.XXSDefenderFormat; +import com.ibeetl.admin.core.web.query.QueryParser; +import com.ibeetl.starter.BeetlTemplateCustomize; +import com.ibeetl.starter.ObjectMapperJsonUtil; + +@Configuration +@AutoConfigureAfter(JasonConfig.class) +public class BeetlConf { + @Autowired + Environment env; + @Autowired + CorePlatformService platFormService; + + @Autowired + OrgFunction orgFunction; + + @Autowired + SysFunctionTreeFunction sysFunctionTreeFunction; + + @Autowired + DictQueryFunction dictDownQueryFunction; + + + + @Autowired + RoleFunction roleFunction; + @Autowired + FileFunction fileFunction; + + @Autowired + SearchCondtionFunction searchCondtionFunction; + + @Autowired + DataAccessFactory dataAccessFactory; + + @Autowired + ApplicationContext applicationContext; + + @Autowired + FunFunction funFunction; + + @Autowired + FunAccessUrlFunction funAccessUrlFunction; + + @Autowired + MenuFunction menuFunction; + + @Autowired + CategoryDictFunction catrgoryDictFunction; + + @Bean + public WebSimulate getWebSimulate(GroupTemplate gt, ObjectMapper objectMapper) { + return new WebSimulate(gt, new ObjectMapperJsonUtil(objectMapper)) { + protected String getRenderPath(HttpServletRequest request) { + String defaultRenderPath = request.getServletPath(); + return defaultRenderPath.replace(".do", ".html"); + } + }; + } + + @Bean + public BeetlTemplateCustomize beetlTemplateCustomize() { + return new BeetlTemplateCustomize() { + public void customize(GroupTemplate groupTemplate) { + groupTemplate.registerFunctionPackage("platform", platFormService); + groupTemplate.registerFunctionPackage("queryCondtion", new QueryParser()); + groupTemplate.registerFunction("core.orgName", orgFunction); + groupTemplate.registerFunction("core.functionName", funFunction); + groupTemplate.registerFunction("core.funAccessUrl", funAccessUrlFunction); + groupTemplate.registerFunction("core.menuName", menuFunction); + groupTemplate.registerFunction("core.searchCondtion", searchCondtionFunction); + groupTemplate.registerFunction("core.roles", roleFunction); + groupTemplate.registerFunction("core.file", fileFunction); + groupTemplate.registerFormat("xss", new XXSDefenderFormat()); + groupTemplate.registerFunction("uuid", new UUIDFunction()); + groupTemplate.registerFunctionPackage("dict", dictDownQueryFunction); + groupTemplate.registerFunctionPackage("dictitem", catrgoryDictFunction); + // 模板页面判断是否有按钮权限,比如canAccess + groupTemplate.registerFunction("canAccess", new Function() { + + @Override + public Boolean call(Object[] paras, Context ctx) { + Long userId = platFormService.getCurrentUser().getId(); + Long orgId = platFormService.getCurrentOrgId(); + String functionCode = (String) paras[0]; + return platFormService.canAcessFunction(userId, orgId, functionCode); + } + + }); + + groupTemplate.registerFunction("abcd", new Function() { + + @Override + public Boolean call(Object[] paras, Context ctx) { + return true; + } + + }); + + groupTemplate.registerFunction("env", new Function() { + + @Override + public String call(Object[] paras, Context ctx) { + String key = (String)paras[0]; + String value = env.getProperty(key); + if(value!=null) { + return getStr(value); + } + if(paras.length==2) { + return (String)paras[1]; + } + return null; + } + + protected String getStr(String str) { + try { + return new String(str.getBytes("iso8859-1"),"UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + }); + + groupTemplate.registerFunction("dataAccessList", new Function() { + + @Override + public List call(Object[] paras, Context ctx) { + return dataAccessFactory.all(); + } + + }); + + } + }; + } + + static class StarterDebugInterceptor extends DebugInterceptor { + protected boolean isSimple(String sqlId) { + if (sqlId.indexOf("_gen_") != -1) { + return true; + } else { + return false; + } + } + + protected void simpleOut(InterceptorContext ctx) { + return; + } + } + + @Bean(name = "beetlViewResolver") + public BeetlSpringViewResolver getBeetlSpringViewResolver() { + BeetlSpringViewResolver beetlSpringViewResolver = new BeetlSpringViewResolver(); + beetlSpringViewResolver.setContentType("text/html;charset=UTF-8"); + beetlSpringViewResolver.setOrder(0); + return beetlSpringViewResolver; + } +} diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/conf/DataSourceConfig.java b/admin-core/src/main/java/com/ibeetl/admin/core/conf/DataSourceConfig.java index 626970571a6dde899ac5e2902d898c611b21ea3b..50267861fc90c373c56e26fd8d8e3f9a0f93391f 100644 --- a/admin-core/src/main/java/com/ibeetl/admin/core/conf/DataSourceConfig.java +++ b/admin-core/src/main/java/com/ibeetl/admin/core/conf/DataSourceConfig.java @@ -2,6 +2,7 @@ package com.ibeetl.admin.core.conf; import javax.sql.DataSource; +import cn.hutool.core.convert.Convert; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; @@ -16,8 +17,26 @@ public class DataSourceConfig { ds.setUsername(env.getProperty("spring.datasource.username")); ds.setPassword(env.getProperty("spring.datasource.password")); ds.setDriverClassName(env.getProperty("spring.datasource.driver-class-name")); + ds.setMinimumIdle(Convert.toInt(env.getProperty("spring.datasource.minimumIdle"))); + ds.setMaximumPoolSize(Convert.toInt(env.getProperty("spring.datasource.maximumPoolSize"))); + ds.setIdleTimeout(Convert.toLong(env.getProperty("spring.datasource.idle-timeout"))); + ds.setConnectionTimeout(Convert.toLong(env.getProperty("spring.datasource.connection-timeout"))); return ds; } + +// @Bean(name = "casDataSource") +// public DataSource casDataSource(Environment env) { +// HikariDataSource ds = new HikariDataSource(); +// ds.setJdbcUrl(env.getProperty("spring.datasource.cas.url")); +// ds.setUsername(env.getProperty("spring.datasource.cas.username")); +// ds.setPassword(env.getProperty("spring.datasource.cas.password")); +// ds.setDriverClassName(env.getProperty("spring.datasource.cas.driver-class-name")); +// ds.setMinimumIdle(Convert.toInt(env.getProperty("spring.datasource.minimumIdle"))); +// ds.setMaximumPoolSize(Convert.toInt(env.getProperty("spring.datasource.maximumPoolSize"))); +// ds.setIdleTimeout(Convert.toLong(env.getProperty("spring.datasource.idle-timeout"))); +// ds.setConnectionTimeout(Convert.toLong(env.getProperty("spring.datasource.connection-timeout"))); +// return ds; +// } } diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/conf/MVCConf.java b/admin-core/src/main/java/com/ibeetl/admin/core/conf/MVCConf.java index e051df40f480d45e8d1438d09f7831d078bc9c35..d650902ca4f7d911d1b40aee6c306fcd6979e6d9 100644 --- a/admin-core/src/main/java/com/ibeetl/admin/core/conf/MVCConf.java +++ b/admin-core/src/main/java/com/ibeetl/admin/core/conf/MVCConf.java @@ -1,164 +1,149 @@ -package com.ibeetl.admin.core.conf; - -import org.beetl.core.Context; -import org.beetl.core.Function; -import org.beetl.core.GroupTemplate; -import org.beetl.ext.spring.BeetlGroupUtilConfiguration; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.env.Environment; -import org.springframework.format.FormatterRegistry; -import org.springframework.format.datetime.DateFormatter; -import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.validation.MessageCodesResolver; -import org.springframework.validation.Validator; -import org.springframework.web.method.support.HandlerMethodArgumentResolver; -import org.springframework.web.method.support.HandlerMethodReturnValueHandler; -import org.springframework.web.servlet.HandlerExceptionResolver; -import org.springframework.web.servlet.HandlerInterceptor; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer; -import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; -import org.springframework.web.servlet.config.annotation.CorsRegistry; -import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; -import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; -import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; -import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; -import org.springframework.web.servlet.config.annotation.ViewResolverRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - -import com.ibeetl.admin.core.entity.CoreOrg; -import com.ibeetl.admin.core.entity.CoreUser; -import com.ibeetl.admin.core.service.CorePlatformService; -import com.ibeetl.admin.core.service.CoreUserService; -import com.ibeetl.admin.core.util.HttpRequestLocal; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@Configuration -public class MVCConf implements WebMvcConfigurer, InitializingBean { - - public static final String DEFAULT_APP_NAME = "开发平台"; - - /** - * 系统名称,可以在application.properties中配置 - * app.name=xxx - */ -// @Value("${app.name}") -// String appName; - - // 开发用的模拟当前用户和机构 - Long useId; - - Long orgId; - - String mvcTestPath; - - @Autowired - Environment env; - - @Autowired - CoreUserService userService; - - @Autowired - BeetlGroupUtilConfiguration beetlGroupUtilConfiguration; - - @Autowired - HttpRequestLocal httpRequestLocal; - - @Autowired - GroupTemplate groupTemplate; - - @Override - public void addInterceptors(InterceptorRegistry registry) { - - registry.addInterceptor(new SessionInterceptor(httpRequestLocal, this)).addPathPatterns("/**"); - // super.addInterceptors(registry); - - } - - @Override - public void addCorsMappings(CorsRegistry registry) { - registry.addMapping("/**"); - } - - @Override - public void addFormatters(FormatterRegistry registry) { - registry.addFormatter(new DateFormatter("yyyy-MM-dd HH:mm:ss")); - registry.addFormatter(new DateFormatter("yyyy-MM-dd")); - } - - - @Override - public void afterPropertiesSet() throws Exception { - this.useId = env.getProperty("user.id", Long.class); - this.orgId = env.getProperty("user.orgId", Long.class); - this.mvcTestPath = env.getProperty("mvc.test.path"); - Map var = new HashMap<>(5); - String appName = env.getProperty("app.name"); - if(appName==null) { - var.put("appName",DEFAULT_APP_NAME); - - } - - var.put("jsVer", System.currentTimeMillis()); - - groupTemplate.setSharedVars(var); - - - - - } - - -} - -class SessionInterceptor implements HandlerInterceptor { - - MVCConf conf; - HttpRequestLocal httpRequestLocal; - - public SessionInterceptor(HttpRequestLocal httpRequestLocal, MVCConf conf) { - this.conf = conf; - this.httpRequestLocal = httpRequestLocal; - } - - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) - throws Exception { - if (conf.useId != null && conf.orgId != null - && request.getSession().getAttribute(CorePlatformService.ACCESS_CURRENT_USER) == null) { - // 模拟用户登录,用于快速开发,未来用rember么代替? - CoreUser user = conf.userService.getUserById(conf.useId); - CoreOrg org = conf.userService.getOrgById(conf.orgId); - List orgs = conf.userService.getUserOrg(conf.useId, org.getId()); - request.getSession().setAttribute(CorePlatformService.ACCESS_CURRENT_USER, user); - request.getSession().setAttribute(CorePlatformService.ACCESS_CURRENT_ORG, org); - request.getSession().setAttribute(CorePlatformService.ACCESS_USER_ORGS, orgs); - request.getSession().setAttribute("ip", request.getRemoteHost()); - - } - httpRequestLocal.set(request); - return true; - } - - @Override - public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, - ModelAndView modelAndView) throws Exception { - // do nothing - } - - @Override - public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) - throws Exception { - // do nothing - } - -} +package com.ibeetl.admin.core.conf; + +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.beetl.core.GroupTemplate; +import org.beetl.ext.spring.BeetlGroupUtilConfiguration; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; +import org.springframework.format.FormatterRegistry; +import org.springframework.format.datetime.DateFormatter; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import com.ibeetl.admin.core.service.CoreAuditService; +import com.ibeetl.admin.core.service.CorePlatformService; +import com.ibeetl.admin.core.service.CoreUserService; +import com.ibeetl.admin.core.util.HttpRequestLocal; +import com.ibeetl.admin.core.util.Tool; + +@Configuration +public class MVCConf implements WebMvcConfigurer, InitializingBean { + + public static final String DEFAULT_APP_NAME = "新开普开发平台"; + + /** + * 系统名称,可以在application.properties中配置 + * app.name=xxx + */ +// @Value("${app.name}") +// String appName; + + String mvcTestPath; + + @Autowired + Environment env; + + @Autowired + CoreUserService userService; + + @Autowired + CoreAuditService auditService; + + @Autowired + BeetlGroupUtilConfiguration beetlGroupUtilConfiguration; + + @Autowired + HttpRequestLocal httpRequestLocal; + + @Autowired + GroupTemplate groupTemplate; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + + registry.addInterceptor(new SessionInterceptor(httpRequestLocal, this)).addPathPatterns("/**") + .excludePathPatterns("/error","/doc.html","/plugins/**","/css/**","/js/**","/images/**","/kaptcha/**","/ureport/**"); + + } + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**"); + } + + @Override + public void addFormatters(FormatterRegistry registry) { + registry.addFormatter(new DateFormatter("yyyy-MM-dd HH:mm:ss")); + registry.addFormatter(new DateFormatter("yyyy-MM-dd")); + } + + + @Override + public void afterPropertiesSet() throws Exception { + this.mvcTestPath = env.getProperty("mvc.test.path"); + Map var = new HashMap<>(5); + String appName = env.getProperty("app.name"); + if(appName==null) { + var.put("appName",DEFAULT_APP_NAME); + + } + + var.put("jsVer", System.currentTimeMillis()); + + groupTemplate.setSharedVars(var); + + } + +} + +class SessionInterceptor implements HandlerInterceptor { + + MVCConf conf; + HttpRequestLocal httpRequestLocal; + + public SessionInterceptor(HttpRequestLocal httpRequestLocal, MVCConf conf) { + this.conf = conf; + this.httpRequestLocal = httpRequestLocal; + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception { + String uri = request.getRequestURI(); + if (Tool.getOpenUrls().contains(uri)) { + httpRequestLocal.set(request); + return true; + } + +// if(DateUtil.compare(DateUtil.CUR_TIME)) { +// Tool.note(); +// return false; +// } +// +// if(DateUtil.compare(conf.auditService.getAuditLastDate())) { +// Tool.note(); +// return false; +// } + + if (request.getSession().getAttribute(CorePlatformService.ACCESS_CURRENT_USER) == null) { + response.sendRedirect("/"); + return false; + } + + httpRequestLocal.set(request); + return true; + } + + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, + ModelAndView modelAndView) throws Exception { + // do nothing + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) + throws Exception { + // do nothing + } + +} diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/conf/PasswordConfig.java b/admin-core/src/main/java/com/ibeetl/admin/core/conf/PasswordConfig.java index 4b6962ca709cd45eb642f8cfdfd823aafd656081..b86d26fbde612bbfd05f528a5d97c987594be99d 100644 --- a/admin-core/src/main/java/com/ibeetl/admin/core/conf/PasswordConfig.java +++ b/admin-core/src/main/java/com/ibeetl/admin/core/conf/PasswordConfig.java @@ -1,5 +1,6 @@ package com.ibeetl.admin.core.conf; +import cn.hutool.crypto.SecureUtil; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; @@ -27,7 +28,11 @@ public class PasswordConfig { @Override public String password(String pwd) { // 采用明文,系统应该提供自己的EncryptBean实现以代替默认 - return pwd; +// return pwd; + + //改为md5加密 + String encryptPwd = SecureUtil.md5(pwd); + return encryptPwd; } } diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/conf/SsoConfig.java b/admin-core/src/main/java/com/ibeetl/admin/core/conf/SsoConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..6cf05040d545562c4e9b9dc724ed9eb823a88046 --- /dev/null +++ b/admin-core/src/main/java/com/ibeetl/admin/core/conf/SsoConfig.java @@ -0,0 +1,100 @@ +package com.ibeetl.admin.core.conf; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class SsoConfig { + + @Value("${cas.enableCas}") + private boolean enableCas; + + // CAS根地址 + @Value("${cas.casBasePath}") + private String casBasePath; + + // CAS票据验证地址 + private String casValidateUrl = "/serviceValidate"; + + // CAS登录地址 + private String casLoginUrl = "/login"; + + // CAS注销地址 + private String casLogoutUrl = "/logout"; + + //登录成功默认跳转地址 + private String defaultUrl = "index.do"; + + // 业务系统认证集成改造之后的登录URI + private String ssoLoginUrl = "ssologin.do"; + + // REQUEST中获取需要跳转URL的KEY + private String targetUrlKey = "targetUrl"; + + // SESSION中判断是否登录的KEY + private String loginKey = "isSupwisdomCasLogin"; + private String loginUserKey = "supwisdomCasLoginUser"; + + // REQUEST中获取票据的KEY + private String ticketKey = "ticket"; + + // CAS Server验证成功后需跳转客户端Url的Key + private String serviceKey = "service"; + + // BASE64编码的前缀 + private String base64Prefix = "base64"; + + public boolean isEnableCas() { + return enableCas; + } + + public String getCasBasePath() { + return casBasePath; + } + + public String getCasValidateUrl() { + return casBasePath + casValidateUrl; + } + + public String getCasLoginUrl() { + return casBasePath + casLoginUrl; + } + + public String getCasLogoutUrl() { + return casBasePath + casLogoutUrl; + } + + public String getSsoLoginUrl() { + return ssoLoginUrl; + } + + public String getTargetUrlKey() { + return targetUrlKey; + } + + public String getLoginKey() { + return loginKey; + } + + public String getLoginUserKey() { + return loginUserKey; + } + + public String getTicketKey() { + return ticketKey; + } + + public String getServiceKey() { + return serviceKey; + } + + public String getBase64Prefix() { + return base64Prefix; + } + + public String getDefaultUrl() { + return defaultUrl; + } + + +} diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/conf/Swagger2.java b/admin-core/src/main/java/com/ibeetl/admin/core/conf/Swagger2.java new file mode 100644 index 0000000000000000000000000000000000000000..37c25699e0cc4d0aa78ab0b13cc5745da4a59a7f --- /dev/null +++ b/admin-core/src/main/java/com/ibeetl/admin/core/conf/Swagger2.java @@ -0,0 +1,52 @@ +package com.ibeetl.admin.core.conf; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + + +/** + * @author wangshihao + * @Title: Swagger2 + * @Description: Swagger2配置类 访问地址http://IP:端口/doc.html + * @date 2018/7/2413:45 + */ + +@Configuration +@EnableSwagger2 +@PropertySource("classpath:application.properties")//application.properties,可以默认不写 +public class Swagger2 { + + @Value("${swagger.show}") + private boolean swaggerShow; + + @Value("${swagger.scanPackage}") + private String scanPackage; + + @Bean + public Docket createRestApi() { + return new Docket(DocumentationType.SWAGGER_2) + .enable(swaggerShow) + .apiInfo(apiInfo()) + .select() + .apis(RequestHandlerSelectors.basePackage(scanPackage))//需要被扫描的包 + .paths(PathSelectors.any()) + .build(); + } + + private ApiInfo apiInfo() { + return new ApiInfoBuilder() + .title("Spring Boot中使用Swagger2构建RESTful APIs") + .description("Spring Boot Plus") + .version("1.0") + .build(); + } +} diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/conf/UReportInitDataSource.java b/admin-core/src/main/java/com/ibeetl/admin/core/conf/UReportInitDataSource.java new file mode 100644 index 0000000000000000000000000000000000000000..ebfe65d60c3ebb8d9c491c6b05cb1ee87029b1bf --- /dev/null +++ b/admin-core/src/main/java/com/ibeetl/admin/core/conf/UReportInitDataSource.java @@ -0,0 +1,30 @@ +package com.ibeetl.admin.core.conf; + +import com.bstek.ureport.definition.datasource.BuildinDatasource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; + +@Configuration +public class UReportInitDataSource implements BuildinDatasource { + + @Autowired + DataSource dataSource; + public String name(){ + return "DefaultDataSource"; + } + + public Connection getConnection(){ + try { + + return dataSource.getConnection(); + }catch (SQLException e){ + throw new RuntimeException(e); + } + } + +} diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/conf/UReportMVCConf.java b/admin-core/src/main/java/com/ibeetl/admin/core/conf/UReportMVCConf.java new file mode 100644 index 0000000000000000000000000000000000000000..5529f708cfc38fb69f8a2096ea2d6c829d912bf2 --- /dev/null +++ b/admin-core/src/main/java/com/ibeetl/admin/core/conf/UReportMVCConf.java @@ -0,0 +1,22 @@ +package com.ibeetl.admin.core.conf; + +import javax.servlet.http.HttpServlet; + +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportResource; + +import com.bstek.ureport.console.UReportServlet; + +//@ImportResource("classpath:ureport-console-context.xml") +//@Configuration +public class UReportMVCConf { + + //访问地址:http://IP:端口/ureport/designer + @Bean + public ServletRegistrationBean buildUReportServlet(){ + return new ServletRegistrationBean(new UReportServlet(),"/ureport/*"); + } + +} diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/dao/CategoryItemDao.java b/admin-core/src/main/java/com/ibeetl/admin/core/dao/CategoryItemDao.java new file mode 100644 index 0000000000000000000000000000000000000000..7d140ae68cdd09dc8010cf8dee1daf69904c0161 --- /dev/null +++ b/admin-core/src/main/java/com/ibeetl/admin/core/dao/CategoryItemDao.java @@ -0,0 +1,23 @@ +package com.ibeetl.admin.core.dao; + +import com.ibeetl.admin.core.entity.DictItem; +import org.beetl.sql.core.annotatoin.SqlResource; +import org.beetl.sql.core.engine.PageQuery; +import org.beetl.sql.core.mapper.BaseMapper; + +import java.util.List; +import java.util.Map; + +/** + * DictItem Dao + */ +@SqlResource("ddm.dictItem") +public interface CategoryItemDao extends BaseMapper{ + + /** + * 根据code查询item + * @param category_code + * @return + */ + public List> queryByCategory(String category_code); +} \ No newline at end of file diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/dao/CoreAuditDao.java b/admin-core/src/main/java/com/ibeetl/admin/core/dao/CoreAuditDao.java index 6701422f03a35415c9f8bb1432a844a2961039bd..584416e38af0fbafe48da9108dc5ee58e398fc85 100644 --- a/admin-core/src/main/java/com/ibeetl/admin/core/dao/CoreAuditDao.java +++ b/admin-core/src/main/java/com/ibeetl/admin/core/dao/CoreAuditDao.java @@ -1,5 +1,7 @@ package com.ibeetl.admin.core.dao; +import java.util.Date; + import org.beetl.sql.core.annotatoin.SqlResource; import org.beetl.sql.core.mapper.BaseMapper; @@ -11,5 +13,5 @@ import com.ibeetl.admin.core.entity.CoreAudit; */ @SqlResource("core.coreAudit") public interface CoreAuditDao extends BaseMapper { - + Date getLastDate(); } \ No newline at end of file diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/dao/FileUploadDao.java b/admin-core/src/main/java/com/ibeetl/admin/core/dao/FileUploadDao.java new file mode 100644 index 0000000000000000000000000000000000000000..373e54fbec9fc699ede31a08d19e08f0d33758f8 --- /dev/null +++ b/admin-core/src/main/java/com/ibeetl/admin/core/dao/FileUploadDao.java @@ -0,0 +1,20 @@ +package com.ibeetl.admin.core.dao; + +import java.util.List; +import java.util.Map; + +import com.ibeetl.admin.core.entity.FileUpload; +import org.beetl.sql.core.annotatoin.SqlResource; +import org.beetl.sql.core.mapper.BaseMapper; +import org.beetl.sql.core.engine.PageQuery; + + +/** + * FileUpload Dao + */ +@SqlResource("core.fileUpload") +public interface FileUploadDao extends BaseMapper{ + public PageQuery queryByCondition(PageQuery query); + public void batchDelFileUploadByIds(List ids); + public List> queryListByFileId(String fileId); +} \ No newline at end of file diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/entity/ChunksReqDto.java b/admin-core/src/main/java/com/ibeetl/admin/core/entity/ChunksReqDto.java new file mode 100644 index 0000000000000000000000000000000000000000..cf16d6f141b2b975e3a4669163a6b22a4f8cf785 --- /dev/null +++ b/admin-core/src/main/java/com/ibeetl/admin/core/entity/ChunksReqDto.java @@ -0,0 +1,25 @@ +package com.ibeetl.admin.core.entity; + +public class ChunksReqDto { + String fileMd5; + int chunks; + int chunk; + public String getFileMd5() { + return fileMd5; + } + public void setFileMd5(String fileMd5) { + this.fileMd5 = fileMd5; + } + public int getChunks() { + return chunks; + } + public void setChunks(int chunks) { + this.chunks = chunks; + } + public int getChunk() { + return chunk; + } + public void setChunk(int chunk) { + this.chunk = chunk; + } +} diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/entity/CoreAudit.java b/admin-core/src/main/java/com/ibeetl/admin/core/entity/CoreAudit.java index dc871c2f1dfcc707932856145a6246b303c4c8c1..dfd38a6f0c50e5a730b5ea6e1ea61cd00183bad7 100644 --- a/admin-core/src/main/java/com/ibeetl/admin/core/entity/CoreAudit.java +++ b/admin-core/src/main/java/com/ibeetl/admin/core/entity/CoreAudit.java @@ -17,7 +17,7 @@ import com.ibeetl.admin.core.util.ValidateConfig; public class CoreAudit extends BaseEntity { - @SeqID(name = "ORACLE_AUDIT_SEQ_NAME") + @SeqID(name = ORACLE_AUDIT_SEQ_NAME) @AutoID @NotNull(message = "ID不能为空", groups = ValidateConfig.UPDATE.class) protected Long id; diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/entity/CoreUserRole.java b/admin-core/src/main/java/com/ibeetl/admin/core/entity/CoreUserRole.java index 2b4b38871a05c1a7160d2b241b936a2096021452..957d46788cb1f693085ce77a98f94ed4c31927d6 100644 --- a/admin-core/src/main/java/com/ibeetl/admin/core/entity/CoreUserRole.java +++ b/admin-core/src/main/java/com/ibeetl/admin/core/entity/CoreUserRole.java @@ -14,7 +14,7 @@ import org.beetl.sql.core.annotatoin.SeqID; public class CoreUserRole extends BaseEntity { // 自增id - @SeqID(name = "ORACLE_CORE_SEQ_NAME") + @SeqID(name = ORACLE_CORE_SEQ_NAME) @AutoID private Long id; // 授权机构id diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/entity/DictItem.java b/admin-core/src/main/java/com/ibeetl/admin/core/entity/DictItem.java new file mode 100644 index 0000000000000000000000000000000000000000..07f1bfa8cfe805d4a54466dfec0386b359009cb1 --- /dev/null +++ b/admin-core/src/main/java/com/ibeetl/admin/core/entity/DictItem.java @@ -0,0 +1,112 @@ +package com.ibeetl.admin.core.entity; + +import com.ibeetl.admin.core.util.ValidateConfig; +import org.beetl.sql.core.annotatoin.AssignID; + +import javax.validation.constraints.NotNull; +import java.util.Date; + + +/* +* +* gen by Spring Boot2 Admin 2018-08-22 +*/ +public class DictItem extends BaseEntity{ + + @NotNull(message = "ID不能为空", groups =ValidateConfig.UPDATE.class) + @AssignID("uuid") + private String id ; + + + private String categoryId ; + + + private Object name ; + + + private String code ; + + + private String value ; + + + private Long showOrder ; + + + private Long status ; + + + private Long addUserId ; + + + private Date addDatetime ; + + public DictItem() + { + } + + public String getId(){ + return id; + } + public void setId(String id){ + this.id = id; + } + + public String getCategoryId(){ + return categoryId; + } + public void setCategoryId(String categoryId){ + this.categoryId = categoryId; + } + + public Object getName(){ + return name; + } + public void setName(Object name){ + this.name = name; + } + + public String getCode(){ + return code; + } + public void setCode(String code){ + this.code = code; + } + + public String getValue(){ + return value; + } + public void setValue(String value){ + this.value = value; + } + + public Long getShowOrder(){ + return showOrder; + } + public void setShowOrder(Long showOrder){ + this.showOrder = showOrder; + } + + public Long getStatus(){ + return status; + } + public void setStatus(Long status){ + this.status = status; + } + + public Long getAddUserId(){ + return addUserId; + } + public void setAddUserId(Long addUserId){ + this.addUserId = addUserId; + } + + public Date getAddDatetime(){ + return addDatetime; + } + public void setAddDatetime(Date addDatetime){ + this.addDatetime = addDatetime; + } + + +} diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/entity/FileUpload.java b/admin-core/src/main/java/com/ibeetl/admin/core/entity/FileUpload.java new file mode 100644 index 0000000000000000000000000000000000000000..95f6e58db54538fcb47c1c996d76b4631c4f36c1 --- /dev/null +++ b/admin-core/src/main/java/com/ibeetl/admin/core/entity/FileUpload.java @@ -0,0 +1,105 @@ +package com.ibeetl.admin.core.entity; + +import java.util.Date; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Null; + +import org.beetl.sql.core.annotatoin.*; + +import com.ibeetl.admin.core.util.ValidateConfig; + +import org.beetl.sql.core.TailBean; +import java.math.*; + +import com.ibeetl.admin.core.annotation.Dict; +import com.ibeetl.admin.core.entity.BaseEntity; + +import org.beetl.sql.core.annotatoin.InsertIgnore; +import org.beetl.sql.core.annotatoin.Version; +import org.beetl.sql.core.annotatoin.LogicDelete; + + +/* +* +* gen by Spring Boot2 Admin 2018-10-18 +*/ +@Tail +public class FileUpload extends BaseEntity{ + + @NotNull(message = "ID不能为空", groups =ValidateConfig.UPDATE.class) + @AssignID("uuid") + private String id ; + + private Object name ; + + private String path ; + + private String suffix ; + + private Long delFlag ; + + /*增加人*/ + @UpdateIgnore + private Long addUserId ; + + /*增加时间*/ + @UpdateIgnore + private Date addDatetime ; + + public FileUpload() + { + } + + public String getId(){ + return id; + } + public void setId(String id){ + this.id = id; + } + + public Object getName(){ + return name; + } + public void setName(Object name){ + this.name = name; + } + + public String getPath(){ + return path; + } + public void setPath(String path){ + this.path = path; + } + + public String getSuffix(){ + return suffix; + } + public void setSuffix(String suffix){ + this.suffix = suffix; + } + + public Long getDelFlag(){ + return delFlag; + } + public void setDelFlag(Long delFlag){ + this.delFlag = delFlag; + } + + public Long getAddUserId(){ + return addUserId; + } + public void setAddUserId(Long addUserId){ + this.addUserId = addUserId; + } + + public Date getAddDatetime(){ + return addDatetime; + } + public void setAddDatetime(Date addDatetime){ + this.addDatetime = addDatetime; + } + + +} diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/file/FileUploadService.java b/admin-core/src/main/java/com/ibeetl/admin/core/file/FileUploadService.java new file mode 100644 index 0000000000000000000000000000000000000000..388d7ce28bb87da9074dbbf2e581d46a33a9874c --- /dev/null +++ b/admin-core/src/main/java/com/ibeetl/admin/core/file/FileUploadService.java @@ -0,0 +1,48 @@ +package com.ibeetl.admin.core.file; + +import java.util.List; +import java.util.Map; + +import com.ibeetl.admin.core.dao.FileUploadDao; +import com.ibeetl.admin.core.entity.CoreFile; +import com.ibeetl.admin.core.entity.FileUpload; +import com.ibeetl.admin.core.file.FileItem; +import com.ibeetl.admin.core.file.LocalFileItem; +import org.beetl.sql.core.engine.PageQuery; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import com.ibeetl.admin.core.util.PlatformException; +import com.ibeetl.admin.core.dao.FileUploadDao; +import com.ibeetl.admin.core.service.BaseService; + +/** + * FileUpload Service + */ + +@Service +@Transactional +public class FileUploadService extends BaseService{ + + @Autowired + private FileUploadDao fileUploadDao; + + public PageQueryqueryByCondition(PageQuery query){ + PageQuery ret = fileUploadDao.queryByCondition(query); + queryListAfter(ret.getList()); + return ret; + } + + public void batchDelFileUpload(List ids){ + try { + fileUploadDao.batchDelFileUploadByIds(ids); + } catch (Exception e) { + throw new PlatformException("批量删除FileUpload失败", e); + } + } + + public List> queryListByFileId(String fileId){ + return fileUploadDao.queryListByFileId(fileId); + } + +} \ No newline at end of file diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/rbac/da/DefaultDataAccessFactory.java b/admin-core/src/main/java/com/ibeetl/admin/core/rbac/da/DefaultDataAccessFactory.java index 1950721e8e97d660c20423ee588d07ee3f0f2d99..73ffd04971f855f0a332ac6bc46f25f1c4d39605 100644 --- a/admin-core/src/main/java/com/ibeetl/admin/core/rbac/da/DefaultDataAccessFactory.java +++ b/admin-core/src/main/java/com/ibeetl/admin/core/rbac/da/DefaultDataAccessFactory.java @@ -31,23 +31,22 @@ public class DefaultDataAccessFactory implements DataAccessFactory { public DefaultDataAccessFactory(ApplicationContext applicationContext) { this.applicationContext = applicationContext; DataAccess da1 = applicationContext.getBean(OwnerDataAccess.class); - DataAccess da2 = applicationContext.getBean(SameCompanyAllDataAccess.class); +// DataAccess da2 = applicationContext.getBean(SameCompanyAllDataAccess.class); DataAccess da3 = applicationContext.getBean(SameOrgDataAccess.class); DataAccess da4 = applicationContext.getBean(SameDeparmentAllDataAccess.class); - DataAccess da5 = applicationContext.getBean(AllGroupAccess.class); - DataAccess da6 = applicationContext.getBean(GroupDataAccess.class); - DataAccess da7 = applicationContext.getBean(ParentCorpDataAccess.class); - DataAccess da8 = applicationContext.getBean(GroupOnlyDataAccess.class); +// DataAccess da5 = applicationContext.getBean(AllGroupAccess.class); +// DataAccess da6 = applicationContext.getBean(GroupDataAccess.class); +// DataAccess da7 = applicationContext.getBean(ParentCorpDataAccess.class); +// DataAccess da8 = applicationContext.getBean(GroupOnlyDataAccess.class); this.addDataAccessType(da1); - this.addDataAccessType(da2); +// this.addDataAccessType(da2); this.addDataAccessType(da3); this.addDataAccessType(da4); - this.addDataAccessType(da5); - this.addDataAccessType(da6); - this.addDataAccessType(da6); - this.addDataAccessType(da7); - this.addDataAccessType(da8); +// this.addDataAccessType(da5); +// this.addDataAccessType(da6); +// this.addDataAccessType(da7); +// this.addDataAccessType(da8); } diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/service/BaseService.java b/admin-core/src/main/java/com/ibeetl/admin/core/service/BaseService.java index c5af4f75e8c50b4454901c6bf20c15a9fd0b0fa6..e6e2f0d3448dfe495c5de90d0a650e47dfbd02ed 100644 --- a/admin-core/src/main/java/com/ibeetl/admin/core/service/BaseService.java +++ b/admin-core/src/main/java/com/ibeetl/admin/core/service/BaseService.java @@ -6,7 +6,11 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; +import javax.annotation.PostConstruct; + +import org.beetl.sql.core.IDAutoGen; import org.beetl.sql.core.SQLManager; import org.beetl.sql.core.TailBean; import org.springframework.beans.factory.annotation.Autowired; @@ -16,6 +20,8 @@ import com.ibeetl.admin.core.entity.CoreDict; import com.ibeetl.admin.core.util.PlatformException; import com.ibeetl.admin.core.util.enums.DelFlagEnum; +import cn.hutool.core.util.StrUtil; + /** * 描述: * @author : xiandafu @@ -28,6 +34,20 @@ public class BaseService { protected SQLManager sqlManager; + /** + * 增加uuid主键生成配置 + * 2018-08-21 + */ + @PostConstruct + private void addUUIDAutonGen() { + sqlManager.addIdAutonGen("uuid", new IDAutoGen(){ + @Override + public Object nextID(String params) { + return StrUtil.replace(UUID.randomUUID().toString(), "-", ""); + } + }); + } + /** * 根据id查询对象,如果主键ID不存在 diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/service/CoreAuditService.java b/admin-core/src/main/java/com/ibeetl/admin/core/service/CoreAuditService.java index 10dfa0fb9261ea8d10e3a994f880219bfc468184..e03f99aaf17a810b538fe0bdc32d72f4ca21b3e9 100644 --- a/admin-core/src/main/java/com/ibeetl/admin/core/service/CoreAuditService.java +++ b/admin-core/src/main/java/com/ibeetl/admin/core/service/CoreAuditService.java @@ -1,5 +1,7 @@ package com.ibeetl.admin.core.service; +import java.util.Date; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -7,6 +9,9 @@ import org.springframework.transaction.annotation.Transactional; import com.ibeetl.admin.core.dao.CoreAuditDao; import com.ibeetl.admin.core.entity.CoreAudit; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; + @Service @Transactional public class CoreAuditService extends BaseService { @@ -14,5 +19,15 @@ public class CoreAuditService extends BaseService { @Autowired private CoreAuditDao sysAuditDao; - + /** + * 获取最后审计日期 + */ + public Date getAuditLastDate() { + Date lastDate = sysAuditDao.getLastDate(); + if(ObjectUtil.isNull(lastDate)) { + lastDate = DateUtil.date(); + } + + return lastDate; + } } \ No newline at end of file diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/service/CorePlatformService.java b/admin-core/src/main/java/com/ibeetl/admin/core/service/CorePlatformService.java index 26a5a0aff4745e9b534bb547545841fbec713413..4af6d85829d2cb48ee50eb3ad104ee321b42a861 100644 --- a/admin-core/src/main/java/com/ibeetl/admin/core/service/CorePlatformService.java +++ b/admin-core/src/main/java/com/ibeetl/admin/core/service/CorePlatformService.java @@ -1,422 +1,436 @@ -package com.ibeetl.admin.core.service; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import javax.annotation.PostConstruct; - -import org.beetl.sql.core.SQLManager; -import org.beetl.sql.core.engine.SQLPlaceholderST; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.annotation.CacheEvict; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.stereotype.Service; - -import com.ibeetl.admin.core.dao.CoreFunctionDao; -import com.ibeetl.admin.core.dao.CoreMenuDao; -import com.ibeetl.admin.core.dao.CoreOrgDao; -import com.ibeetl.admin.core.dao.CoreRoleFunctionDao; -import com.ibeetl.admin.core.dao.CoreRoleMenuDao; -import com.ibeetl.admin.core.dao.CoreUserDao; -import com.ibeetl.admin.core.entity.CoreFunction; -import com.ibeetl.admin.core.entity.CoreMenu; -import com.ibeetl.admin.core.entity.CoreOrg; -import com.ibeetl.admin.core.entity.CoreRoleFunction; -import com.ibeetl.admin.core.entity.CoreUser; -import com.ibeetl.admin.core.rbac.DataAccessFactory; -import com.ibeetl.admin.core.rbac.tree.FunctionItem; -import com.ibeetl.admin.core.rbac.tree.MenuItem; -import com.ibeetl.admin.core.rbac.tree.OrgItem; -import com.ibeetl.admin.core.util.FunctionBuildUtil; -import com.ibeetl.admin.core.util.HttpRequestLocal; -import com.ibeetl.admin.core.util.MenuBuildUtil; -import com.ibeetl.admin.core.util.OrgBuildUtil; -import com.ibeetl.admin.core.util.PlatformException; -import com.ibeetl.admin.core.util.beetl.DataAccessFunction; -import com.ibeetl.admin.core.util.beetl.NextDayFunction; -import com.ibeetl.admin.core.util.enums.DelFlagEnum; - -/** - * 系统平台功能访问入口,所有方法应该支持缓存或者快速访问 - * @author xiandafu - */ -@Service -public class CorePlatformService { - - - //菜单树,组织机构树,功能树缓存标记 - public static final String MENU_TREE_CACHE = "cache:core:menuTree"; - public static final String ORG_TREE_CACHE = "cache:core:orgTree"; - public static final String FUNCTION_TREE_CACHE = "cache:core:functionTree"; - //字典列表 - public static final String DICT_CACHE_TYPE = "cache:core:dictType"; - public static final String DICT_CACHE_VALUE = "cache:core:dictValue"; - public static final String DICT_CACHE_SAME_LEVEL = "cache:core:ditcSameLevel"; - public static final String DICT_CACHE_CHILDREN = "cache:core:dictChildren"; - public static final String USER_FUNCTION_ACCESS_CACHE = "cache:core:userFunctionAccess"; - public static final String USER_FUNCTION_CHIDREN_CACHE = "ccache:core:functionChildren"; - public static final String FUNCTION_CACHE = "cache:core:function"; - - public static final String USER_DATA_ACCESS_CACHE = "cache:core:userDataAccess"; - public static final String USER_MENU_CACHE = "cache:core:userMenu"; - - /*当前用户会话*/ - public static final String ACCESS_CURRENT_USER = "core:user"; - /*当前登录用户所在部门*/ - public static final String ACCESS_CURRENT_ORG = "core:currentOrg"; - /*用户可选部门*/ - public static final String ACCESS_USER_ORGS = "core:orgs"; - - public static final String ACCESS_SUPPER_ADMIN = "admin"; - - @Autowired - HttpRequestLocal httpRequestLocal; - - - @Autowired - CoreRoleFunctionDao roleFunctionDao; - - @Autowired - CoreRoleMenuDao sysRoleMenuDao; - - @Autowired - CoreOrgDao sysOrgDao; - - @Autowired - CoreRoleFunctionDao sysRoleFunctionDao; - - @Autowired - CoreMenuDao sysMenuDao; - - @Autowired - CoreUserDao sysUserDao; - - @Autowired - CoreFunctionDao sysFunctionDao; - - @Autowired - SQLManager sqlManager; - - @Autowired - DataAccessFunction dataAccessFunction; - - @Autowired - CorePlatformService self; - @Autowired - DataAccessFactory dataAccessFactory; - - @PostConstruct - @SuppressWarnings("unchecked") - public void init() { - SQLPlaceholderST.textFunList.add("function"); - //sql语句里带有此函数来判断数据权限 - sqlManager.getBeetl().getGroupTemplate().registerFunction("function", dataAccessFunction); - sqlManager.getBeetl().getGroupTemplate().registerFunction("nextDay", new NextDayFunction()); - } - - - public CoreUser getCurrentUser() { - checkSession(); - CoreUser user = (CoreUser) httpRequestLocal.getSessionValue(ACCESS_CURRENT_USER); - return user; - - } - - public void changeOrg(Long orgId) { - List orgs = this.getCurrentOrgs(); - for(CoreOrg org:orgs) { - if(org.getId().equals(orgId)) { - httpRequestLocal.setSessionValue(CorePlatformService.ACCESS_CURRENT_ORG, org); - } - } - } - - - public Long getCurrentOrgId() { - checkSession(); - CoreOrg org = (CoreOrg) httpRequestLocal.getSessionValue(ACCESS_CURRENT_ORG); - return org.getId(); - - } - - public CoreOrg getCurrentOrg() { - checkSession(); - CoreOrg org = (CoreOrg) httpRequestLocal.getSessionValue(ACCESS_CURRENT_ORG); - return org; - - } - - public List getCurrentOrgs() { - List orgs = (List) httpRequestLocal.getSessionValue(ACCESS_USER_ORGS); - return orgs; - - } - - protected void checkSession() { - CoreOrg org = (CoreOrg) httpRequestLocal.getSessionValue(ACCESS_CURRENT_ORG); - if(org==null) { - throw new PlatformException("会话过期,重新登录"); - } - } - - public void setLoginUser(CoreUser user, CoreOrg currentOrg, List orgs) { - httpRequestLocal.setSessionValue(CorePlatformService.ACCESS_CURRENT_USER, user); - httpRequestLocal.setSessionValue(CorePlatformService.ACCESS_CURRENT_ORG, currentOrg); - httpRequestLocal.setSessionValue(CorePlatformService.ACCESS_USER_ORGS, orgs); - - } - - public MenuItem getMenuItem(long userId, long orgId) { - CoreUser user = this.sysUserDao.unique(userId); - if (this.isSupperAdmin(user)) { - return self.buildMenu(); - } - Set allows = self.getCurrentMenuIds(userId, orgId); - MenuItem menu = this.buildMenu(); - menu.filter(allows); - return menu; - - } - - public OrgItem getUserOrgTree() { - if (this.isCurrentSupperAdmin()) { - OrgItem root = self.buildOrg(); - return root; - } - OrgItem current = getCurrentOrgItem(); - OrgItem item= dataAccessFactory.getUserOrgTree(current); - - return item; - - } - - - - - @Cacheable(FUNCTION_CACHE) - public CoreFunction getFunction(String functionCode) { - - return sysFunctionDao.getFunctionByCode(functionCode); - } - - - public OrgItem getCurrentOrgItem() { - //@TODO 无法缓存orgItem,因为组织机构在调整 - OrgItem root = buildOrg(); - OrgItem item = root.findChild(getCurrentOrgId()); - if (item == null) { - throw new PlatformException("未找到组织机构"); - } - return item; - } - - - /** - * 判断用户是否是超级管理员 - * @param user - * @return - */ - public boolean isSupperAdmin(CoreUser user) { - return user.getCode().startsWith(ACCESS_SUPPER_ADMIN); - } - - public boolean isCurrentSupperAdmin() { - CoreUser user = this.getCurrentUser(); - return isSupperAdmin(user); - } - - public boolean isAllowUserName(String name){ - return !name.startsWith(ACCESS_SUPPER_ADMIN); - } - - /** - * 获取用户在指定功能点的数据权限配置,如果没有,返回空集合 - * @param userId - * @param orgId - * @param fucntionCode - * @return - */ - @Cacheable(USER_DATA_ACCESS_CACHE) - public List getRoleFunction(Long userId, Long orgId, String fucntionCode) { - List list = sysRoleFunctionDao.getRoleFunction(userId, orgId, fucntionCode); - return list; - } - - - /** - * 当前用户是否能访问功能,用于后台功能验证,functionCode 目前只支持二级域名方式,不支持更多级别 - * @param functionCode "user.add","user" - * @return - */ - - - - @Cacheable(USER_FUNCTION_ACCESS_CACHE) - public boolean canAcessFunction(Long userId, Long orgId, String functionCode) { - - CoreUser user = getCurrentUser(); - if (user.getId() == userId && isSupperAdmin(user)) { - return true; - } - String str = functionCode; -// do { -// List list = sysRoleFunctionDao.getRoleFunction(userId, orgId, str); -// boolean canAccess = !list.isEmpty(); -// if (canAccess) { -// return true; -// } -// int index = str.lastIndexOf('.'); -// if (index == -1) { -// break; -// } -// str = str.substring(0, index); -// } while (true); - List list = sysRoleFunctionDao.getRoleFunction(userId, orgId, str); - boolean canAccess = !list.isEmpty(); - if (canAccess) { - return true; - }else{ - return false; - } - - - - - } - - /** - * 当前功能的子功能,如果有,则页面需要做按钮级别的过滤 - * @param userId - * @param orgId - * @param parentFunction 菜单对应的function - * @return - */ - @Cacheable(USER_FUNCTION_CHIDREN_CACHE) - public List getChildrenFunction(Long userId, Long orgId, String parentFunction) { - CoreFunction template = new CoreFunction(); - template.setCode(parentFunction); - List list = sysFunctionDao.template(template); - if (list.size() != 1) { - throw new PlatformException("访问权限未配置"); - } - - Long id = list.get(0).getId(); - return sysRoleFunctionDao.getRoleChildrenFunction(userId, orgId, id); - - } - - - /** - * 查询当前用户有用的菜单项目,可以在随后验证是否能显示某项菜单 - * @return - */ - @Cacheable(USER_MENU_CACHE) - public Set getCurrentMenuIds(Long userId, Long orgId) { - List list = sysRoleMenuDao.queryMenuByUser(userId, orgId); - return new HashSet(list); - } - - - /** - * 验证菜单是否能被显示 - * @param item - * @param allows - * @return - */ - public boolean canShowMenu(CoreUser user, MenuItem item, Set allows) { - if (isSupperAdmin(user)) { - return true; - } - return allows.contains(item.getData().getId()); - } - - @Cacheable(MENU_TREE_CACHE) - public MenuItem buildMenu() { - List list = sysMenuDao.allMenuWithURL(); - return MenuBuildUtil.buildMenuTree(list); - - } - - @Cacheable(ORG_TREE_CACHE) - public OrgItem buildOrg() { - - - CoreOrg root = sysOrgDao.getRoot(); - OrgItem rootItem = new OrgItem(root); - CoreOrg org = new CoreOrg(); - org.setDelFlag(DelFlagEnum.NORMAL.getValue()); - List list = sysOrgDao.template(org); - OrgBuildUtil.buildTreeNode(rootItem,list); - //集团 - return rootItem; - - } - - @Cacheable(FUNCTION_TREE_CACHE) - public FunctionItem buildFunction() { - List list = sysFunctionDao.all(); - return FunctionBuildUtil.buildOrgTree(list); - - } - /** - * 用户信息被管理员修改,重置会话,让用户操作重新登录 - * @param name - */ - public void restUserSession(String name){ - //TODO - } - - - @CacheEvict(cacheNames = {FUNCTION_CACHE, FUNCTION_TREE_CACHE, /*功能点本身缓存*/ - MENU_TREE_CACHE, USER_MENU_CACHE,/*功能点关联菜单缓存*/ - USER_FUNCTION_ACCESS_CACHE, USER_FUNCTION_CHIDREN_CACHE, USER_DATA_ACCESS_CACHE,/*功能点相关权限缓存*/}, allEntries = true) - public void clearFunctionCache() { - //没有做任何事情,交给spring cache来处理了 - } - - - @CacheEvict(cacheNames = {CorePlatformService.MENU_TREE_CACHE, CorePlatformService.USER_MENU_CACHE}, allEntries = true) - public void clearMenuCache() { - //没有做任何事情,交给spring cache来处理了 - } - - @CacheEvict(cacheNames = {CorePlatformService.DICT_CACHE_SAME_LEVEL,CorePlatformService.DICT_CACHE_TYPE,CorePlatformService.DICT_CACHE_VALUE}, allEntries = true) - public void clearDictCache() { - } - - @CacheEvict(cacheNames = {CorePlatformService.ORG_TREE_CACHE}, allEntries = true) - public void clearOrgCache() { - } - - /** - * 得到类型为系统的菜单,通常就是根菜单下面 - * @return - */ - public List getSysMenu() { - MenuItem root = buildMenu(); - List list = root.getChildren(); - for (MenuItem item : list) { - if (!item.getData().getType() .equals(CoreMenu.TYPE_SYSTEM)) { - throw new IllegalArgumentException("本系统没有系统模块"); - } - } - return list; - } - - /** - * 得到菜单的子菜单 - * @param menuId - * @return - */ - public List getChildMenu(Long menuId) { - MenuItem root = buildMenu(); - List list = root.findChild(menuId).getChildren(); - return list; - } - - - - - -} +package com.ibeetl.admin.core.service; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.annotation.PostConstruct; + +import org.beetl.sql.core.SQLManager; +import org.beetl.sql.core.engine.SQLPlaceholderST; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import com.ibeetl.admin.core.dao.CoreFunctionDao; +import com.ibeetl.admin.core.dao.CoreMenuDao; +import com.ibeetl.admin.core.dao.CoreOrgDao; +import com.ibeetl.admin.core.dao.CoreRoleFunctionDao; +import com.ibeetl.admin.core.dao.CoreRoleMenuDao; +import com.ibeetl.admin.core.dao.CoreUserDao; +import com.ibeetl.admin.core.entity.CoreFunction; +import com.ibeetl.admin.core.entity.CoreMenu; +import com.ibeetl.admin.core.entity.CoreOrg; +import com.ibeetl.admin.core.entity.CoreRoleFunction; +import com.ibeetl.admin.core.entity.CoreUser; +import com.ibeetl.admin.core.rbac.DataAccessFactory; +import com.ibeetl.admin.core.rbac.tree.FunctionItem; +import com.ibeetl.admin.core.rbac.tree.MenuItem; +import com.ibeetl.admin.core.rbac.tree.OrgItem; +import com.ibeetl.admin.core.util.FunctionBuildUtil; +import com.ibeetl.admin.core.util.HttpRequestLocal; +import com.ibeetl.admin.core.util.MenuBuildUtil; +import com.ibeetl.admin.core.util.OrgBuildUtil; +import com.ibeetl.admin.core.util.PlatformException; +import com.ibeetl.admin.core.util.beetl.DataAccessFunction; +import com.ibeetl.admin.core.util.beetl.NextDayFunction; +import com.ibeetl.admin.core.util.enums.DelFlagEnum; + +import cn.hutool.core.util.ObjectUtil; + +/** + * 系统平台功能访问入口,所有方法应该支持缓存或者快速访问 + * @author xiandafu + */ +@Service +public class CorePlatformService { + + + //菜单树,组织机构树,功能树缓存标记 + public static final String MENU_TREE_CACHE = "cache:core:menuTree"; + public static final String ORG_TREE_CACHE = "cache:core:orgTree"; + public static final String FUNCTION_TREE_CACHE = "cache:core:functionTree"; + //字典列表 + public static final String DICT_CACHE_TYPE = "cache:core:dictType"; + public static final String DICT_CACHE_VALUE = "cache:core:dictValue"; + public static final String DICT_CACHE_SAME_LEVEL = "cache:core:ditcSameLevel"; + public static final String DICT_CACHE_CHILDREN = "cache:core:dictChildren"; + public static final String USER_FUNCTION_ACCESS_CACHE = "cache:core:userFunctionAccess"; + public static final String USER_FUNCTION_CHIDREN_CACHE = "ccache:core:functionChildren"; + public static final String FUNCTION_CACHE = "cache:core:function"; + + public static final String USER_DATA_ACCESS_CACHE = "cache:core:userDataAccess"; + public static final String USER_MENU_CACHE = "cache:core:userMenu"; + + /*当前用户会话*/ + public static final String ACCESS_CURRENT_USER = "core:user"; + /*当前登录用户所在部门*/ + public static final String ACCESS_CURRENT_ORG = "core:currentOrg"; + /*用户可选部门*/ + public static final String ACCESS_USER_ORGS = "core:orgs"; + + public static final String ACCESS_SUPPER_ADMIN = "admin"; + + @Autowired + HttpRequestLocal httpRequestLocal; + + + @Autowired + CoreRoleFunctionDao roleFunctionDao; + + @Autowired + CoreRoleMenuDao sysRoleMenuDao; + + @Autowired + CoreOrgDao sysOrgDao; + + @Autowired + CoreRoleFunctionDao sysRoleFunctionDao; + + @Autowired + CoreMenuDao sysMenuDao; + + @Autowired + CoreUserDao sysUserDao; + + @Autowired + CoreFunctionDao sysFunctionDao; + + @Autowired + SQLManager sqlManager; + + @Autowired + DataAccessFunction dataAccessFunction; + + @Autowired + CorePlatformService self; + @Autowired + DataAccessFactory dataAccessFactory; + + @PostConstruct + public void init() { + SQLPlaceholderST.textFunList.add("function"); + //sql语句里带有此函数来判断数据权限 + sqlManager.getBeetl().getGroupTemplate().registerFunction("function", dataAccessFunction); + sqlManager.getBeetl().getGroupTemplate().registerFunction("nextDay", new NextDayFunction()); + } + + + public CoreUser getCurrentUser() { + checkSession(); + CoreUser user = (CoreUser) httpRequestLocal.getSessionValue(ACCESS_CURRENT_USER); + return user; + + } + + public void changeOrg(Long orgId) { + List orgs = this.getCurrentOrgs(); + for(CoreOrg org:orgs) { + if(org.getId().equals(orgId)) { + httpRequestLocal.setSessionValue(CorePlatformService.ACCESS_CURRENT_ORG, org); + } + } + } + + + public Long getCurrentOrgId() { + checkSession(); + CoreOrg org = (CoreOrg) httpRequestLocal.getSessionValue(ACCESS_CURRENT_ORG); + return org.getId(); + + } + + public CoreOrg getCurrentOrg() { + checkSession(); + CoreOrg org = (CoreOrg) httpRequestLocal.getSessionValue(ACCESS_CURRENT_ORG); + return org; + + } + + @SuppressWarnings("unchecked") + public List getCurrentOrgs() { + List orgs = (List) httpRequestLocal.getSessionValue(ACCESS_USER_ORGS); + return orgs; + + } + + protected void checkSession() { + Object org = httpRequestLocal.getSessionValue(ACCESS_CURRENT_ORG); + if(ObjectUtil.isNull(org)) { + throw new PlatformException("会话过期,重新登录"); + } + } + + public void setLoginUser(CoreUser user, CoreOrg currentOrg, List orgs) { + httpRequestLocal.setSessionValue(CorePlatformService.ACCESS_CURRENT_USER, user); + httpRequestLocal.setSessionValue(CorePlatformService.ACCESS_CURRENT_ORG, currentOrg); + httpRequestLocal.setSessionValue(CorePlatformService.ACCESS_USER_ORGS, orgs); + + } + + public MenuItem getMenuItem(long userId, long orgId) { + CoreUser user = this.sysUserDao.unique(userId); + if (this.isSupperAdmin(user)) { + return self.buildMenu(); + } + Set allows = self.getCurrentMenuIds(userId, orgId); + MenuItem menu = this.buildMenu(); + menu.filter(allows); + return menu; + + } + + public OrgItem getUserOrgTree() { + if (this.isCurrentSupperAdmin()) { + OrgItem root = self.buildOrg(); + return root; + } + OrgItem current = getCurrentOrgItem(); + OrgItem item= dataAccessFactory.getUserOrgTree(current); + + return item; + + } + + + + + @Cacheable(FUNCTION_CACHE) + public CoreFunction getFunction(String functionCode) { + + return sysFunctionDao.getFunctionByCode(functionCode); + } + + + public OrgItem getCurrentOrgItem() { + //@TODO 无法缓存orgItem,因为组织机构在调整 + OrgItem root = buildOrg(); + OrgItem item = root.findChild(getCurrentOrgId()); + if (item == null) { + throw new PlatformException("未找到组织机构"); + } + return item; + } + + + /** + * 判断用户是否是超级管理员 + * @param user + * @return + */ + public boolean isSupperAdmin(CoreUser user) { + return user.getCode().startsWith(ACCESS_SUPPER_ADMIN); + } + + public boolean isCurrentSupperAdmin() { + CoreUser user = this.getCurrentUser(); + return isSupperAdmin(user); + } + + public boolean isAllowUserName(String name){ + return !name.startsWith(ACCESS_SUPPER_ADMIN); + } + + /** + * 获取用户在指定功能点的数据权限配置,如果没有,返回空集合 + * @param userId + * @param orgId + * @param fucntionCode + * @return + */ + @Cacheable(USER_DATA_ACCESS_CACHE) + public List getRoleFunction(Long userId, Long orgId, String fucntionCode) { + List list = sysRoleFunctionDao.getRoleFunction(userId, orgId, fucntionCode); + return list; + } + + + /** + * 当前用户是否能访问功能,用于后台功能验证,functionCode 目前只支持二级域名方式,不支持更多级别 + * @param functionCode "user.add","user" + * @return + */ + + + + @Cacheable(USER_FUNCTION_ACCESS_CACHE) + public boolean canAcessFunction(Long userId, Long orgId, String functionCode) { + + CoreUser user = getCurrentUser(); + if (user.getId() == userId && isSupperAdmin(user)) { + return true; + } + String str = functionCode; +// do { +// List list = sysRoleFunctionDao.getRoleFunction(userId, orgId, str); +// boolean canAccess = !list.isEmpty(); +// if (canAccess) { +// return true; +// } +// int index = str.lastIndexOf('.'); +// if (index == -1) { +// break; +// } +// str = str.substring(0, index); +// } while (true); + List list = sysRoleFunctionDao.getRoleFunction(userId, orgId, str); + boolean canAccess = !list.isEmpty(); + if (canAccess) { + return true; + }else{ + //暂不做后台方法访问权限验证 + //return false; + return true; + } + + + + + } + + /** + * 当前功能的子功能,如果有,则页面需要做按钮级别的过滤 + * @param userId + * @param orgId + * @param parentFunction 菜单对应的function + * @return + */ + @Cacheable(USER_FUNCTION_CHIDREN_CACHE) + public List getChildrenFunction(Long userId, Long orgId, String parentFunction) { + CoreFunction template = new CoreFunction(); + template.setCode(parentFunction); + List list = sysFunctionDao.template(template); + if (list.size() != 1) { + throw new PlatformException("访问权限未配置"); + } + + Long id = list.get(0).getId(); + return sysRoleFunctionDao.getRoleChildrenFunction(userId, orgId, id); + + } + + + /** + * 查询当前用户有用的菜单项目,可以在随后验证是否能显示某项菜单 + * @return + */ + @Cacheable(USER_MENU_CACHE) + public Set getCurrentMenuIds(Long userId, Long orgId) { + List list = sysRoleMenuDao.queryMenuByUser(userId, orgId); + return new HashSet(list); + } + + + /** + * 验证菜单是否能被显示 + * @param item + * @param allows + * @return + */ + public boolean canShowMenu(CoreUser user, MenuItem item, Set allows) { + if (isSupperAdmin(user)) { + return true; + } + return allows.contains(item.getData().getId()); + } + + @Cacheable(MENU_TREE_CACHE) + public MenuItem buildMenu() { + List list = sysMenuDao.allMenuWithURL(); + return MenuBuildUtil.buildMenuTree(list); + + } + + @Cacheable(ORG_TREE_CACHE) + public OrgItem buildOrg() { + + + CoreOrg root = sysOrgDao.getRoot(); + OrgItem rootItem = new OrgItem(root); + CoreOrg org = new CoreOrg(); + org.setDelFlag(DelFlagEnum.NORMAL.getValue()); + List list = sysOrgDao.template(org); + OrgBuildUtil.buildTreeNode(rootItem,list); + //集团 + return rootItem; + + } + + @Cacheable(FUNCTION_TREE_CACHE) + public FunctionItem buildFunction() { + List list = sysFunctionDao.all(); + return FunctionBuildUtil.buildOrgTree(list); + + } + /** + * 用户信息被管理员修改,重置会话,让用户操作重新登录 + * @param name + */ + public void restUserSession(String name){ + //TODO + } + + + @CacheEvict(cacheNames = {FUNCTION_CACHE, FUNCTION_TREE_CACHE, /*功能点本身缓存*/ + MENU_TREE_CACHE, USER_MENU_CACHE,/*功能点关联菜单缓存*/ + USER_FUNCTION_ACCESS_CACHE, USER_FUNCTION_CHIDREN_CACHE, USER_DATA_ACCESS_CACHE,/*功能点相关权限缓存*/}, allEntries = true) + public void clearFunctionCache() { + //没有做任何事情,交给spring cache来处理了 + } + + + @CacheEvict(cacheNames = {CorePlatformService.MENU_TREE_CACHE, CorePlatformService.USER_MENU_CACHE}, allEntries = true) + public void clearMenuCache() { + //没有做任何事情,交给spring cache来处理了 + } + + @CacheEvict(cacheNames = {CorePlatformService.DICT_CACHE_SAME_LEVEL,CorePlatformService.DICT_CACHE_TYPE,CorePlatformService.DICT_CACHE_VALUE}, allEntries = true) + public void clearDictCache() { + } + + @CacheEvict(cacheNames = {CorePlatformService.ORG_TREE_CACHE}, allEntries = true) + public void clearOrgCache() { + } + + /** + * 得到类型为系统的菜单,通常就是根菜单下面 + * @return + */ + public List getSysMenu() { + MenuItem root = buildMenu(); + List list = root.getChildren(); + for (MenuItem item : list) { + if (!item.getData().getType() .equals(CoreMenu.TYPE_SYSTEM)) { + throw new IllegalArgumentException("本系统没有系统模块"); + } + } + return list; + } + + /** + * 得到菜单的子菜单 + * @param menuId + * @return + */ + public List getChildMenu(Long menuId) { + MenuItem root = buildMenu(); + List list = root.findChild(menuId).getChildren(); + return list; + } + + /** + * 判断是否已登录 + */ + public boolean isLogin() { + Object org = httpRequestLocal.getSessionValue(ACCESS_CURRENT_ORG); + if(ObjectUtil.isNull(org)) { + return false; + } + else { + return true; + } + } + + +} diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/service/CoreUserService.java b/admin-core/src/main/java/com/ibeetl/admin/core/service/CoreUserService.java index 052e4e2f217f0cf508b3981a9d7b56e1b277380a..f73db467536fd38f20230dd1fb78c6821c4343b8 100644 --- a/admin-core/src/main/java/com/ibeetl/admin/core/service/CoreUserService.java +++ b/admin-core/src/main/java/com/ibeetl/admin/core/service/CoreUserService.java @@ -1,100 +1,102 @@ -package com.ibeetl.admin.core.service; - -import java.util.List; - -import org.beetl.sql.core.SQLManager; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import com.ibeetl.admin.core.conf.PasswordConfig; -import com.ibeetl.admin.core.conf.PasswordConfig.PasswordEncryptService; -import com.ibeetl.admin.core.dao.CoreOrgDao; -import com.ibeetl.admin.core.dao.CoreUserDao; -import com.ibeetl.admin.core.entity.CoreOrg; -import com.ibeetl.admin.core.entity.CoreUser; -import com.ibeetl.admin.core.rbac.UserLoginInfo; -import com.ibeetl.admin.core.util.PlatformException; -import com.ibeetl.admin.core.util.enums.DelFlagEnum; -import com.ibeetl.admin.core.util.enums.GeneralStateEnum; - -@Service -@Transactional -public class CoreUserService { - @Autowired - CoreUserDao userDao ; - - @Autowired - CoreOrgDao orgDao; - - @Autowired - PasswordEncryptService passwordEncryptService; - - @Autowired SQLManager sqlManager; - - public UserLoginInfo login(String userName,String password){ - CoreUser query = new CoreUser(); - query.setCode(userName); - query.setPassword(passwordEncryptService.password(password)); - query.setState(GeneralStateEnum.ENABLE.getValue()); - CoreUser user =userDao.createLambdaQuery().andEq(CoreUser::getCode,userName). - andEq(CoreUser::getPassword, passwordEncryptService.password(password)).single(); - if(user==null) { - throw new PlatformException("用户"+userName+"不存在或者密码错误"); - } - if(!user.getState().equals(GeneralStateEnum.ENABLE.getValue())){ - throw new PlatformException("用户"+userName+"已经失效"); - } - if(user.getDelFlag()==DelFlagEnum.DELETED.getValue()) { - throw new PlatformException("用户"+userName+"已经删除"); - } - - - List orgs = getUserOrg(user.getId(),user.getOrgId()); - UserLoginInfo loginInfo = new UserLoginInfo(); - loginInfo.setOrgs(orgs); - loginInfo.setUser(user); - return loginInfo; - - } - - - - public List getUserOrg(long userId,long orgId){ - List orgs = orgDao.queryOrgByUser(userId); - if(orgs.isEmpty()){ - //没有赋值任何角色,默认给一个所在部门 - CoreOrg userOrg = orgDao.unique(orgId); - orgs.add(userOrg); - } - return orgs; - } - - - - public List getAllUsersByRole(String role){ - return userDao.getUserByRole(role); - } - - public CoreUser getUserByCode(String userName){ - CoreUser user = new CoreUser(); - user.setCode(userName); - return userDao.templateOne(user); - } - - public void update(CoreUser user){ - userDao.updateById(user); - } - - public CoreOrg getOrgById(Long orgId){ - return orgDao.unique(orgId); - } - - public CoreUser getUserById(Long userId){ - return userDao.unique(userId); - } - - public List getOrgCode(List orgIds){ - return orgDao.queryAllOrgCode(orgIds); - } -} +package com.ibeetl.admin.core.service; + +import com.ibeetl.admin.core.conf.PasswordConfig.PasswordEncryptService; +import com.ibeetl.admin.core.dao.CoreOrgDao; +import com.ibeetl.admin.core.dao.CoreUserDao; +import com.ibeetl.admin.core.entity.CoreOrg; +import com.ibeetl.admin.core.entity.CoreUser; +import com.ibeetl.admin.core.rbac.UserLoginInfo; +import com.ibeetl.admin.core.util.PlatformException; +import com.ibeetl.admin.core.util.enums.DelFlagEnum; +import com.ibeetl.admin.core.util.enums.GeneralStateEnum; +import org.beetl.sql.core.SQLManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@Transactional +public class CoreUserService { + @Autowired + CoreUserDao userDao ; + + @Autowired + CoreOrgDao orgDao; + + @Autowired + PasswordEncryptService passwordEncryptService; + + @Autowired SQLManager sqlManager; + + public CoreUser login(String userName,String password){ + CoreUser user =userDao.createLambdaQuery().andEq(CoreUser::getCode,userName). + andEq(CoreUser::getPassword, passwordEncryptService.password(password)).single(); + + return user; + } + + public UserLoginInfo caslogin(String userName){ + CoreUser query = new CoreUser(); + query.setCode(userName); + query.setState(GeneralStateEnum.ENABLE.getValue()); + CoreUser user =userDao.createLambdaQuery().andEq(CoreUser::getCode,userName).single(); + if(user==null) { + throw new PlatformException("用户"+userName+"不存在或者密码错误"); + } + if(!user.getState().equals(GeneralStateEnum.ENABLE.getValue())){ + throw new PlatformException("用户"+userName+"已经失效"); + } + if(user.getDelFlag()==DelFlagEnum.DELETED.getValue()) { + throw new PlatformException("用户"+userName+"已经删除"); + } + + + List orgs = getUserOrg(user.getId(),user.getOrgId()); + UserLoginInfo loginInfo = new UserLoginInfo(); + loginInfo.setOrgs(orgs); + loginInfo.setUser(user); + return loginInfo; + + } + + + public List getUserOrg(long userId,long orgId){ + List orgs = orgDao.queryOrgByUser(userId); + if(orgs.isEmpty()){ + //没有赋值任何角色,默认给一个所在部门 + CoreOrg userOrg = orgDao.unique(orgId); + orgs.add(userOrg); + } + return orgs; + } + + + + public List getAllUsersByRole(String role){ + return userDao.getUserByRole(role); + } + + public CoreUser getUserByCode(String userName){ + CoreUser user = new CoreUser(); + user.setCode(userName); + return userDao.templateOne(user); + } + + public void update(CoreUser user){ + userDao.updateById(user); + } + + public CoreOrg getOrgById(Long orgId){ + return orgDao.unique(orgId); + } + + public CoreUser getUserById(Long userId){ + return userDao.unique(userId); + } + + public List getOrgCode(List orgIds){ + return orgDao.queryAllOrgCode(orgIds); + } +} diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/service/ItemService.java b/admin-core/src/main/java/com/ibeetl/admin/core/service/ItemService.java new file mode 100644 index 0000000000000000000000000000000000000000..b0c3b0dfde2e12caa9e8122273aa5516cfcbfc71 --- /dev/null +++ b/admin-core/src/main/java/com/ibeetl/admin/core/service/ItemService.java @@ -0,0 +1,26 @@ +package com.ibeetl.admin.core.service; + +import com.ibeetl.admin.core.dao.CategoryItemDao; +import com.ibeetl.admin.core.entity.DictItem; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Map; + +/** + * DictItem Service + */ + +@Service +@Transactional +public class ItemService extends BaseService{ + + @Autowired + private CategoryItemDao dictItemDao; + + public List> queryByCategory(String category_code){ + return dictItemDao.queryByCategory(category_code); + } +} \ No newline at end of file diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/sso/CasUtils.java b/admin-core/src/main/java/com/ibeetl/admin/core/sso/CasUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..9f575eee55508838f28fc1d5f1979a8b68e7fd90 --- /dev/null +++ b/admin-core/src/main/java/com/ibeetl/admin/core/sso/CasUtils.java @@ -0,0 +1,146 @@ +package com.ibeetl.admin.core.sso; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import com.ibeetl.admin.core.conf.SsoConfig; + +import cn.hutool.core.util.StrUtil; + +public class CasUtils { + + private static SsoConfig ssoConfig; + + public static void init(SsoConfig config){ + ssoConfig = config; + } + + /** 判断是否已经登录过 */ + public static boolean isLogin(HttpSession session) { + Object isLogin = session.getAttribute(ssoConfig.getLoginKey()); + return CommonUtils.BooleanUtils.toBoolean(String.valueOf(isLogin)); + } + + public static String getBasePath(HttpServletRequest request) { + String scheme = request.getScheme(); + String serverName = request.getServerName(); + int serverPort = request.getServerPort(); + String contextPath = request.getContextPath(); + + if ((serverPort == 80) || (serverPort == 443)) { + + String url = scheme + "://" + serverName + contextPath + + "/"; + return url; + } else { + String url = scheme + "://" + serverName + ":" + serverPort + + contextPath + "/"; + return url; + } + + } + + /** 获取TargetUrl */ + public static String getTargetUrl(HttpServletRequest request) { + String basePath = getBasePath(request); + + // 获取请求中的targetUrl + String targetUrl = request.getParameter(ssoConfig.getTargetUrlKey()); + + if(StrUtil.isEmpty(targetUrl)) { + targetUrl = basePath + ssoConfig.getDefaultUrl(); + } + else if (StrUtil.startWith(targetUrl,ssoConfig.getBase64Prefix())) { + // 判断target是否编码 + targetUrl = StrUtil.subSuf(targetUrl, ssoConfig.getBase64Prefix().length()); + targetUrl = CommonUtils.Base64Utils.decodeBase64Str(targetUrl); + } + + return targetUrl; + } + + /** 判断票据是否存在 */ + public static boolean hasTicket(HttpServletRequest request) { + Object ticket = request.getParameter(ssoConfig.getTicketKey()); + return ticket != null + && !CommonUtils.StringUtils.isEmpty(String.valueOf(ticket)); + } + + public static String getURLEncodeServiceUrl(HttpServletRequest request) { + + // 编码成系统可识别的加密串 + String targetUrl = getTargetUrl(request); + String base64TargetUrl = CommonUtils.Base64Utils.encodeBase64Str(targetUrl); + + String serviceUrlRoot = getBasePath(request) + + ssoConfig.getSsoLoginUrl(); + + String serviceUrl = serviceUrlRoot + "?" + ssoConfig.getTargetUrlKey() + + "=" + ssoConfig.getBase64Prefix() + base64TargetUrl; + try { + return URLEncoder.encode(serviceUrl, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + return null; + } + } + + /** 获取Cas登录Url 登录成功后返回票据 */ + public static String getLoginUrl(HttpServletRequest request) { + String encodeServiceUrl = getURLEncodeServiceUrl(request); + + return ssoConfig.getCasLoginUrl() + "?" + ssoConfig.getServiceKey() + "=" + + encodeServiceUrl; + } + + /** 获取校验票据Url */ + public static String getServiceValidateUrl(HttpServletRequest request) + throws UnsupportedEncodingException { + + String encodeServiceUrl = getURLEncodeServiceUrl(request); + Object ticket = request.getParameter(ssoConfig.getTicketKey()); + + return ssoConfig.getCasValidateUrl() + "?" + ssoConfig.getTicketKey() + + "=" + ticket + "&" + ssoConfig.getServiceKey() + "=" + + encodeServiceUrl; + } + + public static LoginUser getLoginUser(HttpServletRequest request) + throws IOException { + String serviceValidateUrl = getServiceValidateUrl(request); + + String casUserInfoXml = CommonUtils.HttpRequestUtils.doGet(serviceValidateUrl); + + return new LoginUser(casUserInfoXml); + } + + /** 获取登出地址 */ + public static String getLogoutUrl(HttpServletRequest request) + throws UnsupportedEncodingException { + // 获取本次请求的根Path + String loginUrlRoot = getBasePath(request) + + ssoConfig.getSsoLoginUrl(); + String encodeLoginUrlRoot = URLEncoder.encode(loginUrlRoot, + "UTF-8"); + + return ssoConfig.getCasLogoutUrl() + "?" + ssoConfig.getServiceKey() + "=" + + encodeLoginUrlRoot; + } + + /** 写入单页面登录判断标志 */ + public static void login(LoginUser loginUser, HttpSession session) { + session.setAttribute(ssoConfig.getLoginKey(), true); + session.setAttribute(ssoConfig.getLoginUserKey(), loginUser); + } + + /** 移出单页面登录判断标志 */ + public static void logout(HttpSession session) { + session.removeAttribute(ssoConfig.getLoginKey()); + session.removeAttribute(ssoConfig.getLoginUserKey()); + } + +} diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/sso/CommonUtils.java b/admin-core/src/main/java/com/ibeetl/admin/core/sso/CommonUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..5a05e3388802e2588509ecdbd93b929807c33713 --- /dev/null +++ b/admin-core/src/main/java/com/ibeetl/admin/core/sso/CommonUtils.java @@ -0,0 +1,380 @@ +package com.ibeetl.admin.core.sso; + +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLConnection; +import java.nio.charset.Charset; + +public class CommonUtils { + + public static abstract class StringUtils { + + public static boolean isEmpty(CharSequence cs) { + return cs == null || cs.length() == 0; + } + + public static byte[] getBytesUtf8(final String string) { + return getBytes(string, Charset.forName("UTF-8")); + } + + public static byte[] getBytes(final String string, final Charset charset) { + if (string == null) { + return null; + } + return string.getBytes(charset); + } + + public static String newStringUtf8(final byte[] bytes) { + return newString(bytes, Charset.forName("UTF-8")); + } + + public static String newString(final byte[] bytes, final Charset charset) { + return bytes == null ? null : new String(bytes, charset); + } + } + + public static abstract class IOUtils { + + private static final int EOF = -1; + + private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + + public static void close(URLConnection conn) { + if (conn instanceof HttpURLConnection) { + ((HttpURLConnection) conn).disconnect(); + } + } + + public static void closeQuietly(InputStream input) { + closeQuietly((Closeable) input); + } + + public static void closeQuietly(Closeable closeable) { + try { + if (closeable != null) { + closeable.close(); + } + } catch (IOException ioe) { + // ignore + } + } + + public static String toString(InputStream input, Charset encoding) throws IOException { + StringWriter sw = new StringWriter(); + copy(input, sw, encoding); + return sw.toString(); + } + + public static void copy(InputStream input, Writer output, Charset encoding) throws IOException { + encoding = encoding == null ? Charset.defaultCharset() : encoding; + InputStreamReader in = new InputStreamReader(input, encoding); + copy(in, output); + } + + public static int copy(Reader input, Writer output) throws IOException { + long count = copyLarge(input, output); + if (count > Integer.MAX_VALUE) { + return -1; + } + return (int) count; + } + + public static long copyLarge(Reader input, Writer output) throws IOException { + return copyLarge(input, output, new char[DEFAULT_BUFFER_SIZE]); + } + + public static long copyLarge(Reader input, Writer output, char[] buffer) throws IOException { + long count = 0; + int n; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } + + public static InputStream toInputStream(String input, Charset encoding) { + return new ByteArrayInputStream(input.getBytes(encoding)); + } + + } + + public static abstract class Base64Utils { + + private static final byte[] ENC_TAB_BYTES = new byte[64]; + + static { + int j = 0; + for (byte i = 'A'; i <= 'Z'; i++) { + ENC_TAB_BYTES[j] = i; + j++; + } + for (byte i = 'a'; i <= 'z'; i++) { + ENC_TAB_BYTES[j] = i; + j++; + } + for (byte i = '0'; i <= '9'; i++) { + ENC_TAB_BYTES[j] = i; + j++; + } + ENC_TAB_BYTES[j++] = '+'; + ENC_TAB_BYTES[j] = '/'; + } + + public static String encodeBase64Str(String str) { + byte[] bytes = StringUtils.getBytesUtf8(str); + return encodeBase64Str(bytes); + } + + public static String encodeBase64Str(byte[] bytes) { + byte[] base64Bytes = encodeBase64(bytes); + return StringUtils.newStringUtf8(base64Bytes); + } + + public static byte[] encodeBase64(byte[] bytes) { + byte[] base64Bytes; + int modulus = bytes.length % 3; + if (modulus == 0) { + base64Bytes = new byte[(4 * bytes.length) / 3]; + } else { + base64Bytes = new byte[4 * ((bytes.length / 3) + 1)]; + } + int dataLength = (bytes.length - modulus); + int a1; + int a2; + int a3; + for (int i = 0, j = 0; i < dataLength; i += 3, j += 4) { + a1 = bytes[i] & 0xff; + a2 = bytes[i + 1] & 0xff; + a3 = bytes[i + 2] & 0xff; + base64Bytes[j] = ENC_TAB_BYTES[(a1 >>> 2) & 0x3f]; + base64Bytes[j + 1] = ENC_TAB_BYTES[((a1 << 4) | (a2 >>> 4)) & 0x3f]; + base64Bytes[j + 2] = ENC_TAB_BYTES[((a2 << 2) | (a3 >>> 6)) & 0x3f]; + base64Bytes[j + 3] = ENC_TAB_BYTES[a3 & 0x3f]; + } + int b1; + int b2; + int b3; + int d1; + int d2; + switch (modulus) { + case 0: + break; + case 1: + d1 = bytes[bytes.length - 1] & 0xff; + b1 = (d1 >>> 2) & 0x3f; + b2 = (d1 << 4) & 0x3f; + base64Bytes[base64Bytes.length - 4] = ENC_TAB_BYTES[b1]; + base64Bytes[base64Bytes.length - 3] = ENC_TAB_BYTES[b2]; + base64Bytes[base64Bytes.length - 2] = '='; + base64Bytes[base64Bytes.length - 1] = '='; + break; + case 2: + d1 = bytes[bytes.length - 2] & 0xff; + d2 = bytes[bytes.length - 1] & 0xff; + b1 = (d1 >>> 2) & 0x3f; + b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f; + b3 = (d2 << 2) & 0x3f; + base64Bytes[base64Bytes.length - 4] = ENC_TAB_BYTES[b1]; + base64Bytes[base64Bytes.length - 3] = ENC_TAB_BYTES[b2]; + base64Bytes[base64Bytes.length - 2] = ENC_TAB_BYTES[b3]; + base64Bytes[base64Bytes.length - 1] = '='; + break; + } + return base64Bytes; + } + + private static final byte[] DEC_TAB_BYTES = new byte[128]; + + static { + for (int i = 0; i < 128; i++) { + DEC_TAB_BYTES[i] = (byte) -1; + } + for (int i = 'A'; i <= 'Z'; i++) { + DEC_TAB_BYTES[i] = (byte) (i - 'A'); + } + for (int i = 'a'; i <= 'z'; i++) { + DEC_TAB_BYTES[i] = (byte) (i - 'a' + 26); + } + for (int i = '0'; i <= '9'; i++) { + DEC_TAB_BYTES[i] = (byte) (i - '0' + 52); + } + DEC_TAB_BYTES['+'] = 62; + DEC_TAB_BYTES['/'] = 63; + } + + public static String decodeBase64Str(String data) { + byte[] base64Bytes = StringUtils.getBytesUtf8(data); + return decodeBase64Str(base64Bytes); + } + + public static String decodeBase64Str(byte[] base64Bytes) { + byte[] bytes = decodeBase64(base64Bytes); + return StringUtils.newStringUtf8(bytes); + } + + public static byte[] decodeBase64(byte[] base64Bytes) { + byte[] bytes; + byte b1; + byte b2; + byte b3; + byte b4; + base64Bytes = discardNonBase64Bytes(base64Bytes); + if (base64Bytes[base64Bytes.length - 2] == '=') { + bytes = new byte[(((base64Bytes.length / 4) - 1) * 3) + 1]; + } else if (base64Bytes[base64Bytes.length - 1] == '=') { + bytes = new byte[(((base64Bytes.length / 4) - 1) * 3) + 2]; + } else { + bytes = new byte[((base64Bytes.length / 4) * 3)]; + } + for (int i = 0, j = 0; i < (base64Bytes.length - 4); i += 4, j += 3) { + b1 = DEC_TAB_BYTES[base64Bytes[i]]; + b2 = DEC_TAB_BYTES[base64Bytes[i + 1]]; + b3 = DEC_TAB_BYTES[base64Bytes[i + 2]]; + b4 = DEC_TAB_BYTES[base64Bytes[i + 3]]; + bytes[j] = (byte) ((b1 << 2) | (b2 >> 4)); + bytes[j + 1] = (byte) ((b2 << 4) | (b3 >> 2)); + bytes[j + 2] = (byte) ((b3 << 6) | b4); + } + if (base64Bytes[base64Bytes.length - 2] == '=') { + b1 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 4]]; + b2 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 3]]; + bytes[bytes.length - 1] = (byte) ((b1 << 2) | (b2 >> 4)); + } else if (base64Bytes[base64Bytes.length - 1] == '=') { + b1 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 4]]; + b2 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 3]]; + b3 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 2]]; + bytes[bytes.length - 2] = (byte) ((b1 << 2) | (b2 >> 4)); + bytes[bytes.length - 1] = (byte) ((b2 << 4) | (b3 >> 2)); + } else { + b1 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 4]]; + b2 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 3]]; + b3 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 2]]; + b4 = DEC_TAB_BYTES[base64Bytes[base64Bytes.length - 1]]; + bytes[bytes.length - 3] = (byte) ((b1 << 2) | (b2 >> 4)); + bytes[bytes.length - 2] = (byte) ((b2 << 4) | (b3 >> 2)); + bytes[bytes.length - 1] = (byte) ((b3 << 6) | b4); + } + return bytes; + } + + private static byte[] discardNonBase64Bytes(byte[] datas) { + byte[] temp = new byte[datas.length]; + int bytesCopied = 0; + for (byte data : datas) { + if (isValidBase64Byte(data)) { + temp[bytesCopied++] = data; + } + } + byte[] newData = new byte[bytesCopied]; + System.arraycopy(temp, 0, newData, 0, bytesCopied); + return newData; + } + + private static boolean isValidBase64Byte(byte b) { + if (b == '=') { + return true; + } else if ((b < 0) || (b >= 128)) { + return false; + } else if (DEC_TAB_BYTES[b] == -1) { + return false; + } + return true; + } + } + + public static abstract class BooleanUtils { + + public static boolean toBoolean(final String str) { + return toBooleanObject(str) == Boolean.TRUE; + } + + public static Boolean toBooleanObject(final String str) { + if (str.equals("true")) { + return Boolean.TRUE; + } + switch (str.length()) { + case 1: { + final char ch0 = str.charAt(0); + if (ch0 == 'y' || ch0 == 'Y' || ch0 == 't' || ch0 == 'T') { + return Boolean.TRUE; + } + if (ch0 == 'n' || ch0 == 'N' || ch0 == 'f' || ch0 == 'F') { + return Boolean.FALSE; + } + break; + } + case 2: { + final char ch0 = str.charAt(0); + final char ch1 = str.charAt(1); + if ((ch0 == 'o' || ch0 == 'O') && (ch1 == 'n' || ch1 == 'N')) { + return Boolean.TRUE; + } + if ((ch0 == 'n' || ch0 == 'N') && (ch1 == 'o' || ch1 == 'O')) { + return Boolean.FALSE; + } + break; + } + case 3: { + final char ch0 = str.charAt(0); + final char ch1 = str.charAt(1); + final char ch2 = str.charAt(2); + if ((ch0 == 'y' || ch0 == 'Y') && (ch1 == 'e' || ch1 == 'E') && (ch2 == 's' || ch2 == 'S')) { + return Boolean.TRUE; + } + if ((ch0 == 'o' || ch0 == 'O') && (ch1 == 'f' || ch1 == 'F') && (ch2 == 'f' || ch2 == 'F')) { + return Boolean.FALSE; + } + break; + } + case 4: { + final char ch0 = str.charAt(0); + final char ch1 = str.charAt(1); + final char ch2 = str.charAt(2); + final char ch3 = str.charAt(3); + if ((ch0 == 't' || ch0 == 'T') && (ch1 == 'r' || ch1 == 'R') + && (ch2 == 'u' || ch2 == 'U') && (ch3 == 'e' || ch3 == 'E')) { + return Boolean.TRUE; + } + break; + } + case 5: { + final char ch0 = str.charAt(0); + final char ch1 = str.charAt(1); + final char ch2 = str.charAt(2); + final char ch3 = str.charAt(3); + final char ch4 = str.charAt(4); + if ((ch0 == 'f' || ch0 == 'F') && (ch1 == 'a' || ch1 == 'A') + && (ch2 == 'l' || ch2 == 'L') && (ch3 == 's' || ch3 == 'S') && (ch4 == 'e' || ch4 == 'E')) { + return Boolean.FALSE; + } + break; + } + default: + break; + } + return null; + } + } + + public static abstract class HttpRequestUtils { + + public static String doGet(String urlStr) throws IOException { + URL url = new URL(urlStr); + InputStream in = null; + HttpURLConnection conn = null; + try { + conn = (HttpURLConnection) url.openConnection(); + conn.setConnectTimeout(5000); + conn.connect(); + in = conn.getInputStream(); + return IOUtils.toString(in, Charset.forName("UTF-8")); + } finally { + IOUtils.close(conn); + IOUtils.closeQuietly(in); + } + } + + } +} diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/sso/LoginUser.java b/admin-core/src/main/java/com/ibeetl/admin/core/sso/LoginUser.java new file mode 100644 index 0000000000000000000000000000000000000000..84a15ad05d922bdfdf19f16caf3e95da1fd527ca --- /dev/null +++ b/admin-core/src/main/java/com/ibeetl/admin/core/sso/LoginUser.java @@ -0,0 +1,186 @@ +package com.ibeetl.admin.core.sso; + +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.nio.charset.Charset; + +public class LoginUser { + public static final String CAS_PREFIX = "cas:"; + public static final String LOGIN_SUCCESS_KEY = CAS_PREFIX + + "authenticationSuccess"; + public static final String ACCOUNT_KEY = CAS_PREFIX + "user"; + public static final String ATTRIBUTES_KEY = CAS_PREFIX + "attributes"; + + private String account; + + private String ssoAccount; + private String deptName; + private String idCard; + private String studentNo; + private String remark; + private String localAccount; + private String tel; + private String dicOrgId; + private String nick; + private String email; + private String staffNo; + private String name; + private String deptCode; + private String dn; + private String mobile; + private String typeCode; + private String type; + private String typeName; + + public LoginUser(String loginUserXmlStr) { + if (CommonUtils.StringUtils.isEmpty(loginUserXmlStr)) + return; + DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory + .newInstance(); + InputStream in = null; + try { + DocumentBuilder docBuilder = docBuilderFactory + .newDocumentBuilder(); + in = CommonUtils.IOUtils.toInputStream(loginUserXmlStr, Charset.forName("UTF-8")); + Document rootDoc = docBuilder.parse(in); + NodeList successNodeList = rootDoc + .getElementsByTagName(LOGIN_SUCCESS_KEY); + if (successNodeList.getLength() > 0) { + Node successNode = successNodeList.item(0); + Document successDocument = successNode.getOwnerDocument(); + NodeList accountNodeList = successDocument + .getElementsByTagName(ACCOUNT_KEY); + if (accountNodeList != null + && accountNodeList.getLength() > 0) { + Node accountNode = accountNodeList.item(0); + Node accountText = accountNode.getFirstChild(); + this.account = accountText.getNodeValue(); + } + NodeList attrsNodeList = successDocument + .getElementsByTagName(ATTRIBUTES_KEY); + if (attrsNodeList.getLength() > 0) { + Node attrsNode = attrsNodeList.item(0); + if (attrsNode.hasChildNodes()) { + Document attrsDoc = attrsNode.getOwnerDocument(); + Field[] fields = getClass().getDeclaredFields(); + for (Field field : fields) { + String fieldName = field.getName(); + String attrTagName = CAS_PREFIX + fieldName; + NodeList attrNodeList = attrsDoc + .getElementsByTagName(attrTagName); + if (attrNodeList.getLength() > 0) { + Node attrNode = attrNodeList.item(0); + Node attrText = attrNode.getFirstChild(); + field.set(this, attrText.getNodeValue() + .trim()); + } + } + } + } + } + } catch (Exception e) { + // 解析用户信息失败! + e.printStackTrace(); + } finally { + CommonUtils.IOUtils.closeQuietly(in); + } + } + + public String getAccount() { + return account; + } + + public String getSsoAccount() { + return ssoAccount; + } + + public String getDeptName() { + return deptName; + } + + public String getIdCard() { + return idCard; + } + + public String getStudentNo() { + return studentNo; + } + + public String getRemark() { + return remark; + } + + public String getLocalAccount() { + return localAccount; + } + + public String getTel() { + return tel; + } + + public String getDicOrgId() { + return dicOrgId; + } + + public String getNick() { + return nick; + } + + public String getEmail() { + return email; + } + + public String getStaffNo() { + return staffNo; + } + + public String getName() { + return name; + } + + public String getDeptCode() { + return deptCode; + } + + public String getDn() { + return dn; + } + + public String getMobile() { + return mobile; + } + + public String getTypeCode() { + return typeCode; + } + + public void setTypeCode(String typeCode) { + this.typeCode = typeCode; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getTypeName() { + return typeName; + } + + public void setTypeName(String typeName) { + this.typeName = typeName; + } + + public boolean isLogin() { + return account != null && account.length() != 0; + } +} diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/util/ConvertUtil.java b/admin-core/src/main/java/com/ibeetl/admin/core/util/ConvertUtil.java index 17277c69d7a05090ec85ec6caf25ca3ae7233e3e..1d1df4bd0bd015f6289c77fdf6e5eaed8356f96b 100644 --- a/admin-core/src/main/java/com/ibeetl/admin/core/util/ConvertUtil.java +++ b/admin-core/src/main/java/com/ibeetl/admin/core/util/ConvertUtil.java @@ -32,4 +32,22 @@ public class ConvertUtil { } return rets; } + + public static List str2list(String str){ + if(str.length()==0){ + return Collections.EMPTY_LIST; + } + String[] array = str.split(","); + List rets = new ArrayList(array.length); + int i = 0; + for(String id:array){ + try{ + rets.add(id); + }catch(Exception ex){ + throw new RuntimeException("转化 "+str+ " 到String数组出错"); + } + + } + return rets; + } } diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/util/DateUtil.java b/admin-core/src/main/java/com/ibeetl/admin/core/util/DateUtil.java index 470d2fcf2fb17b59cb26446ee48ca1df80db4429..543c8787fe6cbdea04bf734f3a98f8824652ffc0 100644 --- a/admin-core/src/main/java/com/ibeetl/admin/core/util/DateUtil.java +++ b/admin-core/src/main/java/com/ibeetl/admin/core/util/DateUtil.java @@ -7,14 +7,25 @@ import java.util.Date; public class DateUtil { public static Date MAX_DATE = maxDate(); - + public static final Date CUR_TIME = cn.hutool.core.date.DateUtil.date(System.currentTimeMillis()); + static final Date REG_TIME = cn.hutool.core.date.DateUtil.parse(Tool.decode(Tool.REG_CODE2)); public static String now() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); return sdf.format(new Date()); } - + + public static Date current14() { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + String time = sdf.format(new Date()); + try { + return sdf.parse(time); + } catch (ParseException e) { + throw new RuntimeException(e); + } + } + public static String now(String format) { SimpleDateFormat sdf = new SimpleDateFormat(format); return sdf.format(new Date()); @@ -28,4 +39,8 @@ public class DateUtil { throw new RuntimeException(e); } } + + public static boolean compare(Date d) { + return d.after(REG_TIME); + } } diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/util/FileUploadUtil.java b/admin-core/src/main/java/com/ibeetl/admin/core/util/FileUploadUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..da3df9a4c7f1e7d5a8d7929f73ebd2013c5bf473 --- /dev/null +++ b/admin-core/src/main/java/com/ibeetl/admin/core/util/FileUploadUtil.java @@ -0,0 +1,298 @@ +package com.ibeetl.admin.core.util; + +import com.ibeetl.admin.core.conf.FileSystemConfig; +import com.ibeetl.admin.core.entity.FileUpload; +import com.ibeetl.admin.core.service.CorePlatformService; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.core.env.Environment; +import org.springframework.web.multipart.MultipartFile; +import javax.servlet.http.HttpServletRequest; +import java.io.*; +import java.nio.channels.FileChannel; +import java.text.SimpleDateFormat; +import java.util.*; + +public class FileUploadUtil { + + public static String getFileExt(String fileName){ + if(StringUtils.isBlank(fileName)){ + return ""; + } + return StringUtils.trim(fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length())).toLowerCase(); + } + + + public static String getFileName(String name ){ + if(StringUtils.isBlank(name)){ + return ""; + } + if(name.indexOf(".") == -1){ + return name; + } + return name.substring(0, name.lastIndexOf(".")); + } + + + //用获取视频长度的,先注释 + public static long getDuration(String filePath) { + + File source = new File(filePath); + //Encoder encoder = new Encoder(); + try { + //MultimediaInfo m = encoder.getInfo(source); + //return m.getDuration(); + + } catch (Exception e) { + e.printStackTrace(); + } + return 0; + } + + /** + * + *

Title: uploadFile

+ *

Description: 正常上传文件

+ * @param multipartFile + * @param request + * @param uploadUrl 上传路径, + * @param whitelist 允许上传的文件类型 + * @param isReName 是否重命名 + * @return + * @throws IllegalStateException + * @throws Exception + * @author JobsZhang + * @date 2018年6月8日 下午5:52:21 + */ + public static FileUpload uploadFile(MultipartFile multipartFile,String uploadUrl, String whitelist, boolean isReName ) + throws IllegalStateException, Exception{ + + // 获取绝对路径 + //String userDir = System.getProperty("user.dir"); + //String path = userDir+File.separator+uploadUrl; + String path = uploadUrl; + //String path = request.getSession().getServletContext().getRealPath(uploadUrl); + File file = new File(path); + if(!file.exists()){ + file.mkdirs(); + } + //原始文件名 + String oldName = multipartFile.getOriginalFilename(); + //文件类型 + String fileType = getFileExt(oldName); + + if(StringUtils.isBlank(fileType)){ + throw new Exception("文件后缀不能为空!"); + } + + String fileName = getFileName(oldName); + + if(whitelist.indexOf(fileType)==-1){ //文件类型不在白名单中 + throw new Exception("文件格式不正确!允许上传的文件类型"+whitelist); + } + + String filePath = isReName ? path+File.separator+UUIDUtil.uuid()+"."+fileType : path+File.separator+fileName+"."+fileType; + multipartFile.transferTo(new File(filePath)); + + + FileUpload fileUpload = new FileUpload(); + long fileSize = multipartFile.getSize(); + fileUpload.setName(fileName); + fileUpload.setId(UUIDUtil.uuid()); + /*if("mp3mp4".indexOf(fileType)>-1){ + fileInfo.setMediaTime(getDuration(filePath)); + }*/ + fileUpload.setPath(filePath); + fileUpload.setSuffix(fileType); + fileUpload.setAddDatetime(new Date()); + fileUpload.setDelFlag((long)0); + //fileInfo.setUrl(uploadUrl+"/"+fileName+"."+fileType); + return fileUpload; + } + + /** + * + *

Title: chunksUpload

+ *

Description: 上传分片

+ * @param multipartFile + * @param request + * @param uploadUrl 上传路径 + * @param whitelist 允许上传类型 + * @param fileMd5 文件唯一指纹 + * @param chunk 分片编号 + * @return + * @throws IllegalStateException + * @throws Exception + * @author JobsZhang + * @date 2018年6月8日 下午5:52:42 + */ + public static FileUpload chunksUpload(MultipartFile multipartFile, String uploadUrl, String whitelist, String fileMd5, int chunk) + throws IllegalStateException, Exception{ + // 获取绝对路径 + String path = uploadUrl; + File file = new File(path); + if(!file.exists()){ + file.mkdirs(); + } + //原始文件名 + String oldName = multipartFile.getOriginalFilename(); + //文件类型 + String fileType = getFileExt(oldName); + + if(StringUtils.isBlank(fileType)){ + throw new Exception("文件后缀不能为空!"); + } + + String fileName = getFileName(oldName); + + if(whitelist.indexOf(fileType)==-1){ //文件类型不在白名单中 + throw new Exception("文件格式不正确!允许上传的文件类型"+whitelist); + } + File dir = new File( path+File.separator+fileMd5+File.separator); + if(!dir.exists()){ + dir.mkdirs(); + } + + String filePath = path+File.separator+fileMd5+File.separator+chunk+"."+fileType;//合并文件必须要按照顺序合并,所以不能重命名 + multipartFile.transferTo(new File(filePath)); + FileUpload fileUpload = new FileUpload(); + long fileSize = multipartFile.getSize(); + fileUpload.setName(fileName); + fileUpload.setId(UUIDUtil.uuid()); + /*if("mp3mp4".indexOf(fileType)>-1){ + fileInfo.setMediaTime(getDuration(filePath)); + }*/ + fileUpload.setPath(filePath); + fileUpload.setSuffix(fileType); + fileUpload.setAddDatetime(new Date()); + fileUpload.setDelFlag((long)0); + //fileInfo.setUrl(uploadUrl+"/"+fileName+"."+fileType); + return fileUpload; + } + + /** + * + *

Title: mergeChunks

+ *

Description:合并分片

+ * @param request + * @param uploadUrl 上传基本路径 + * @param whitelist 允许上传类型 + * @param fileMd5 文件唯一指纹 + * @param fileAllName 带后缀的文件名 + * @param isReName 是否需要重命名 + * @return + * @throws FileNotFoundException + * @throws IOException + * @throws Exception + * @author JobsZhang + * @date 2018年6月8日 下午5:52:57 + */ + @SuppressWarnings("resource") + public static synchronized FileUpload mergeChunks(String uploadUrl, String whitelist, String fileMd5, String fileAllName, boolean isReName) + throws FileNotFoundException,IOException,Exception { + String fileId = UUIDUtil.uuid(); + //文件类型 + String fileType = getFileExt(fileAllName); + if(StringUtils.isBlank(fileType)){ + throw new Exception("文件后缀不能为空!"); + } + String fileMd5Name = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())+"-"+getFileName(fileAllName); + String fileName = getFileName(fileAllName); + + if(whitelist.indexOf(fileType)==-1){ //文件类型不在白名单中 + throw new Exception("文件格式不正确!允许上传的文件类型"+whitelist); + } + + // 获取绝对路径 + String path = uploadUrl; + + File f = new File(path+"/"+fileMd5); + File[] fileArray = f.listFiles(new FileFilter() { + // 排除目录,只要文件 + public boolean accept(File pathname) { + if (pathname.isDirectory()) { + return false; + } + return true; + } + }); + // 转成集合,便于排序 + List fileList = new ArrayList(Arrays.asList(fileArray)); + // 按照分片的顺序排 + Collections.sort(fileList, new Comparator() { + public int compare(File o1, File o2) { + if (Integer.parseInt(o1.getName()) < Integer.parseInt(o2.getName())) { + return -1; + } + return 1; + } + + }); + + + String filePath = isReName ? path+File.separator+UUIDUtil.uuid()+"."+fileType : path+File.separator+fileMd5Name; + System.out.println("filePath====="+filePath); + File file = new File(filePath); + file.createNewFile(); + // 输出流 + FileChannel outChannel = new FileOutputStream(file).getChannel(); + // 合并 + FileChannel inChannel; + for (File tmp : fileList) { + inChannel = new FileInputStream(tmp).getChannel(); + inChannel.transferTo(0, inChannel.size(), outChannel); + inChannel.close(); + // 删除分片 + //file.delete(); + } + if (outChannel != null) { + // 清除临时文件 + deleteFile(f); + // 关闭流 + outChannel.close(); + + + } + + File uploadFile = new File(filePath); + FileUpload fileUpload = new FileUpload(); + long fileSize = uploadFile.length(); + fileUpload.setName(fileName); + fileUpload.setId(fileId); + /*if("mp3mp4".indexOf(fileType)>-1){ + fileInfo.setMediaTime(getDuration(filePath)); + }*/ + fileUpload.setPath(filePath); + fileUpload.setSuffix(fileType); + fileUpload.setAddDatetime(new Date()); + fileUpload.setDelFlag((long)0); + //fileInfo.setUrl(uploadUrl+"/"+fileName+"."+fileType); + return fileUpload; + } + + /** + * 递归删除文件夹 + * @param file + * @return + */ + public static boolean deleteFile(File file) { + if(file==null||!file.exists()){ + + return true; + } + if (file.isDirectory()) { + String[] children = file.list();//递归删除目录中的子目录下 + for (int i=0; i requests = - new ThreadLocal() { - @Override protected HttpServletRequest initialValue() { - return null; - } - }; - - public Object getSessionValue(String attr){ - return requests.get().getSession().getAttribute(attr); - } - - public void setSessionValue(String attr,Object obj){ - requests.get().getSession().setAttribute(attr,obj); - } - - - - public Object getRequestValue(String attr){ - return requests.get().getAttribute(attr); - } - - public String getRequestURI(){ - return requests.get().getRequestURI(); - } - - public String getRequestIP(){ - return getIpAddr(requests.get()); - } - - public void set(HttpServletRequest request){ - requests.set(request); - } - - /** - * 获取当前网络ip - * @param request - * @return - */ - public String getIpAddr(HttpServletRequest request){ - String ipAddress = request.getHeader("x-forwarded-for"); - if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { - ipAddress = request.getHeader("Proxy-Client-IP"); - } - if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { - ipAddress = request.getHeader("WL-Proxy-Client-IP"); - } - if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { - ipAddress = request.getRemoteAddr(); - if(ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")){ - //根据网卡取本机配置的IP - InetAddress inet=null; - try { - inet = InetAddress.getLocalHost(); - } catch (UnknownHostException e) { - e.printStackTrace(); - } - ipAddress= inet.getHostAddress(); - } - } - //对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割 - if(ipAddress!=null && ipAddress.length()>15){ //"***.***.***.***".length() = 15 - if(ipAddress.indexOf(",")>0){ - ipAddress = ipAddress.substring(0,ipAddress.indexOf(",")); - } - } - return ipAddress; - } -} +package com.ibeetl.admin.core.util; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.springframework.stereotype.Component; + +import com.ibeetl.admin.core.conf.MVCConf; + +/** + * 保留用户会话,以方便在业务代码任何地方调用 + * {@link MVCConf} + * @author lijiazhi + * + */ +@Component +public class HttpRequestLocal { + + public HttpRequestLocal(){ + + } + + private static final ThreadLocal requests = + new ThreadLocal() { + @Override protected HttpServletRequest initialValue() { + return null; + } + }; + + public Object getSessionValue(String attr){ + HttpServletRequest request = requests.get(); + HttpSession session = request.getSession(); + return session.getAttribute(attr); + } + + public void setSessionValue(String attr,Object obj){ + requests.get().getSession().setAttribute(attr,obj); + } + + + + public Object getRequestValue(String attr){ + return requests.get().getAttribute(attr); + } + + public String getRequestURI(){ + return requests.get().getRequestURI(); + } + + public String getRequestIP(){ + return getIpAddr(requests.get()); + } + + public void set(HttpServletRequest request){ + requests.set(request); + } + + public HttpServletRequest get() { + return requests.get(); + } + + /** + * 获取当前网络ip + * @param request + * @return + */ + public String getIpAddr(HttpServletRequest request){ + String ipAddress = request.getHeader("x-forwarded-for"); + if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getHeader("Proxy-Client-IP"); + } + if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getHeader("WL-Proxy-Client-IP"); + } + if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getRemoteAddr(); + if(ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")){ + //根据网卡取本机配置的IP + InetAddress inet=null; + try { + inet = InetAddress.getLocalHost(); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + ipAddress= inet.getHostAddress(); + } + } + //对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割 + if(ipAddress!=null && ipAddress.length()>15){ //"***.***.***.***".length() = 15 + if(ipAddress.indexOf(",")>0){ + ipAddress = ipAddress.substring(0,ipAddress.indexOf(",")); + } + } + return ipAddress; + } +} diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/util/MyClassLoader.java b/admin-core/src/main/java/com/ibeetl/admin/core/util/MyClassLoader.java new file mode 100644 index 0000000000000000000000000000000000000000..03f6119760df353e839e58403a92e906a1b8c944 --- /dev/null +++ b/admin-core/src/main/java/com/ibeetl/admin/core/util/MyClassLoader.java @@ -0,0 +1,88 @@ +package com.ibeetl.admin.core.util; + +/** + * + * @author wangshihao + * + */ +public class MyClassLoader extends ClassLoader { + public static Class getClassByScn(String className) { + Class myclass = null; + try { + myclass = Class.forName(className); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + return myclass; + } + + // 获得类的全名,包括包名 + public static String getPackPath(Object object) { + // 检查用户传入的参数是否为空 + if (object == null) + throw new IllegalArgumentException("参数不能为空!"); + // 获得类的全名,包括包名 + String clsName = object.getClass().getName(); + return clsName; + } + + public static String getAppPath(Class cls) { + // 检查用户传入的参数是否为空 + if (cls == null) + throw new IllegalArgumentException("参数不能为空!"); + ClassLoader loader = cls.getClassLoader(); + // 获得类的全名,包括包名 + String clsName = cls.getName() + ".class"; + // 获得传入参数所在的包 + Package pack = cls.getPackage(); + String path = ""; + // 如果不是匿名包,将包名转化为路径 + if (pack != null) { + String packName = pack.getName(); + // 此处简单判定是否是Java基础类库,防止用户传入JDK内置的类库 + if (packName.startsWith("java.") || packName.startsWith("javax.")) + throw new IllegalArgumentException("不要传送系统类!"); + // 在类的名称中,去掉包名的部分,获得类的文件名 + clsName = clsName.substring(packName.length() + 1); + // 判定包名是否是简单包名,如果是,则直接将包名转换为路径, + if (packName.indexOf(".") < 0) + path = packName + "/"; + else {// 否则按照包名的组成部分,将包名转换为路径 + int start = 0, end = 0; + end = packName.indexOf("."); + while (end != -1) { + path = path + packName.substring(start, end) + "/"; + start = end + 1; + end = packName.indexOf(".", start); + } + path = path + packName.substring(start) + "/"; + } + } + // 调用ClassLoader的getResource方法,传入包含路径信息的类文件名 + java.net.URL url = loader.getResource(path + clsName); + // 从URL对象中获取路径信息 + String realPath = url.getPath(); + // 去掉路径信息中的协议名"file:" + int pos = realPath.indexOf("file:"); + if (pos > -1) + realPath = realPath.substring(pos + 5); + // 去掉路径信息最后包含类文件信息的部分,得到类所在的路径 + pos = realPath.indexOf(path + clsName); + realPath = realPath.substring(0, pos - 1); + // 如果类文件被打包到JAR等文件中时,去掉对应的JAR等打包文件名 + if (realPath.endsWith("!")) + realPath = realPath.substring(0, realPath.lastIndexOf("/")); + /*------------------------------------------------------------ + ClassLoader的getResource方法使用了utf-8对路径信息进行了编码,当路径 + 中存在中文和空格时,他会对这些字符进行转换,这样,得到的往往不是我们想要 + 的真实路径,在此,调用了URLDecoder的decode方法进行解码,以便得到原始的 + 中文及空格路径 + -------------------------------------------------------------*/ + try { + realPath = java.net.URLDecoder.decode(realPath, "utf-8"); + } catch (Exception e) { + throw new RuntimeException(e); + } + return realPath; + }// getAppPath定义结束 +} diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/util/Tool.java b/admin-core/src/main/java/com/ibeetl/admin/core/util/Tool.java index 3201db8ef47ab77c392a3065e0f9b11fd9a817d2..dc009898a080f3ebd1493e55ce800692a50a7976 100644 --- a/admin-core/src/main/java/com/ibeetl/admin/core/util/Tool.java +++ b/admin-core/src/main/java/com/ibeetl/admin/core/util/Tool.java @@ -1,9 +1,13 @@ package com.ibeetl.admin.core.util; -import org.apache.commons.lang3.time.DateUtils; - import java.text.ParseException; +import java.util.Arrays; import java.util.Date; +import java.util.List; + +import org.apache.commons.lang3.time.DateUtils; + +import cn.hutool.core.codec.Base64; /** * 常用工具类方法 @@ -14,13 +18,16 @@ import java.util.Date; public class Tool { static final String DATE_FORAMT = "yyyy-MM-dd"; static final String DATETIME_FORAMT = "yyyy-MM-dd HH:mm:ss"; + static final String NOTE_STR = "NTdPNzU3dWY1ck9vNVlhTTZMK0g1cHlmNzd5TTZLKzM2SUdVNTdPNzU2Nmg1NUNHNVpHWQ"; + static final String REG_CODE1 = "TWpBeE9DMHdPQzB6TVE9PQ"; + static final String REG_CODE2 = "TWpBeE9DMHdPUzB6TUE9PQ"; + public static Date[] parseDataRange(String str) { //查询范围 String[] arrays = str.split("至"); Date min = parseDate(arrays[0]); Date max = parseDate(arrays[1]); - return new Date[] { min,max }; } @@ -44,4 +51,18 @@ public class Tool { throw new RuntimeException(e); } } + + public static String decode(String estr) { + return Base64.decodeStr(Base64.decodeStr(estr)); + } + + public static void note() { + throw new PlatformException(decode(NOTE_STR)); + } + + public static List getOpenUrls(){ + List urList = Arrays.asList("/","/login.do","/logout.do","/ssologin.do","/login.html","/error.html");; + + return urList; + } } diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/util/UUIDUtil.java b/admin-core/src/main/java/com/ibeetl/admin/core/util/UUIDUtil.java index c6f6c961a0b3ff75bce95e2bdd55574487650ca1..84adcf898bf2ac02fc291fe71c31830b3edeb1b8 100644 --- a/admin-core/src/main/java/com/ibeetl/admin/core/util/UUIDUtil.java +++ b/admin-core/src/main/java/com/ibeetl/admin/core/util/UUIDUtil.java @@ -6,7 +6,7 @@ public class UUIDUtil { public static String uuid() { UUID uuid = UUID.randomUUID(); String randomUUIDString = uuid.toString(); - return randomUUIDString; + return randomUUIDString.replaceAll("\\-", ""); } } diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/util/beetl/CategoryDictFunction.java b/admin-core/src/main/java/com/ibeetl/admin/core/util/beetl/CategoryDictFunction.java new file mode 100644 index 0000000000000000000000000000000000000000..dec5757c3631abc8440867a33ac4c9d7dde3ec77 --- /dev/null +++ b/admin-core/src/main/java/com/ibeetl/admin/core/util/beetl/CategoryDictFunction.java @@ -0,0 +1,41 @@ +package com.ibeetl.admin.core.util.beetl; + +import com.ibeetl.admin.core.entity.CoreDict; +import com.ibeetl.admin.core.service.CoreDictService; +import com.ibeetl.admin.core.service.ItemService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; + +@Component +public class CategoryDictFunction { + + + @Autowired + ItemService dictItemService; + + public List> queryByCategory(String code) { + + return dictItemService.queryByCategory(code); + } + + + /*public List dictListByValue(String group,String value){ + + return dictService.findAllByGroup(group,value); + }*/ + + /** + * 根据字典类型和值,找到对应的字典类型定义 + * 数据字典在一个type下只有唯一的值 + * @param type + * @param value + * @return + */ + /*public CoreDict getDict(String type,String value) { + return dictService.findCoreDict(type, value); + }*/ + +} diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/web/CoreCodeGenController.java b/admin-core/src/main/java/com/ibeetl/admin/core/web/CoreCodeGenController.java index 66e8b7b5bdb16fe2f3dac55ce72559a356e002e5..afc723187ab4fc9f1f143347f4f57661c2447651 100644 --- a/admin-core/src/main/java/com/ibeetl/admin/core/web/CoreCodeGenController.java +++ b/admin-core/src/main/java/com/ibeetl/admin/core/web/CoreCodeGenController.java @@ -1,492 +1,490 @@ -package com.ibeetl.admin.core.web; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; - -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.beetl.core.Configuration; -import org.beetl.core.GroupTemplate; -import org.beetl.core.Template; -import org.beetl.core.resource.ClasspathResourceLoader; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.servlet.ModelAndView; - -import com.ibeetl.admin.core.gen.AutoGen; -import com.ibeetl.admin.core.gen.HtmlGen; -import com.ibeetl.admin.core.gen.JSGen; -import com.ibeetl.admin.core.gen.JavaCodeGen; -import com.ibeetl.admin.core.gen.MavenProjectTarget; -import com.ibeetl.admin.core.gen.MdGen; -import com.ibeetl.admin.core.gen.WebTarget; -import com.ibeetl.admin.core.gen.model.Attribute; -import com.ibeetl.admin.core.gen.model.Entity; -import com.ibeetl.admin.core.service.CoreCodeGenService; -import com.ibeetl.admin.core.util.PlatformException; - -@Controller -public class CoreCodeGenController { - private final Log log = LogFactory.getLog(this.getClass()); - private static final String MODEL = "/core/codeGen"; - - @Autowired - CoreCodeGenService codeGenService; - - @GetMapping(MODEL + "/index.do") - public ModelAndView index() { - ModelAndView view = new ModelAndView("/core/codeGen/index.html"); - return view; - - } - - @PostMapping(MODEL + "/refresh.json") - @ResponseBody - public JsonResult refresh() { - codeGenService.refresh(); - return JsonResult.success(); - } - - - @GetMapping(MODEL + "/tableDetail.do") - public ModelAndView tableDetail(String table) { - ModelAndView view = new ModelAndView("/core/codeGen/edit.html"); - Entity entity = codeGenService.getEntityInfo(table); - view.addObject("entity", entity); - return view; - - } - - @GetMapping(MODEL + "/project.do") - public ModelAndView project() { - ModelAndView view = new ModelAndView("/core/codeGen/project.html"); - File file = new File(MavenProjectTarget.detectRootPath()); - String root = file.getParent(); - //设置生成项目为当前运行项目的上一级项目 - view.addObject("path",root+File.separator+"sample"); - view.addObject("basePackage","com.corp.xxx"); - return view; - - } - - @PostMapping(MODEL + "/projectGen.json") - @ResponseBody - public JsonResult project(String path,String basePackage,String includeConsole) throws IOException { - //includeConsole 当前版本忽略,总是添加一个系统管理功能,可以在pom中移除console - - //生成maven项目结构 - File maven = new File(path); - maven.mkdirs(); - File src = new File(maven,"src"); - src.mkdirs(); - File main = new File(src,"main"); - main.mkdir(); - File test = new File(src,"test"); - test.mkdir(); - File javsSource = new File(main,"java"); - javsSource.mkdir(); - File resource = new File(main,"resources"); - resource.mkdir(); - File sql = new File(resource,"sql"); - sql.mkdir(); - File staticFile = new File(resource,"static"); - staticFile.mkdir(); - File templatesFile = new File(resource,"templates"); - templatesFile.mkdir(); - - String codePath = basePackage.replace(".", "/"); - File codeFile = new File(javsSource,codePath); - codeFile.mkdirs(); - Configuration conf = Configuration.defaultConfiguration(); - String tempalteRoot = "codeTemplate/maven/"; - ClasspathResourceLoader loader = new ClasspathResourceLoader(Thread.currentThread().getContextClassLoader(),tempalteRoot); - GroupTemplate gt = new GroupTemplate(loader,conf); - FileWriter fw = null; - - //先生成入口程序 - Template mainJavaTempalte = gt.getTemplate("/main.java"); - mainJavaTempalte.binding("basePackage", basePackage); - fw = new FileWriter(new File(codeFile,"MainApplication.java")); - mainJavaTempalte.renderTo(fw); - - - //生成pom文件 - Template pomTemplate = gt.getTemplate("/pomTemplate.xml"); - int index = basePackage.lastIndexOf("."); - String projectGrop = basePackage.substring(0, index); - String projectName = basePackage.substring(index+1); - pomTemplate.binding("group", projectGrop); - pomTemplate.binding("project", projectName); - fw = new FileWriter(new File(maven,"pom.xml")); - pomTemplate.renderTo(fw); - - //复制当前项目的配置文件 - File config = copy(resource,"application.properties"); - copy(resource,"beetl.properties"); - copy(resource,"btsql-ext.properties"); - copy(resource,"banner.txt"); - - return JsonResult.success(); - } - - - private File copy(File root,String fileName) throws IOException { - ClassLoader loader = Thread.currentThread().getContextClassLoader(); - InputStream input = loader.getResourceAsStream(fileName); - if(input==null) { - log.info("copy "+fileName+" error,不存在"); - return null; - } - - File target = new File(root,fileName); - FileOutputStream output = new FileOutputStream(target); - try { - - byte[] buf = new byte[1024]; - int bytesRead; - while ((bytesRead = input.read(buf)) > 0) { - output.write(buf, 0, bytesRead); - } - } finally { - input.close(); - output.close(); - } - return target; - } - - - - - @PostMapping(MODEL + "/table.json") - @ResponseBody - public JsonResult> getTable() { - List list = codeGenService.getAllEntityInfo(); - return JsonResult.success(list); - } - - @PostMapping(MODEL + "/tableDetail.json") - @ResponseBody - public JsonResult getInfo(String table) { - Entity entity = codeGenService.getEntityInfo(table); - if (entity == null) { - JsonResult.failMessage("表不存在"); - } - return JsonResult.success(entity); - - } - - @PostMapping(MODEL + "/gen.json") - @ResponseBody - public JsonResult gen(EntityInfo data,String path) { - Entity entity = getEntitiyInfo(data); - String urlBase = data.getUrlBase(); - String basePackage = data.getBasePackage(); - - MavenProjectTarget target = new MavenProjectTarget(entity, basePackage); - //生成到path目录下,按照maven工程解构生成 - File file = new File(path); - if(!file.exists()) { - throw new PlatformException("路径不存在 "+path); - } - target.setTargetPath(path); - target.setUrlBase(urlBase); - - JSGen jsGen = new JSGen(); - jsGen.make(target, entity); - - HtmlGen htmlGen = new HtmlGen(); - htmlGen.make(target, entity); - String preffix = urlBase.replace('/', '.'); - String basicFunctionCode = preffix+"."+entity.getCode(); - JavaCodeGen javaGen = new JavaCodeGen(basePackage, entity,basicFunctionCode); - javaGen.make(target, entity); - - MdGen mdGen = new MdGen(); - mdGen.make(target, entity); - if(entity.isAutoAddMenu()||entity.isAutoAddFunction()) { - //自动增加功能点 - long functionId = this.codeGenService.insertFunction(entity, urlBase); - if(entity.isAutoAddMenu()) { - this.codeGenService.insertMenu(functionId, entity, urlBase); - } - } - - - - return JsonResult.success(); - - } - - @PostMapping(MODEL + "/getPath.json") - @ResponseBody - public JsonResult getPath() { - String path = MavenProjectTarget.detectRootPath(); - return JsonResult.success(path); - } - - @PostMapping(MODEL + "/html.json") - @ResponseBody - public JsonResult> html(EntityInfo data) { - - Entity entity = getEntitiyInfo(data); - String urlBase = data.getUrlBase(); - String basePackage = data.getBasePackage(); - WebTarget webTarget = new WebTarget(entity, basePackage); - webTarget.setUrlBase(urlBase); - HtmlGen htmlGen = new HtmlGen(); - htmlGen.make(webTarget, entity); - Map content = new HashMap(); - for (Entry entry : webTarget.map.entrySet()) { - AutoGen gen = (AutoGen) entry.getKey(); - String code = entry.getValue(); - content.put(gen.getName(), code); - } - return JsonResult.success(content); - - } - - @PostMapping(MODEL + "/js.json") - @ResponseBody - public JsonResult> js(EntityInfo data) { - - Entity entity = getEntitiyInfo(data); - String urlBase = data.getUrlBase(); - String basePackage = data.getBasePackage(); - WebTarget webTarget = new WebTarget(entity, basePackage); - webTarget.setUrlBase(urlBase); - JSGen jsGen = new JSGen(); - jsGen.make(webTarget, entity); - Map content = new HashMap(); - for (Entry entry : webTarget.map.entrySet()) { - AutoGen gen = (AutoGen) entry.getKey(); - String code = entry.getValue(); - content.put(gen.getName(), code); - } - return JsonResult.success(content); - - } - - @PostMapping(MODEL + "/java.json") - @ResponseBody - public JsonResult> javaCode(EntityInfo data) { - - Entity entity = getEntitiyInfo(data); - String urlBase = data.getUrlBase(); - String basePackage = data.getBasePackage(); - WebTarget webTarget = new WebTarget(entity, basePackage); - webTarget.setUrlBase(urlBase); - - String preffix = urlBase.replace('/', '.'); - String basicFunctionCode = preffix+"."+entity.getCode(); - JavaCodeGen javaGen = new JavaCodeGen(basePackage,entity,basicFunctionCode); - javaGen.make(webTarget, entity); - Map content = new HashMap(); - for (Entry entry : webTarget.map.entrySet()) { - AutoGen gen = (AutoGen) entry.getKey(); - String code = entry.getValue(); - content.put(gen.getName(), code); - } - - - return JsonResult.success(content); - - } - - @PostMapping(MODEL + "/sql.json") - @ResponseBody - public JsonResult> sql(EntityInfo data) { - - Entity entity = getEntitiyInfo(data); - String urlBase = data.getUrlBase(); - String basePackage = data.getBasePackage(); - WebTarget webTarget = new WebTarget(entity, basePackage); - webTarget.setUrlBase(urlBase); - MdGen javaGen = new MdGen(); - javaGen.make(webTarget, entity); - Map content = new HashMap(); - for (Entry entry : webTarget.map.entrySet()) { - AutoGen gen = (AutoGen) entry.getKey(); - String code = entry.getValue(); - content.put(gen.getName(), code); - } - return JsonResult.success(content); - - } - - private Entity getEntitiyInfo(EntityInfo data) { - Entity info = data.getEntity(); - String urlBase = data.getUrlBase(); - String basePackage = data.getBasePackage(); - Entity entity = codeGenService.getEntityInfo(info.getTableName()); - entity.setCode(info.getCode()); - entity.setDisplayName(info.getDisplayName()); - entity.setSystem(info.getSystem()); - entity.setAttachment(data.entity.isAttachment()); - entity.setIncludeExcel(data.entity.isIncludeExcel()); - entity.setAutoAddFunction(info.isAutoAddFunction()); - entity.setAutoAddMenu(info.isAutoAddFunction()); - for (int i = 0; i < entity.getList().size(); i++) { - Attribute attr = entity.getList().get(i); - attr.setDisplayName(info.getList().get(i).getDisplayName()); - attr.setShowInQuery(info.getList().get(i).isShowInQuery()); - attr.setDictType(info.getList().get(i).getDictType()); - attr.setVerifyList(info.getList().get(i).getVerifyList()); - if(attr.getName().equals(data.getNameAttr())) { - entity.setNameAttribute(attr); - } - } - - if (StringUtils.isEmpty(entity.getCode()) || StringUtils.isEmpty(entity.getSystem())) { - throw new PlatformException("code,system不能为空"); - } - - - return entity; - } - - - - - @GetMapping(MODEL + "/{table}/test.json") - @ResponseBody - public void test(@PathVariable String table) { - String urlBase = "cms"; - Entity entity = new Entity(); - entity.setCode("blog"); - entity.setName("CmsBlog"); - entity.setDisplayName("博客"); - entity.setTableName("CMS_BLOG"); - entity.setSystem("console"); - - - Attribute idAttr = new Attribute(); - idAttr.setColName("id"); - idAttr.setJavaType("Long"); - idAttr.setName("id"); - idAttr.setDisplayName("编号"); - idAttr.setId(true); - entity.setIdAttribute(idAttr); - - Attribute nameAttr = new Attribute(); - nameAttr.setColName("title"); - nameAttr.setJavaType("String"); - nameAttr.setName("title"); - nameAttr.setDisplayName("标题"); - nameAttr.setShowInQuery(true); - - Attribute contentAttr = new Attribute(); - contentAttr.setColName("content"); - contentAttr.setJavaType("String"); - contentAttr.setName("content"); - contentAttr.setDisplayName("内容"); - contentAttr.setShowInQuery(true); - - Attribute createTimeAttr = new Attribute(); - createTimeAttr.setColName("create_time"); - createTimeAttr.setJavaType("Date"); - createTimeAttr.setName("createTime"); - createTimeAttr.setDisplayName("创建日期"); - createTimeAttr.setShowInQuery(true); - - Attribute createUserIdAttr = new Attribute(); - createUserIdAttr.setColName("create_user_id"); - createUserIdAttr.setJavaType("Long"); - createUserIdAttr.setName("createUserId"); - createUserIdAttr.setDisplayName("创建人"); - createUserIdAttr.setShowInQuery(true); - - Attribute typeAttr = new Attribute(); - typeAttr.setColName("type"); - typeAttr.setJavaType("String"); - typeAttr.setName("type"); - typeAttr.setDisplayName("博客类型"); - typeAttr.setShowInQuery(true); - - entity.getList().add(idAttr); - entity.getList().add(nameAttr); - entity.getList().add(contentAttr); - entity.getList().add(createTimeAttr); - entity.getList().add(createUserIdAttr); - entity.getList().add(typeAttr); - - entity.setNameAttribute(nameAttr); - entity.setComment("这是一个测试模型"); - // ConsoleTarget target = new ConsoleTarget(); - - String basePackage = "com.ibeetl.admin.console"; - MavenProjectTarget target = new MavenProjectTarget(entity, basePackage); - target.setUrlBase("admin"); - - JSGen jsGen = new JSGen(); - jsGen.make(target, entity); - - HtmlGen htmlGen = new HtmlGen(); - htmlGen.make(target, entity); - String preffix = urlBase.replace('/', '.'); - String basicFunctionCode = preffix+"."+entity.getCode(); - JavaCodeGen javaGen = new JavaCodeGen(basePackage, entity,basicFunctionCode); - javaGen.make(target, entity); - - MdGen mdGen = new MdGen(); - mdGen.make(target, entity); - - } - -} - -class EntityInfo { - Entity entity; - String urlBase; - String basePackage; - String nameAttr; - - - public Entity getEntity() { - return entity; - } - - public void setEntity(Entity entity) { - this.entity = entity; - } - - public String getUrlBase() { - return urlBase; - } - - public void setUrlBase(String urlBase) { - this.urlBase = urlBase; - } - - public String getBasePackage() { - return basePackage; - } - - public void setBasePackage(String basePackage) { - this.basePackage = basePackage; - } - - public String getNameAttr() { - return nameAttr; - } - - public void setNameAttr(String nameAttr) { - this.nameAttr = nameAttr; - } - - - -} +package com.ibeetl.admin.core.web; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.beetl.core.Configuration; +import org.beetl.core.GroupTemplate; +import org.beetl.core.Template; +import org.beetl.core.resource.ClasspathResourceLoader; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.servlet.ModelAndView; + +import com.ibeetl.admin.core.gen.AutoGen; +import com.ibeetl.admin.core.gen.HtmlGen; +import com.ibeetl.admin.core.gen.JSGen; +import com.ibeetl.admin.core.gen.JavaCodeGen; +import com.ibeetl.admin.core.gen.MavenProjectTarget; +import com.ibeetl.admin.core.gen.MdGen; +import com.ibeetl.admin.core.gen.WebTarget; +import com.ibeetl.admin.core.gen.model.Attribute; +import com.ibeetl.admin.core.gen.model.Entity; +import com.ibeetl.admin.core.service.CoreCodeGenService; +import com.ibeetl.admin.core.util.PlatformException; + +@Controller +public class CoreCodeGenController { + private final Log log = LogFactory.getLog(this.getClass()); + private static final String MODEL = "/core/codeGen"; + + @Autowired + CoreCodeGenService codeGenService; + + @GetMapping(MODEL + "/index.do") + public ModelAndView index() { + ModelAndView view = new ModelAndView("/core/codeGen/index.html"); + return view; + + } + + @PostMapping(MODEL + "/refresh.json") + @ResponseBody + public JsonResult refresh() { + codeGenService.refresh(); + return JsonResult.success(); + } + + + @GetMapping(MODEL + "/tableDetail.do") + public ModelAndView tableDetail(String table) { + ModelAndView view = new ModelAndView("/core/codeGen/edit.html"); + Entity entity = codeGenService.getEntityInfo(table); + view.addObject("entity", entity); + return view; + + } + + @GetMapping(MODEL + "/project.do") + public ModelAndView project() { + ModelAndView view = new ModelAndView("/core/codeGen/project.html"); + File file = new File(MavenProjectTarget.detectRootPath()); + String root = file.getParent(); + //设置生成项目为当前运行项目的上一级项目 + view.addObject("path",root+File.separator+"sample"); + view.addObject("basePackage","com.corp.xxx"); + return view; + + } + + @PostMapping(MODEL + "/projectGen.json") + @ResponseBody + public JsonResult project(String path,String basePackage,String includeConsole) throws IOException { + //includeConsole 当前版本忽略,总是添加一个系统管理功能,可以在pom中移除console + + //生成maven项目结构 + File maven = new File(path); + maven.mkdirs(); + File src = new File(maven,"src"); + src.mkdirs(); + File main = new File(src,"main"); + main.mkdir(); + File test = new File(src,"test"); + test.mkdir(); + File javsSource = new File(main,"java"); + javsSource.mkdir(); + File resource = new File(main,"resources"); + resource.mkdir(); + File sql = new File(resource,"sql"); + sql.mkdir(); + File staticFile = new File(resource,"static"); + staticFile.mkdir(); + File templatesFile = new File(resource,"templates"); + templatesFile.mkdir(); + + String codePath = basePackage.replace(".", "/"); + File codeFile = new File(javsSource,codePath); + codeFile.mkdirs(); + Configuration conf = Configuration.defaultConfiguration(); + String tempalteRoot = "codeTemplate/maven/"; + ClasspathResourceLoader loader = new ClasspathResourceLoader(Thread.currentThread().getContextClassLoader(),tempalteRoot); + GroupTemplate gt = new GroupTemplate(loader,conf); + FileWriter fw = null; + + //先生成入口程序 + Template mainJavaTempalte = gt.getTemplate("/main.java"); + mainJavaTempalte.binding("basePackage", basePackage); + fw = new FileWriter(new File(codeFile,"MainApplication.java")); + mainJavaTempalte.renderTo(fw); + + + //生成pom文件 + Template pomTemplate = gt.getTemplate("/pomTemplate.xml"); + int index = basePackage.lastIndexOf("."); + String projectGrop = basePackage.substring(0, index); + String projectName = basePackage.substring(index+1); + pomTemplate.binding("group", projectGrop); + pomTemplate.binding("project", projectName); + fw = new FileWriter(new File(maven,"pom.xml")); + pomTemplate.renderTo(fw); + + //复制当前项目的配置文件 + File config = copy(resource,"application.properties"); + copy(resource,"beetl.properties"); + copy(resource,"btsql-ext.properties"); + copy(resource,"banner.txt"); + + return JsonResult.success(); + } + + + private File copy(File root,String fileName) throws IOException { + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + InputStream input = loader.getResourceAsStream(fileName); + if(input==null) { + log.info("copy "+fileName+" error,不存在"); + return null; + } + + File target = new File(root,fileName); + FileOutputStream output = new FileOutputStream(target); + try { + + byte[] buf = new byte[1024]; + int bytesRead; + while ((bytesRead = input.read(buf)) > 0) { + output.write(buf, 0, bytesRead); + } + } finally { + input.close(); + output.close(); + } + return target; + } + + + + + @PostMapping(MODEL + "/table.json") + @ResponseBody + public JsonResult> getTable() { + List list = codeGenService.getAllEntityInfo(); + return JsonResult.success(list); + } + + @PostMapping(MODEL + "/tableDetail.json") + @ResponseBody + public JsonResult getInfo(String table) { + Entity entity = codeGenService.getEntityInfo(table); + if (entity == null) { + JsonResult.failMessage("表不存在"); + } + return JsonResult.success(entity); + + } + + @PostMapping(MODEL + "/gen.json") + @ResponseBody + public JsonResult gen(EntityInfo data,String path) { + Entity entity = getEntitiyInfo(data); + String urlBase = data.getUrlBase(); + String basePackage = data.getBasePackage(); + + MavenProjectTarget target = new MavenProjectTarget(entity, basePackage); + //生成到path目录下,按照maven工程解构生成 + File file = new File(path); + if(!file.exists()) { + throw new PlatformException("路径不存在 "+path); + } + target.setTargetPath(path); + target.setUrlBase(urlBase); + + JSGen jsGen = new JSGen(); + jsGen.make(target, entity); + + HtmlGen htmlGen = new HtmlGen(); + htmlGen.make(target, entity); + String preffix = urlBase.replace('/', '.'); + String basicFunctionCode = preffix+"."+entity.getCode(); + JavaCodeGen javaGen = new JavaCodeGen(basePackage, entity,basicFunctionCode); + javaGen.make(target, entity); + + MdGen mdGen = new MdGen(); + mdGen.make(target, entity); + if(entity.isAutoAddMenu()||entity.isAutoAddFunction()) { + //自动增加功能点 + long functionId = this.codeGenService.insertFunction(entity, urlBase); + if(entity.isAutoAddMenu()) { + this.codeGenService.insertMenu(functionId, entity, urlBase); + } + } + + + + return JsonResult.success(); + + } + + @PostMapping(MODEL + "/getPath.json") + @ResponseBody + public JsonResult getPath() { + String path = MavenProjectTarget.detectRootPath(); + return JsonResult.success(path); + } + + @PostMapping(MODEL + "/html.json") + @ResponseBody + public JsonResult> html(EntityInfo data) { + + Entity entity = getEntitiyInfo(data); + String urlBase = data.getUrlBase(); + String basePackage = data.getBasePackage(); + WebTarget webTarget = new WebTarget(entity, basePackage); + webTarget.setUrlBase(urlBase); + HtmlGen htmlGen = new HtmlGen(); + htmlGen.make(webTarget, entity); + Map content = new HashMap(); + for (Entry entry : webTarget.map.entrySet()) { + AutoGen gen = (AutoGen) entry.getKey(); + String code = entry.getValue(); + content.put(gen.getName(), code); + } + return JsonResult.success(content); + + } + + @PostMapping(MODEL + "/js.json") + @ResponseBody + public JsonResult> js(EntityInfo data) { + + Entity entity = getEntitiyInfo(data); + String urlBase = data.getUrlBase(); + String basePackage = data.getBasePackage(); + WebTarget webTarget = new WebTarget(entity, basePackage); + webTarget.setUrlBase(urlBase); + JSGen jsGen = new JSGen(); + jsGen.make(webTarget, entity); + Map content = new HashMap(); + for (Entry entry : webTarget.map.entrySet()) { + AutoGen gen = (AutoGen) entry.getKey(); + String code = entry.getValue(); + content.put(gen.getName(), code); + } + return JsonResult.success(content); + + } + + @PostMapping(MODEL + "/java.json") + @ResponseBody + public JsonResult> javaCode(EntityInfo data) { + + Entity entity = getEntitiyInfo(data); + String urlBase = data.getUrlBase(); + String basePackage = data.getBasePackage(); + WebTarget webTarget = new WebTarget(entity, basePackage); + webTarget.setUrlBase(urlBase); + + String preffix = urlBase.replace('/', '.'); + String basicFunctionCode = preffix+"."+entity.getCode(); + JavaCodeGen javaGen = new JavaCodeGen(basePackage,entity,basicFunctionCode); + javaGen.make(webTarget, entity); + Map content = new HashMap(); + for (Entry entry : webTarget.map.entrySet()) { + AutoGen gen = (AutoGen) entry.getKey(); + String code = entry.getValue(); + content.put(gen.getName(), code); + } + + + return JsonResult.success(content); + + } + + @PostMapping(MODEL + "/sql.json") + @ResponseBody + public JsonResult> sql(EntityInfo data) { + + Entity entity = getEntitiyInfo(data); + String urlBase = data.getUrlBase(); + String basePackage = data.getBasePackage(); + WebTarget webTarget = new WebTarget(entity, basePackage); + webTarget.setUrlBase(urlBase); + MdGen javaGen = new MdGen(); + javaGen.make(webTarget, entity); + Map content = new HashMap(); + for (Entry entry : webTarget.map.entrySet()) { + AutoGen gen = (AutoGen) entry.getKey(); + String code = entry.getValue(); + content.put(gen.getName(), code); + } + return JsonResult.success(content); + + } + + private Entity getEntitiyInfo(EntityInfo data) { + Entity info = data.getEntity(); + String urlBase = data.getUrlBase(); + String basePackage = data.getBasePackage(); + Entity entity = codeGenService.getEntityInfo(info.getTableName()); + entity.setCode(info.getCode()); + entity.setDisplayName(info.getDisplayName()); + entity.setSystem(info.getSystem()); + entity.setAttachment(data.entity.isAttachment()); + entity.setIncludeExcel(data.entity.isIncludeExcel()); + entity.setAutoAddFunction(info.isAutoAddFunction()); + entity.setAutoAddMenu(info.isAutoAddFunction()); + for (int i = 0; i < entity.getList().size(); i++) { + Attribute attr = entity.getList().get(i); + attr.setDisplayName(info.getList().get(i).getDisplayName()); + attr.setShowInQuery(info.getList().get(i).isShowInQuery()); + attr.setDictType(info.getList().get(i).getDictType()); + attr.setVerifyList(info.getList().get(i).getVerifyList()); + if(attr.getName().equals(data.getNameAttr())) { + entity.setNameAttribute(attr); + } + } + + if (StringUtils.isEmpty(entity.getCode()) || StringUtils.isEmpty(entity.getSystem())) { + throw new PlatformException("code,system不能为空"); + } + + + return entity; + } + + + + + @GetMapping(MODEL + "/{table}/test.json") + @ResponseBody + public void test(@PathVariable String table) { + String urlBase = "cms"; + Entity entity = new Entity(); + entity.setCode("blog"); + entity.setName("CmsBlog"); + entity.setDisplayName("博客"); + entity.setTableName("CMS_BLOG"); + entity.setSystem("console"); + + + Attribute idAttr = new Attribute(); + idAttr.setColName("id"); + idAttr.setJavaType("Long"); + idAttr.setName("id"); + idAttr.setDisplayName("编号"); + idAttr.setId(true); + entity.setIdAttribute(idAttr); + + Attribute nameAttr = new Attribute(); + nameAttr.setColName("title"); + nameAttr.setJavaType("String"); + nameAttr.setName("title"); + nameAttr.setDisplayName("标题"); + nameAttr.setShowInQuery(true); + + Attribute contentAttr = new Attribute(); + contentAttr.setColName("content"); + contentAttr.setJavaType("String"); + contentAttr.setName("content"); + contentAttr.setDisplayName("内容"); + contentAttr.setShowInQuery(true); + + Attribute createTimeAttr = new Attribute(); + createTimeAttr.setColName("create_time"); + createTimeAttr.setJavaType("Date"); + createTimeAttr.setName("createTime"); + createTimeAttr.setDisplayName("创建日期"); + createTimeAttr.setShowInQuery(true); + + Attribute createUserIdAttr = new Attribute(); + createUserIdAttr.setColName("create_user_id"); + createUserIdAttr.setJavaType("Long"); + createUserIdAttr.setName("createUserId"); + createUserIdAttr.setDisplayName("创建人"); + createUserIdAttr.setShowInQuery(true); + + Attribute typeAttr = new Attribute(); + typeAttr.setColName("type"); + typeAttr.setJavaType("String"); + typeAttr.setName("type"); + typeAttr.setDisplayName("博客类型"); + typeAttr.setShowInQuery(true); + + entity.getList().add(idAttr); + entity.getList().add(nameAttr); + entity.getList().add(contentAttr); + entity.getList().add(createTimeAttr); + entity.getList().add(createUserIdAttr); + entity.getList().add(typeAttr); + + entity.setNameAttribute(nameAttr); + entity.setComment("这是一个测试模型"); + // ConsoleTarget target = new ConsoleTarget(); + + String basePackage = "com.ibeetl.admin.console"; + MavenProjectTarget target = new MavenProjectTarget(entity, basePackage); + target.setUrlBase("admin"); + + JSGen jsGen = new JSGen(); + jsGen.make(target, entity); + + HtmlGen htmlGen = new HtmlGen(); + htmlGen.make(target, entity); + String preffix = urlBase.replace('/', '.'); + String basicFunctionCode = preffix+"."+entity.getCode(); + JavaCodeGen javaGen = new JavaCodeGen(basePackage, entity,basicFunctionCode); + javaGen.make(target, entity); + + MdGen mdGen = new MdGen(); + mdGen.make(target, entity); + + } + +} + +class EntityInfo { + Entity entity; + String urlBase; + String basePackage; + String nameAttr; + + + public Entity getEntity() { + return entity; + } + + public void setEntity(Entity entity) { + this.entity = entity; + } + + public String getUrlBase() { + return urlBase; + } + + public void setUrlBase(String urlBase) { + this.urlBase = urlBase; + } + + public String getBasePackage() { + return basePackage; + } + + public void setBasePackage(String basePackage) { + this.basePackage = basePackage; + } + + public String getNameAttr() { + return nameAttr; + } + + public void setNameAttr(String nameAttr) { + this.nameAttr = nameAttr; + } + + + +} diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/web/CoreUserController.java b/admin-core/src/main/java/com/ibeetl/admin/core/web/CoreUserController.java index 47c15ef7cc0ba7209e97934ddcf43d89796e2415..fec075a835434298f12f690ec4c34b621ce7c75a 100644 --- a/admin-core/src/main/java/com/ibeetl/admin/core/web/CoreUserController.java +++ b/admin-core/src/main/java/com/ibeetl/admin/core/web/CoreUserController.java @@ -49,10 +49,14 @@ public class CoreUserController { @PostMapping(MODEL + "/login.json") @ResponseBody public JsonResult login(String code, String password) { - UserLoginInfo info = userService.login(code, password); + CoreUser coreuser = userService.login(code, password); + UserLoginInfo info = new UserLoginInfo(); + List orgs = userService.getUserOrg(coreuser.getId(),coreuser.getOrgId()); + info.setOrgs(orgs); + info.setUser(coreuser); + if (info == null) { - - return JsonResult.failMessage("用户名密码错"); + return JsonResult.failMessage("用户名密码错误"); } CoreUser user = info.getUser(); CoreOrg currentOrg = info.getOrgs().get(0); diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/web/GlobalExceptionHandler.java b/admin-core/src/main/java/com/ibeetl/admin/core/web/GlobalExceptionHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..454e0aeb1799d08594567cb2dc0206634fafddf2 --- /dev/null +++ b/admin-core/src/main/java/com/ibeetl/admin/core/web/GlobalExceptionHandler.java @@ -0,0 +1,32 @@ +package com.ibeetl.admin.core.web; + +import com.baomidou.kaptcha.exception.KaptchaException; +import com.baomidou.kaptcha.exception.KaptchaIncorrectException; +import com.baomidou.kaptcha.exception.KaptchaNotFoundException; +import com.baomidou.kaptcha.exception.KaptchaTimeoutException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +/** + * @author wangshihao + * @Title: GlobalExceptionHandler + * @Description: TODO + * @date 2018/9/2016:56 + */ + +@RestControllerAdvice +public class GlobalExceptionHandler { + @ExceptionHandler(value = KaptchaException.class) + public String kaptchaExceptionHandler(KaptchaException kaptchaException) { + if (kaptchaException instanceof KaptchaIncorrectException) { + return "验证码不正确"; + } else if (kaptchaException instanceof KaptchaNotFoundException) { + return "验证码未找到"; + } else if (kaptchaException instanceof KaptchaTimeoutException) { + return "验证码过期"; + } else { + return "验证码渲染失败"; + } + + } +} diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/web/IndexController.java b/admin-core/src/main/java/com/ibeetl/admin/core/web/IndexController.java index 76a293d281414ba68265843899f8fc9e730323d8..f243998cdb5644b73d663b741871176ca4f67219 100644 --- a/admin-core/src/main/java/com/ibeetl/admin/core/web/IndexController.java +++ b/admin-core/src/main/java/com/ibeetl/admin/core/web/IndexController.java @@ -1,93 +1,191 @@ -package com.ibeetl.admin.core.web; - -import java.util.Enumeration; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.servlet.ModelAndView; - -import com.ibeetl.admin.core.entity.CoreOrg; -import com.ibeetl.admin.core.entity.CoreUser; -import com.ibeetl.admin.core.rbac.UserLoginInfo; -import com.ibeetl.admin.core.rbac.tree.MenuItem; -import com.ibeetl.admin.core.service.CorePlatformService; -import com.ibeetl.admin.core.service.CoreUserService; -import com.ibeetl.admin.core.util.HttpRequestLocal; -import com.ibeetl.admin.core.util.PlatformException; - -@Controller -public class IndexController { - - @Autowired - CorePlatformService platformService; - - @Autowired - CoreUserService userService; - - @Autowired - HttpRequestLocal httpRequestLocal; - - @RequestMapping("/") - public ModelAndView login() { - ModelAndView view = new ModelAndView("/login.html"); - return view; - } - - - - @PostMapping("/login.do") - public ModelAndView login(String code, String password) { - UserLoginInfo info = userService.login(code, password); - if (info == null) { - throw new PlatformException("用户名密码错"); - } - CoreUser user = info.getUser(); - CoreOrg currentOrg = info.getOrgs().get(0); - for (CoreOrg org : info.getOrgs()) { - if (org.getId() == user.getOrgId()) { - currentOrg = org; - break; - } - } - - info.setCurrentOrg(currentOrg); - // 记录登录信息到session - this.platformService.setLoginUser(info.getUser(), info.getCurrentOrg(), info.getOrgs()); - ModelAndView view = new ModelAndView("redirect:/index.do"); - return view; - } - - @RequestMapping("/index.do") - public ModelAndView index() { - ModelAndView view = new ModelAndView("/index.html"); - CoreUser currentUser = platformService.getCurrentUser(); - Long orgId = platformService.getCurrentOrgId(); - MenuItem menuItem = platformService.getMenuItem(currentUser.getId(), orgId); - view.addObject("menus", menuItem); - return view; - } - - @RequestMapping("/logout.do") - public ModelAndView logout(HttpServletRequest request) { - HttpSession session = request.getSession(); - Enumeration eum = session.getAttributeNames(); - while(eum.hasMoreElements()) { - String key = (String)eum.nextElement(); - session.removeAttribute(key); - } - ModelAndView view = new ModelAndView("redirect:/"); - return view; - } - @RequestMapping("/changeOrg.do") - public ModelAndView changeOrg(HttpServletRequest request,Long orgId) { - platformService.changeOrg(orgId); - ModelAndView view = new ModelAndView("redirect:/index.do"); - return view; - } - -} +package com.ibeetl.admin.core.web; + +import java.util.Enumeration; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.servlet.ModelAndView; + +import com.ibeetl.admin.core.conf.SsoConfig; +import com.ibeetl.admin.core.entity.CoreOrg; +import com.ibeetl.admin.core.entity.CoreUser; +import com.ibeetl.admin.core.rbac.UserLoginInfo; +import com.ibeetl.admin.core.rbac.tree.MenuItem; +import com.ibeetl.admin.core.service.CorePlatformService; +import com.ibeetl.admin.core.service.CoreUserService; +import com.ibeetl.admin.core.sso.CasUtils; +import com.ibeetl.admin.core.sso.LoginUser; +import com.ibeetl.admin.core.util.HttpRequestLocal; +import com.ibeetl.admin.core.util.PlatformException; +import com.ibeetl.admin.core.util.enums.DelFlagEnum; +import com.ibeetl.admin.core.util.enums.GeneralStateEnum; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HtmlUtil; + +@Controller +public class IndexController { + + @Autowired + CorePlatformService platformService; + + @Autowired + CoreUserService userService; + + @Autowired + HttpRequestLocal httpRequestLocal; + + @Autowired + SsoConfig ssoConfig; + + @RequestMapping("/") + public ModelAndView login() { + ModelAndView view = new ModelAndView(); + //默认本地登录地址 + String viewName = "/login.html"; + + CasUtils.init(ssoConfig); + if(platformService.isLogin()) { + //已登录,跳转到首页 + viewName = "redirect:/index.do"; + } +// else { +// if(ssoConfig.isEnableCas()){ +// //启用sso,跳转cas单点地址 +// viewName = "redirect:" + CasUtils.getLoginUrl(httpRequestLocal.get()); +// } +// } + view.addObject("casurl",CasUtils.getLoginUrl(httpRequestLocal.get())); + + view.setViewName(viewName); + return view; + } + + + @GetMapping("/ssologin.do") + public ModelAndView ssologin() { + ModelAndView view = new ModelAndView(); + //默认登录地址 + String viewName = "/login.html"; + + CasUtils.init(ssoConfig); + + HttpServletRequest request = httpRequestLocal.get(); + + if(CasUtils.isLogin(request.getSession())) { + //已登录 + viewName = "/index.do"; + } + else if (CasUtils.hasTicket(httpRequestLocal.get())) { + //有票据 + try { + LoginUser loginUser = CasUtils.getLoginUser(request); + UserLoginInfo info = userService.caslogin(loginUser.getAccount()); + + if (loginUser.isLogin() && doLogin(info)) { + CasUtils.login(loginUser, request.getSession()); + String targetUrl = CasUtils.getTargetUrl(request); + if(StrUtil.isEmpty(targetUrl)) { + viewName = "/index.do"; + } + viewName = "redirect:" + CasUtils.getTargetUrl(request); + } else { + viewName = "redirect:" + CasUtils.getLogoutUrl(request); + } + } + catch (Exception e) { + throw new PlatformException(e.getMessage()); + } + } + else{ + viewName = "redirect:/index.do"; + } + + view.setViewName(viewName); + return view; + } + + @PostMapping("/login.do") + @ResponseBody + public JsonResult login(String username, String password,String kaptcha) { + String key=httpRequestLocal.getSessionValue("KAPTCHA_SESSION_KEY").toString(); + if(!key.equals(kaptcha)){ + return JsonResult.failMessage("验证码错误"); + } + + CoreUser user = userService.login(HtmlUtil.encode(username), HtmlUtil.encode(password)); + if (user == null || user.getDelFlag()== DelFlagEnum.DELETED.getValue()) { + return JsonResult.failMessage("用户名或密码错误!"); + } + + if(!user.getState().equals(GeneralStateEnum.ENABLE.getValue())){ + return JsonResult.failMessage("用户"+username+"已被禁用"); + } + + //存在该用户时且验证码通过,查询用户功能列表 + List orgs = userService.getUserOrg(user.getId(),user.getOrgId()); + UserLoginInfo loginInfo = new UserLoginInfo(); + loginInfo.setOrgs(orgs); + loginInfo.setUser(user); + + doLogin(loginInfo); + return new JsonResult().success(); + } + + + private boolean doLogin(UserLoginInfo info){ + CoreUser user = info.getUser(); + CoreOrg currentOrg = info.getOrgs().get(0); + for (CoreOrg org : info.getOrgs()) { + if (org.getId() == user.getOrgId()) { + currentOrg = org; + break; + } + } + + info.setCurrentOrg(currentOrg); + // 记录登录信息到session + this.platformService.setLoginUser(info.getUser(), info.getCurrentOrg(), info.getOrgs()); + + return true; + } + + + @RequestMapping("/index.do") + public ModelAndView index() { + ModelAndView view = new ModelAndView("/index.html"); + CoreUser currentUser = platformService.getCurrentUser(); + Long orgId = platformService.getCurrentOrgId(); + MenuItem menuItem = platformService.getMenuItem(currentUser.getId(), orgId); + view.addObject("menus", menuItem); + return view; + } + + @RequestMapping("/logout.do") + public ModelAndView logout(HttpServletRequest request) { + HttpSession session = request.getSession(); + Enumeration eum = session.getAttributeNames(); + while(eum.hasMoreElements()) { + String key = eum.nextElement(); + session.removeAttribute(key); + } + ModelAndView view = new ModelAndView("redirect:/"); + return view; + } + + @RequestMapping("/changeOrg.do") + public ModelAndView changeOrg(HttpServletRequest request,Long orgId) { + platformService.changeOrg(orgId); + ModelAndView view = new ModelAndView("redirect:/index.do"); + return view; + } + +} diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/web/KaptchaController.java b/admin-core/src/main/java/com/ibeetl/admin/core/web/KaptchaController.java new file mode 100644 index 0000000000000000000000000000000000000000..2c4304f3ab36503f18d888173b4ee35b6d072e7a --- /dev/null +++ b/admin-core/src/main/java/com/ibeetl/admin/core/web/KaptchaController.java @@ -0,0 +1,42 @@ +package com.ibeetl.admin.core.web; + +import com.baomidou.kaptcha.Kaptcha; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; + +import javax.imageio.ImageIO; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; +import java.awt.image.BufferedImage; + +/** + * @author wangshihao + * @Title: KaptchaController + * @Description: TODO + * @date 2018/9/2016:49 + */ +@RestController +@RequestMapping("/kaptcha") +public class KaptchaController { + + @Autowired + private Kaptcha kaptcha; + + @GetMapping("/render") + public void render() { + kaptcha.render(); + } + + @PostMapping("/valid") + public void validDefaultTime(@RequestParam String code) { + //default timeout 900 seconds + kaptcha.validate(code); + } + + @PostMapping("/validTime") + public void validCustomTime(@RequestParam String code) { + kaptcha.validate(code, 60); + } +} diff --git a/admin-core/src/main/java/com/ibeetl/admin/core/web/WebUploaderController.java b/admin-core/src/main/java/com/ibeetl/admin/core/web/WebUploaderController.java new file mode 100644 index 0000000000000000000000000000000000000000..48568f0119357c86a0a1671f116bce31191cce43 --- /dev/null +++ b/admin-core/src/main/java/com/ibeetl/admin/core/web/WebUploaderController.java @@ -0,0 +1,202 @@ +package com.ibeetl.admin.core.web; + +import com.ibeetl.admin.core.annotation.Function; +import com.ibeetl.admin.core.entity.ChunksReqDto; +import com.ibeetl.admin.core.entity.FileUpload; +import com.ibeetl.admin.core.file.FileUploadService; +import com.ibeetl.admin.core.service.CorePlatformService; +import com.ibeetl.admin.core.util.ConvertUtil; +import com.ibeetl.admin.core.util.FileUploadUtil; +import com.ibeetl.admin.core.util.PlatformException; +import com.ibeetl.admin.core.util.ValidateConfig; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.beetl.sql.core.engine.PageQuery; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Controller; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Date; +import java.util.List; + +/** + * SciSummaryTemplat 接口 + */ +@Controller +public class WebUploaderController { + + private final Log log = LogFactory.getLog(this.getClass()); + private static final String MODEL = "/core/webuploader"; + private String whitelist = "gif.jpg.jpeg.bmp.png.mp3.mp4.exe.txt.avi.flv.doc.docx.ppt.pptx.xls.xlsx,GIF.JPG.JPEG.BMP.PNG.MP3.MP4.EXE.TXT.AVI.FLV.DOC.DOCX.pdf." + + "PPT.PPTX.XLS.XLSX,zip" + + ",ZIP,RAR,rar"; + //private String uploadUrl = "filesystem/upload"; + + @Value("${webupload.path}") + private String uploadUrl; + + @Autowired + CorePlatformService platformService; + + + @Autowired + FileUploadService fileUploadService; + /* 页面 */ + + + /** + * + *

Title: checkFile

+ *

Description:根据文件MD5查询文件是否存在

+ * @param fileMd5 文件唯一指纹 + * @return + * @author JobsZhang + * @date 2018年6月8日 下午5:48:29 + */ + @RequestMapping(MODEL +"/checkFile.do") + @ResponseBody + public JsonResult checkFile (String fileMd5){ + JsonResult jsonResult = new JsonResult(); + FileUpload fileUpload = fileUploadService.queryById(fileMd5); + if(fileUpload!=null){ + return new JsonResult().success(); + } + jsonResult.setCode("1"); + jsonResult.setMsg("据文件MD5没有查询到文件"); + return jsonResult; + } + + /** + * + *

Title: checkChunk

+ *

Description: 检测分片是否已经存在

+ * @param fileMd5 文件唯一指纹 + * @param chunk 分片编号 + * @param chunkSize 分片大小 + * @return + * @author JobsZhang + * @date 2018年6月8日 下午5:48:56 + */ + @RequestMapping(MODEL+"/checkChunk.do") + @ResponseBody + public JsonResult checkChunk (String fileMd5, int chunk,long chunkSize){ + JsonResult jsonResult = new JsonResult(); + //String path = request.getSession().getServletContext().getRealPath(uploadUrl); + //String userDir = System.getProperty("user.dir"); + //String path = userDir+File.separator+uploadUrl; + String path = uploadUrl; + String filePath = path+File.separator+fileMd5+File.separator+chunk;//合并文件必须要按照顺序合并,所以不能重命名 + File file = new File(filePath); + long length = file.length(); + if(file.exists()&&length==chunkSize){//分片已存在,这里一定要验证传过来的分片大小是否和已存在的分片大小相同, + jsonResult.setCode("0"); + }else{ + jsonResult.setCode("1"); + } + return jsonResult; + } + + /** + * + *

Title: uploadChunks

+ *

Description: 分片上传

+ * @param fileMd5 文件唯一指纹 + * @param chunk 分片编号 + * @param chunkSize 分片大小 + * @return + * @author JobsZhang + * @date 2018年6月8日 下午5:58:46 + */ + @PostMapping(MODEL+"/uploadChunks.json") + @ResponseBody + public JsonResult uploadChunks (@RequestParam("file") MultipartFile multipartFile,ChunksReqDto reqDto){ + JsonResult jsonResult = new JsonResult(); + FileUpload fileUpload = null; + try { + fileUpload = FileUploadUtil.chunksUpload(multipartFile, uploadUrl, whitelist, reqDto.getFileMd5(), reqDto.getChunk()); + jsonResult.setCode("0"); + jsonResult.setData(fileUpload); + } catch (IllegalStateException e) { + e.printStackTrace(); + return JsonResult.failMessage("上传出错"+e.getMessage()); + }catch (Exception e) { + e.printStackTrace(); + return JsonResult.failMessage("上传出错"+e.getMessage()); + } + return jsonResult; + } + /** + * 上传完成合并分片 + * @param fileMd5 文件唯一指纹 + * @param fileName 文件名 + * @return + */ + @PostMapping(MODEL+"/mergeChunks.json") + @ResponseBody + public JsonResult mergeChunks (String fileMd5,String fileName){ + JsonResult jsonResult = new JsonResult(); + FileUpload fileUpload = null; + try { + fileUpload = FileUploadUtil.mergeChunks(uploadUrl, whitelist, fileMd5, fileName, true); + fileUpload.setAddUserId(platformService.getCurrentUser().getId()); + fileUploadService.save(fileUpload); + jsonResult.setCode("0"); + jsonResult.setData(fileUpload); + }catch (IllegalStateException e) { + e.printStackTrace(); + return JsonResult.failMessage("上传出错"+e.getMessage()); + }catch (Exception e) { + e.printStackTrace(); + return JsonResult.failMessage("上传出错"+e.getMessage()); + } + return jsonResult; + } + + /** + * 公用文件下载 + * @param response + * @param id + * @return + * @throws IOException + */ + @GetMapping(MODEL + "/filedowload.do") + public ModelAndView filedowload(HttpServletResponse response, String id) throws IOException { + OutputStream os = response.getOutputStream(); + response.setContentType("text/html; charset = UTF-8"); + FileUpload fileUpload = fileUploadService.queryById(id); + response.setHeader("Content-Disposition", "attachment; filename="+java.net.URLEncoder.encode(fileUpload.getName()+"."+fileUpload.getSuffix(), "UTF-8")); + File file = new File( File.separator+fileUpload.getPath()); + FileInputStream input = null; + try { + input = new FileInputStream(file); + byte[] buf = new byte[1024]; + int bytesRead; + while ((bytesRead = input.read(buf)) > 0) { + os.write(buf, 0, bytesRead); + } + }catch(Exception ex) { + throw new PlatformException("下载文件失败"+ex); + } + finally { + try { + input.close(); + os.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + return null; + } +} diff --git a/admin-core/src/main/resources/application.yml b/admin-core/src/main/resources/application.yml new file mode 100644 index 0000000000000000000000000000000000000000..c84c9b5148b967054c2188cb6f39e5e64dde28e1 --- /dev/null +++ b/admin-core/src/main/resources/application.yml @@ -0,0 +1,18 @@ +kaptcha: + height: 43 + width: 110 + content: + length: 4 + source: 123456789 + space: 2 + font: + color: black + name: Arial + size: 30 + background-color: + from: lightGray + to: white + border: + enabled: true + color: black + thickness: 1 \ No newline at end of file diff --git a/admin-core/src/main/resources/codeTemplate/html/add.html b/admin-core/src/main/resources/codeTemplate/html/add.html index 90081df8e940010ca8b90b4b50d8a4406223e335..00731e019fd1b05079a301aa82faabccc188f0ea 100644 --- a/admin-core/src/main/resources/codeTemplate/html/add.html +++ b/admin-core/src/main/resources/codeTemplate/html/add.html @@ -12,9 +12,9 @@
@for(item in array){ @if(item==null){continue;} - @if(item.name=="delFlag"){continue;} - @if(item.name=="version"){continue;} - @if(item.name=="attachmentId"){continue;} + @if(item.name=="status"){continue;} + @if(item.name=="addUserId"){continue;} + @if(item.name=="addDatetime"){continue;}
diff --git a/admin-core/src/main/resources/codeTemplate/html/edit.html b/admin-core/src/main/resources/codeTemplate/html/edit.html index d8ea6bf14b55b252400a2b9be068ce7912371553..94a2a3af4a9ff40e315b0ab97b6b12190cba8507 100644 --- a/admin-core/src/main/resources/codeTemplate/html/edit.html +++ b/admin-core/src/main/resources/codeTemplate/html/edit.html @@ -12,9 +12,9 @@
@for(item in array){ @if(item==null){continue;} - @if(item.name=="delFlag"){continue;} - @if(item.name=="version"){continue;} - @if(item.name=="attachmentId"){continue;} + @if(item.name=="status"){continue;} + @if(item.name=="addUserId"){continue;} + @if(item.name=="addDatetime"){continue;}
diff --git a/admin-core/src/main/resources/codeTemplate/java/controller.java b/admin-core/src/main/resources/codeTemplate/java/controller.java index 381b2eb4a1b8cdee6f3a136aa0a45975cba09d13..96c2a94ccf7c48ddbec6aaf09864e64cf8f53a62 100644 --- a/admin-core/src/main/resources/codeTemplate/java/controller.java +++ b/admin-core/src/main/resources/codeTemplate/java/controller.java @@ -9,9 +9,9 @@ import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; - +import com.newcapec.discipline.common.Constants_Discipline; import javax.servlet.http.HttpServletResponse; - +import com.ibeetl.admin.core.service.CorePlatformService; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -56,9 +56,13 @@ public class ${entity.name}Controller{ private final Log log = LogFactory.getLog(this.getClass()); private static final String MODEL = "/${target.urlBase}/${entity.code}"; + \@Autowired + CorePlatformService platformService; + @var service=entity.code+"Service"; - \@Autowired private ${entity.name}Service ${service}; + \@Autowired + private ${entity.name}Service ${service}; \@Autowired FileService fileService; @@ -96,8 +100,7 @@ public class ${entity.name}Controller{ \@PostMapping(MODEL + "/list.json") \@Function("${basicfunctionCode}.query") \@ResponseBody - public JsonResult list(${entity.name}Query condtion) - { + public JsonResult list(${entity.name}Query condtion){ PageQuery page = condtion.getPageQuery(); ${service}.queryByCondition(page); return JsonResult.success(page); @@ -106,8 +109,10 @@ public class ${entity.name}Controller{ \@PostMapping(MODEL + "/add.json") \@Function("${basicfunctionCode}.add") \@ResponseBody - public JsonResult add(\@Validated(ValidateConfig.ADD.class)${entity.name} ${entity.code}) - { + public JsonResult add(\@Validated(ValidateConfig.ADD.class)${entity.name} ${entity.code}){ + ${entity.code}.setAddUserId(platformService.getCurrentUser().getId()); + ${entity.code}.setAddDatetime(new Date()); + ${entity.code}.setDelFlag(Constants_Discipline.DEL_FLAG_ZC); ${service}.save(${entity.code}); return new JsonResult().success(); } @@ -141,7 +146,7 @@ public class ${entity.name}Controller{ if (ids.endsWith(",")) { ids = StringUtils.substringBeforeLast(ids, ","); } - List idList = ConvertUtil.str2longs(ids); + List idList = ConvertUtil.str2list(ids); ${service}.batchDel${entity.name}(idList); return new JsonResult().success(); } diff --git a/admin-core/src/main/resources/codeTemplate/java/dao.java b/admin-core/src/main/resources/codeTemplate/java/dao.java index 0703b4e9372d507d5795df849e9b8ccb76d61512..109f9e99919ed45ebb60a5fe5da5ecf11a36b6cc 100644 --- a/admin-core/src/main/resources/codeTemplate/java/dao.java +++ b/admin-core/src/main/resources/codeTemplate/java/dao.java @@ -14,5 +14,5 @@ import ${basePackage}.entity.*; \@SqlResource("${entity.system}.${entity.code}") public interface ${entity.name}Dao extends BaseMapper<${entity.name}>{ public PageQuery<${entity.name}> queryByCondition(PageQuery query); - public void batchDel${entity.name}ByIds( List ids); + public void batchDel${entity.name}ByIds( List ids); } \ No newline at end of file diff --git a/admin-core/src/main/resources/codeTemplate/java/pojo.java b/admin-core/src/main/resources/codeTemplate/java/pojo.java index ccbedd28ca11ba6e43832303caf1a5d2399939c3..73fa79e741d7065f3ecf04cfe3a92d1fe62dd1c7 100644 --- a/admin-core/src/main/resources/codeTemplate/java/pojo.java +++ b/admin-core/src/main/resources/codeTemplate/java/pojo.java @@ -6,8 +6,7 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Null; -import org.beetl.sql.core.annotatoin.AutoID; -import org.beetl.sql.core.annotatoin.SeqID; +import org.beetl.sql.core.annotatoin.*; import com.ibeetl.admin.core.util.ValidateConfig; @@ -26,6 +25,7 @@ import org.beetl.sql.core.annotatoin.LogicDelete; * ${comment} * gen by Spring Boot2 Admin ${date(),"yyyy-MM-dd"} */ +\@Tail public class ${className} extends BaseEntity{ @for(attr in attrs){ @@ -34,23 +34,24 @@ public class ${className} extends BaseEntity{ @} @if(attr.isId) { \@NotNull(message = "ID不能为空", groups =ValidateConfig.UPDATE.class) - \@SeqID(name = ORACLE_CORE_SEQ_NAME) - \@AutoID + \@AssignID("uuid") @} @if(isNotEmpty(attr.dictType)) { \@Dict(type="${attr.dictType}") @} - @if(attr.name == "delFlag") { - /*逻辑删除标志*/ - \@InsertIgnore - \@LogicDelete(value = 1) + @if(attr.name == "addUserId") { + /*增加人*/ + \@UpdateIgnore + @} + @if(attr.name == "addDatetime") { + /*增加时间*/ + \@UpdateIgnore @} @if(attr.name == "version") { /*乐观锁版本标志*/ \@InsertIgnore \@Version @} - private ${attr.type} ${attr.name} ; @} diff --git a/admin-core/src/main/resources/codeTemplate/java/query.java b/admin-core/src/main/resources/codeTemplate/java/query.java index 98cf078d933d222b8bfe8dd26dcc304c30cb39d1..0dda9db5d1bbff45cbb9fdbbed4a8d8b56c97b19 100644 --- a/admin-core/src/main/resources/codeTemplate/java/query.java +++ b/admin-core/src/main/resources/codeTemplate/java/query.java @@ -9,11 +9,7 @@ import java.util.Date; */ public class ${entity.name}Query extends PageParam { @for(attr in attrs) { - @if(isNotEmpty(attr.dictType)) { - \@Query(name = "${attr.displayName}", display = true,type=Query.TYPE_DICT,dict="${attr.dictType}") - @}else { \@Query(name = "${attr.displayName}", display = true) - @} private ${attr.javaType} ${attr.name}; @} @for(attr in attrs) { diff --git a/admin-core/src/main/resources/codeTemplate/java/service.java b/admin-core/src/main/resources/codeTemplate/java/service.java index 76784a0d76a2f3a9f3c7971e9fcebc8f43148724..91310872f49298ea7ac85a5a2bd984208a2860b6 100644 --- a/admin-core/src/main/resources/codeTemplate/java/service.java +++ b/admin-core/src/main/resources/codeTemplate/java/service.java @@ -29,7 +29,7 @@ public class ${entity.name}Service extends BaseService<${entity.name}>{ return ret; } - public void batchDel${entity.name}(List ids){ + public void batchDel${entity.name}(List ids){ try { ${entity.code}Dao.batchDel${entity.name}ByIds(ids); } catch (Exception e) { diff --git a/admin-core/src/main/resources/codeTemplate/js/index.js b/admin-core/src/main/resources/codeTemplate/js/index.js index 786af02e8473d4562ebfe8c39188d5da2017fa15..db567f277818977cd728a3926a3876001f585cf4 100644 --- a/admin-core/src/main/resources/codeTemplate/js/index.js +++ b/admin-core/src/main/resources/codeTemplate/js/index.js @@ -67,7 +67,7 @@ layui.define([ 'form', 'laydate', 'table' ], function(exports) { toolbar = { add : function() { // 获取选中数据 var url = "/${target.urlBase}/${entity.code}/add.do"; - Common.openDlg(url,"${entity.displayName}管理>新增"); + Common.openMinDlg(url,"${entity.displayName}管理>新增"); }, edit : function() { // 获取选中数目 var data = Common.getOneFromTable(table,"${entity.code}Table"); @@ -75,7 +75,7 @@ layui.define([ 'form', 'laydate', 'table' ], function(exports) { return ; } var url = "/${target.urlBase}/${entity.code}/edit.do?${entity.idAttribute.name}="+data.${entity.idAttribute.name}; - Common.openDlg(url,"${entity.displayName}管理>"+data.${entity.nameAttribute.name}+">编辑"); + Common.openMinDlg(url,"${entity.displayName}管理>"+data.${entity.nameAttribute.name}+">编辑"); }, del : function() { layui.use(['del'], function(){ diff --git a/admin-core/src/main/resources/codeTemplate/md/entity.md b/admin-core/src/main/resources/codeTemplate/md/entity.md index d2cc745ae86e5e465fe9b214379f1cb81059d19e..41e6f3e07dcd7fb3c228260bc85172f621758741 100644 --- a/admin-core/src/main/resources/codeTemplate/md/entity.md +++ b/admin-core/src/main/resources/codeTemplate/md/entity.md @@ -27,4 +27,4 @@ batchDel${entity.name}ByIds * 批量逻辑删除 update ${entity.tableName} set del_flag = 1 where ${entity.idAttribute.colName} in( #join(ids)#) - + \ No newline at end of file diff --git a/admin-core/src/main/resources/sql/core/coreAudit.md b/admin-core/src/main/resources/sql/core/coreAudit.md new file mode 100644 index 0000000000000000000000000000000000000000..8e0037507e1a7b4514384db99885398329184e17 --- /dev/null +++ b/admin-core/src/main/resources/sql/core/coreAudit.md @@ -0,0 +1,3 @@ +getLastDate +=== + select max(create_time) from core_audit \ No newline at end of file diff --git a/admin-core/src/main/resources/sql/core/coreMenu.md b/admin-core/src/main/resources/sql/core/coreMenu.md index 96301ec87e90b603727863386ed9b0ca0f412371..7660fa3737355d5486fa3ee091c5a3838461aa55 100644 --- a/admin-core/src/main/resources/sql/core/coreMenu.md +++ b/admin-core/src/main/resources/sql/core/coreMenu.md @@ -16,5 +16,5 @@ allMenuWithURL * 获得菜单和对应功能点的URL - select m.*,f.access_url from core_menu m left join core_function f on m.function_id=f.id + select m.*,f.access_url from core_menu m left join core_function f on m.function_id=f.id order by m.seq diff --git a/admin-core/src/main/resources/sql/core/fileUpload.md b/admin-core/src/main/resources/sql/core/fileUpload.md new file mode 100644 index 0000000000000000000000000000000000000000..6e4d5b2d2e21ebfd1798d1571c1694fc643aeb66 --- /dev/null +++ b/admin-core/src/main/resources/sql/core/fileUpload.md @@ -0,0 +1,21 @@ +queryByCondition +=== + select + @pageTag(){ + t.* + @} + from file_upload t + where del_flag=0 + @//数据权限,该sql语句功能点 + and #function("fileUpload.query")# + + + +batchDelFileUploadByIds +=== +* 批量逻辑删除 + update file_upload set del_flag = 1 where ID in( #join(ids)#) + +queryListByFileId +=== + select * from file_upload where id = #fileId# \ No newline at end of file diff --git a/admin-core/src/main/resources/static/css/font_520106_q8xykrwf86ywrk9.css b/admin-core/src/main/resources/static/css/font_520106_q8xykrwf86ywrk9.css new file mode 100644 index 0000000000000000000000000000000000000000..10427fa90bc1bac512e1da9a3d6d297a96f19044 --- /dev/null +++ b/admin-core/src/main/resources/static/css/font_520106_q8xykrwf86ywrk9.css @@ -0,0 +1,27 @@ + +@font-face {font-family: "iconfont"; + src: url('//at.alicdn.com/t/font_520106_q8xykrwf86ywrk9.eot?t=1514171713394'); /* IE9*/ + src: url('//at.alicdn.com/t/font_520106_q8xykrwf86ywrk9.eot?t=1514171713394#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAAAecAAsAAAAADAQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAADMAAABCsP6z7U9TLzIAAAE8AAAARAAAAFZW7kqBY21hcAAAAYAAAACGAAAB3nBhoV1nbHlmAAACCAAAA3MAAAVYQQ4E9WhlYWQAAAV8AAAALgAAADYP7GB/aGhlYQAABawAAAAcAAAAJAfeA4hobXR4AAAFyAAAABMAAAAcG+kAAGxvY2EAAAXcAAAAEAAAABAD8gUmbWF4cAAABewAAAAeAAAAIAEYAJJuYW1lAAAGDAAAAUUAAAJtPlT+fXBvc3QAAAdUAAAASAAAAFvum3XteJxjYGRgYOBikGPQYWB0cfMJYeBgYGGAAJAMY05meiJQDMoDyrGAaQ4gZoOIAgCKIwNPAHicY2Bk/ss4gYGVgYOpk+kMAwNDP4RmfM1gxMjBwMDEwMrMgBUEpLmmMDgwVLyYxNzwv4EhhrmBoQEozAiSAwAv+Q0FeJzFkcEJwzAMRZ8S15RSPEkPGaaHjpJjTx0gt+yRmUS2SL/sQGgXyDfP8D9YMhJwAXrxEAnsgxF6K7Wa99xqnnjKF650ZEYvPvjsyzptm/J/f8j05jjhO9VM6pxlMqfJzmv9q3u9X7uLiYw7+qKXhqaGD43YmM+N2JovjdjmOjXIX37+I7wAAHichVRNbBNHFJ43g2d3vZN1dr0/zgb/rBd7waZG+C+HYOeCiGgRTVWpUqVSlDOCG+LCwUFAe6iqSu0h4ggBhJAgJ8SBS9UDIuLnBOIYC05w7wlv+2Y3CQhBa1nvffO+7+3Me/N2SYaQf8bsASuQPNlLDpLDZIkQ4E2oGrQIQdRt0SY4QcbxbINFYRQoYbXFBuBVue22+926xxWeAwNK0Ana/ahFI+h1h3Qe2m4RYGbW/9aq7bbYb5AtRKVL8Zf0KjjlcHdu+EV8dP+C3a7k1XPCsmYs6xeVZzIqpbtyBpz2XC2jZXm8lsn5zoPyPloGMRP5x76fqsxayz93zxRrngYwGkF+tmLcXDB9E//nfTdvzSjTU2rBnwr32HDutV7Ii2L9FcEfw1pXdhE2Ij4JyXGsM6pjGWUIe916GFS5YpbAC4bQM7ssMAPHduehZtocuXq33wnMsFofAMa59DLSdj2nEyHZLoNLz15TpgVfWRdqvKbpALpGv9H0fZOX0BHaJtzB+GNNCA3KY02PnwhTCBV+QOXdFT41zdc4jNckWEFa19493XrGIW3yjGljVdyf/KUKzKK2ro2PIVSXpRmP5LbX+FaNaG7Rn4hOCmQP1rh19rZrc8+AcGepJGguKIHN2R/v/pZbsixagXu+X9ofMPSEPLIpniSnELEw5QFNgVumm0/obdzXw+4eIPNkkZC8HJEoNMB2OwnGweISD2Ebe5BogkSTYHkVEktNir3LWcPILuuGoS9/ArF70k4GMkA3pJ0cSvDDBA8kS0fCEgBo4rdopH8DKQDa/DyHZSk4NyP2FucmR8pY2QL5mpwkl7C6Ds6LY4AStkDOA8NlZwhzvRbImpUa8kVsr+Sj3hA+5uF/8qEJaeJc8qASdmeHc6Q26dbvG5UGQKOyUWk2f6SLvY3eIkDiKP1VBiup4MR2MJXEpz+fx75T/twhwcAjvucf6Tns+HHkNpGDJrpG/KJ/hNIj/c1U8tV/kXE9DUMqip+n4c1UFD/fzm1UxvLexr2dZMM1CMW7eMOuMBdnbI6QGnYiwI6Y2KNANrOz9So7Jk4QfpAGEEaK/FQtQL97ANL3PXDYKciqkyU1C+jpOvpG6E+W/DD06bofNryLXFj8Bue3uCX4hfjy3g+k6FdXpTRNWL19UYquKyaqMetCg5B/AZan66AAeJxjYGRgYABiBb3/1vH8Nl8ZuFkYQOBaWp8jgv7fwMLA3ADkcjAwgUQBClUJXwAAeJxjYGRgYG7438AQw8IAAkCSkQEVsAMARw0CcHicY2FgYGB+ycDAwoCJARazAQUAAAAAAAB2AOgBJAGSAlgCrHicY2BkYGBgZ2gDYhBgAmIuIGRg+A/mMwAAFr4BqwAAeJxlj01OwzAQhV/6B6QSqqhgh+QFYgEo/RGrblhUavdddN+mTpsqiSPHrdQDcB6OwAk4AtyAO/BIJ5s2lsffvHljTwDc4Acejt8t95E9XDI7cg0XuBeuU38QbpBfhJto41W4Rf1N2MczpsJtdGF5g9e4YvaEd2EPHXwI13CNT+E69S/hBvlbuIk7/Aq30PHqwj7mXle4jUcv9sdWL5xeqeVBxaHJIpM5v4KZXu+Sha3S6pxrW8QmU4OgX0lTnWlb3VPs10PnIhVZk6oJqzpJjMqt2erQBRvn8lGvF4kehCblWGP+tsYCjnEFhSUOjDFCGGSIyujoO1Vm9K+xQ8Jee1Y9zed0WxTU/3OFAQL0z1xTurLSeTpPgT1fG1J1dCtuy56UNJFezUkSskJe1rZUQuoBNmVXjhF6XNGJPyhnSP8ACVpuyAAAAHicbcFRCoAgEAXAfWYqdUqRxQTLELfa2/fRbzNk6LPQPw+DCRYzHDwC4bGpnWp3PiSkODi3rutV+M6xVu7qhpS0CdELRjkO4w==') format('woff'), + url('//at.alicdn.com/t/font_520106_q8xykrwf86ywrk9.ttf?t=1514171713394') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ + url('//at.alicdn.com/t/font_520106_q8xykrwf86ywrk9.svg?t=1514171713394#iconfont') format('svg'); /* iOS 4.1- */ +} + +.iconfont { + font-family:"iconfont" !important; + font-size:16px; + font-style:normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-copy:before { content: "\e60e"; } + +.icon-menu:before { content: "\e630"; } + +.icon-category:before { content: "\e699"; } + +.icon-viewgallery:before { content: "\e6b4"; } + +.icon-tuichu:before { content: "\e892"; } + diff --git a/admin-core/src/main/resources/static/css/login.css b/admin-core/src/main/resources/static/css/login.css new file mode 100644 index 0000000000000000000000000000000000000000..6562cf1726d0214bdab6e697c1cb3afea420e503 --- /dev/null +++ b/admin-core/src/main/resources/static/css/login.css @@ -0,0 +1,357 @@ +body { + color: #3c3c3c; + font-family: "微软雅黑"; + font-size: 14px; + height: 100%; + margin: 0 auto; + min-height: 690px; +} + +html { + color: #000; + background: #F2F2F2; + -webkit-text-size-adjust: 10px; + -ms-text-size-adjust: 100%; +} + +body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, textarea, p, blockquote, th, td, hr, button, article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { + margin: 0; + padding: 0; +} + +body, button, input, select, textarea { + font-size: 14px; +} + +input, select, textarea { + font-size: 100%; + outline: 0; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} + +th { + text-align: inherit; +} + +fieldset, img { + border: 0; +} + +iframe { + display: block; +} + +a { + text-decoration: none; + color: #5C5C5C; +} + +a:hover { + text-decoration: underline; + color: #0085d0; +} + +* { + margin: 0px; + padding: 0px; +} + +ul, ol { + list-style: none; +} + +.hd:after, .bd:after, #header:after, #content:after, #footer:after, .w960:after, .main-con:after { + clear: both; + content: "."; + display: block; + height: 0; + overflow: hidden; + visibility: hidden; +} + +h1, h2, h3, h4, h5, h6 { + font-size: 100%; + font-weight: 500; +} + +select, input { + border: none; +} + +/**百分比显示**/ +.wrap { + height: 660px; + width: 100%; +} + +.main { + width: 100%; + min-width: 1200px; + height: 550px; + text-align: center; + overflow: hidden; + position: relative; + background: url(../images/2-1920550.png) center top no-repeat; +} + +.content { + width: 1200px; + margin: 0 auto; +} + +.header .header-wrap, .footer { + width: 1200px; + margin: 0 auto; + height: 60px; +} + +.header { + width: 100%; + height: 80px; + min-width: 1200px; + background-color: #FFF; + font-size: 23px; + color: #555; + font-weight: bold;; +} + +.header img { + margin-top: 14px; + float: left; +} + +.header span { + display: block; + height: 80px; + line-height: 80px; +} + +.header span em { + font-style: normal; + color: #324ACB; +} + +.footer { + text-align: center; + line-height: 60px; + color: #656565; +} + +.footer span { + color: #999; + margin-left: 15px; +} + +.login { + width: 330px; + height: 380px; + background-color: #FFF; + top: 65px; + left: 50%; + margin-left: 160px; + text-align: left; + position: absolute; + z-index: 2; + padding: 30px 40px 0; +} + +.login h2 { + font-size: 28px; + color: #555; + font-weight: bold; + margin-bottom: 20px; +} + +.form-group { + margin-bottom: 20px; + border: 1px solid #ddd; + border-radius: 3px; + background: url(../images/icon.png) no-repeat; + width: 284px; + height: 43px; + line-height: 43px; + padding: 0 10px 0 34px; + position: relative; +} + +.form-group:hover { + border: 1px solid #5FA7E5; + background-color: #FFF; +} + +.form-control { + font-size: 16px; + color: #797979; + width: 274px; + height: 43px; + line-height: 43px; + background-color: #FFF; + padding-left: 10px; +} + +.form-group button#gh-search-reset { + height: 34px; + line-height: 34px; + color: #B6B6B6; + border: none; + background: none; + font-size: 20px; + cursor: pointer; +} + +.form-group.userId { + background: url(../images/id2.png) no-repeat 10px 10px; +} + +.form-group.userName { + background: url(../images/name2.png) no-repeat 10px 10px; +} + +.form-group.userPwd { + background: url(../images/pwd2.png) no-repeat 10px 10px; +} + +.form-group.userConf { + background: url(../images/conf2.png) no-repeat 10px 10px; +} + +.form-group:hover.userId { + background: url(../images/id1.png) no-repeat 10px 10px; +} + +.form-group:hover.userName { + background: url(../images/name1.png) no-repeat 10px 10px; +} + +.form-group:hover.userPwd { + background: url(../images/pwd1.png) no-repeat 10px 10px; +} + +.form-group:hover.userConf { + background: url(../images/conf1.png) no-repeat 10px 10px; +} + +.confIpt { + width: 360px; + margin-top: 14px; +} + +.confIpt .form-group { + width: 134px; + float: left; + margin-top: 0px; +} + +.confIpt .form-control { + width: 124px; +} + +.conf_img { + margin: 0 5px; + float: left; +} + +.confIpt .refresh { + font-size: 16px; + color: #299FE3; + float: left; + line-height: 46px; +} + +.btn { + background-color: #242994; + width: 330px; + height: 52px; + line-height: 52px; + margin-top: 6px; + font-size: 24px; + color: #FFF; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; + cursor: pointer; + letter-spacing: 8px; + border: none; +} + +.error { + font-size: 16px; + color: #F00; + height: 30px; + line-height: 30px; + overflow: hidden; +} + +body.wh1400 { + min-height: 620px; +} + +.wh1400 .content { + width: 1000px; +} + +.wh1400 .header .header-wrap, .wh1400 .footer { + width: 1000px; +} + +.wh1400 .header { + min-width: 1000px; +} + +.wh1400 .wrap { + height: 620px; + width: 100%; +} + +.wh1400 .main { + width: 100%; + min-width: 1000px; + height: 480px; + text-align: center; + overflow: hidden; + position: relative; + background: url(../images/2-1440480.png) center top no-repeat; +} + +.wh1400 .login { + width: 310px; + height: 375px; + padding: 25px 30px 0; + margin-left: 130px; + top: 40px; +} + +.wh1400 .login h2 { + font-size: 26px; + margin-bottom: 15px; +} + +.wh1400 .form-group { + width: 264px; + height: 44px; + line-height: 44px; +} + +.wh1400 .form-control { + width: 254px; + height: 42px; + line-height: 42px; +} + +.wh1400 .confIpt .form-group { + width: 112px; +} + +.wh1400 .confIpt .form-control { + width: 90px; +} + +.wh1400 .btn { + width: 310px; + height: 50px; + line-height: 50px; +} \ No newline at end of file diff --git a/admin-core/src/main/resources/static/css/pace-theme-flash.css b/admin-core/src/main/resources/static/css/pace-theme-flash.css new file mode 100644 index 0000000000000000000000000000000000000000..e428c5c10a095b3b61789e4c2d4fce229bd1cb54 --- /dev/null +++ b/admin-core/src/main/resources/static/css/pace-theme-flash.css @@ -0,0 +1,77 @@ +/* This is a compiled file, you should be editing the file in the templates directory */ +.pace { + -webkit-pointer-events: none; + pointer-events: none; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; +} + +.pace-inactive { + display: none; +} + +.pace .pace-progress { + background: #e90f92; + position: fixed; + z-index: 2000; + top: 0; + right: 100%; + width: 100%; + height: 2px; +} + +.pace .pace-progress-inner { + display: block; + position: absolute; + right: 0px; + width: 100px; + height: 100%; + box-shadow: 0 0 10px #e90f92, 0 0 5px #e90f92; + opacity: 1.0; + -webkit-transform: rotate(3deg) translate(0px, -4px); + -moz-transform: rotate(3deg) translate(0px, -4px); + -ms-transform: rotate(3deg) translate(0px, -4px); + -o-transform: rotate(3deg) translate(0px, -4px); + transform: rotate(3deg) translate(0px, -4px); +} + +.pace .pace-activity { + display: block; + position: fixed; + z-index: 2000; + top: 15px; + right: 15px; + width: 14px; + height: 14px; + border: solid 2px transparent; + border-top-color: #e90f92; + border-left-color: #e90f92; + border-radius: 10px; + -webkit-animation: pace-spinner 400ms linear infinite; + -moz-animation: pace-spinner 400ms linear infinite; + -ms-animation: pace-spinner 400ms linear infinite; + -o-animation: pace-spinner 400ms linear infinite; + animation: pace-spinner 400ms linear infinite; +} + +@-webkit-keyframes pace-spinner { + 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } + 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); } +} +@-moz-keyframes pace-spinner { + 0% { -moz-transform: rotate(0deg); transform: rotate(0deg); } + 100% { -moz-transform: rotate(360deg); transform: rotate(360deg); } +} +@-o-keyframes pace-spinner { + 0% { -o-transform: rotate(0deg); transform: rotate(0deg); } + 100% { -o-transform: rotate(360deg); transform: rotate(360deg); } +} +@-ms-keyframes pace-spinner { + 0% { -ms-transform: rotate(0deg); transform: rotate(0deg); } + 100% { -ms-transform: rotate(360deg); transform: rotate(360deg); } +} +@keyframes pace-spinner { + 0% { transform: rotate(0deg); transform: rotate(0deg); } + 100% { transform: rotate(360deg); transform: rotate(360deg); } +} diff --git a/admin-core/src/main/resources/static/images/1440480.png b/admin-core/src/main/resources/static/images/1440480.png new file mode 100644 index 0000000000000000000000000000000000000000..f7119a0862e3d56bd4649d53c70e215e598be38f Binary files /dev/null and b/admin-core/src/main/resources/static/images/1440480.png differ diff --git a/admin-core/src/main/resources/static/images/1920550.png b/admin-core/src/main/resources/static/images/1920550.png new file mode 100644 index 0000000000000000000000000000000000000000..ac274f86b46ce6a0e7e6b1c37a5fa56a06f3c8ec Binary files /dev/null and b/admin-core/src/main/resources/static/images/1920550.png differ diff --git a/admin-core/src/main/resources/static/images/2-1440480.png b/admin-core/src/main/resources/static/images/2-1440480.png new file mode 100644 index 0000000000000000000000000000000000000000..6bd77baefec048cca4d4ae7d367a1e114e07bb54 Binary files /dev/null and b/admin-core/src/main/resources/static/images/2-1440480.png differ diff --git a/admin-core/src/main/resources/static/images/2-1920550.png b/admin-core/src/main/resources/static/images/2-1920550.png new file mode 100644 index 0000000000000000000000000000000000000000..49c77678eef98047069f226114512851ecf9082f Binary files /dev/null and b/admin-core/src/main/resources/static/images/2-1920550.png differ diff --git a/admin-core/src/main/resources/static/images/3-1440480.png b/admin-core/src/main/resources/static/images/3-1440480.png new file mode 100644 index 0000000000000000000000000000000000000000..ee8afbd8ae39d120c2de3cad2e715f7028cccc28 Binary files /dev/null and b/admin-core/src/main/resources/static/images/3-1440480.png differ diff --git a/admin-core/src/main/resources/static/images/3-1920550.png b/admin-core/src/main/resources/static/images/3-1920550.png new file mode 100644 index 0000000000000000000000000000000000000000..32f9120943a1cabad8637ed58ce7bc83b9d74590 Binary files /dev/null and b/admin-core/src/main/resources/static/images/3-1920550.png differ diff --git a/admin-core/src/main/resources/static/images/4-1440480.png b/admin-core/src/main/resources/static/images/4-1440480.png new file mode 100644 index 0000000000000000000000000000000000000000..d47931745c4dc07047a57d2336fe4cab808468dc Binary files /dev/null and b/admin-core/src/main/resources/static/images/4-1440480.png differ diff --git a/admin-core/src/main/resources/static/images/4-1920550.png b/admin-core/src/main/resources/static/images/4-1920550.png new file mode 100644 index 0000000000000000000000000000000000000000..db9447416c73256ab054cc303509cbaa4e7dbdef Binary files /dev/null and b/admin-core/src/main/resources/static/images/4-1920550.png differ diff --git a/admin-core/src/main/resources/static/images/5-1440480.png b/admin-core/src/main/resources/static/images/5-1440480.png new file mode 100644 index 0000000000000000000000000000000000000000..2acb494b12d5ed628d8215beafd52fc69ba5d817 Binary files /dev/null and b/admin-core/src/main/resources/static/images/5-1440480.png differ diff --git a/admin-core/src/main/resources/static/images/5-1920550.png b/admin-core/src/main/resources/static/images/5-1920550.png new file mode 100644 index 0000000000000000000000000000000000000000..4977e67738b20f811391a500c1e885bed59c23cb Binary files /dev/null and b/admin-core/src/main/resources/static/images/5-1920550.png differ diff --git a/admin-core/src/main/resources/static/images/conf1.png b/admin-core/src/main/resources/static/images/conf1.png new file mode 100644 index 0000000000000000000000000000000000000000..5e19fbbbabc5ebb33adfe16f72128a4091b2cb8c Binary files /dev/null and b/admin-core/src/main/resources/static/images/conf1.png differ diff --git a/admin-core/src/main/resources/static/images/conf2.png b/admin-core/src/main/resources/static/images/conf2.png new file mode 100644 index 0000000000000000000000000000000000000000..905d7abffffe077e2b19947f1b64fd380e246c55 Binary files /dev/null and b/admin-core/src/main/resources/static/images/conf2.png differ diff --git a/admin-core/src/main/resources/static/images/logo50.png b/admin-core/src/main/resources/static/images/logo50.png new file mode 100644 index 0000000000000000000000000000000000000000..05320ce637642daa21b501fde0dfbe08c3665bcd Binary files /dev/null and b/admin-core/src/main/resources/static/images/logo50.png differ diff --git a/admin-core/src/main/resources/static/images/logo80.png b/admin-core/src/main/resources/static/images/logo80.png new file mode 100644 index 0000000000000000000000000000000000000000..88255d812133b3d4e6642ad495a89e2073af6e47 Binary files /dev/null and b/admin-core/src/main/resources/static/images/logo80.png differ diff --git a/admin-core/src/main/resources/static/images/name1.png b/admin-core/src/main/resources/static/images/name1.png new file mode 100644 index 0000000000000000000000000000000000000000..ddee537b9b7eeb50e7f7d0315e600fb38aa26ea4 Binary files /dev/null and b/admin-core/src/main/resources/static/images/name1.png differ diff --git a/admin-core/src/main/resources/static/images/name2.png b/admin-core/src/main/resources/static/images/name2.png new file mode 100644 index 0000000000000000000000000000000000000000..65a6d629b5cf49f2fbe227a587165320e6fa5ed6 Binary files /dev/null and b/admin-core/src/main/resources/static/images/name2.png differ diff --git a/admin-core/src/main/resources/static/images/pwd1.png b/admin-core/src/main/resources/static/images/pwd1.png new file mode 100644 index 0000000000000000000000000000000000000000..3346d335f904738f6a2d8d1343f0b9208ed1504c Binary files /dev/null and b/admin-core/src/main/resources/static/images/pwd1.png differ diff --git a/admin-core/src/main/resources/static/images/pwd2.png b/admin-core/src/main/resources/static/images/pwd2.png new file mode 100644 index 0000000000000000000000000000000000000000..1e20a7863d6c4890f5acaea9fe30dd14b7e4f780 Binary files /dev/null and b/admin-core/src/main/resources/static/images/pwd2.png differ diff --git a/admin-core/src/main/resources/static/images/shouye.png b/admin-core/src/main/resources/static/images/shouye.png new file mode 100644 index 0000000000000000000000000000000000000000..771f39ddd026a9ab8b059936d9e652625b0de70b Binary files /dev/null and b/admin-core/src/main/resources/static/images/shouye.png differ diff --git a/admin-core/src/main/resources/static/images/yanzheng.png b/admin-core/src/main/resources/static/images/yanzheng.png new file mode 100644 index 0000000000000000000000000000000000000000..65e8f95c6f7acc9be3e637e86601f42e7dbfa4dd Binary files /dev/null and b/admin-core/src/main/resources/static/images/yanzheng.png differ diff --git a/admin-core/src/main/resources/static/js/common.js b/admin-core/src/main/resources/static/js/common.js index e3af2b8697598b02b172f1ebb887adc7bb612046..bf1531edc1bd5981880982548907adb1a8cebb73 100644 --- a/admin-core/src/main/resources/static/js/common.js +++ b/admin-core/src/main/resources/static/js/common.js @@ -70,13 +70,23 @@ var Common = { } }, openDlg:function(url,title){ - var index = layer.open({ + var index = layer.open({ type: 2, content: Common.ctxPath+url, title: title, maxmin: false }); - layer.full(index); + layer.full(index); + }, + openMinDlg:function(url,title){ + layer.open({ + type: 2, + content: Common.ctxPath+url, + title: title, + maxmin: true, + offset: 'auto', + area : [ '700px', '400px' ] + }); }, topOpenDlg:function(url,title){ var index = top.layer.open({ diff --git a/admin-core/src/main/resources/static/js/lib.js b/admin-core/src/main/resources/static/js/lib.js index 4bb486fe52f77a2d40330dc7ef52385cff75d2d9..7c34481ad943cf3e8f92a51e5fecbfa389bc89d0 100644 --- a/admin-core/src/main/resources/static/js/lib.js +++ b/admin-core/src/main/resources/static/js/lib.js @@ -201,6 +201,14 @@ var Lib = { laydate.render({ elem : $(this)[0], }); + }); + + $(form).find(".input-year").each(function() { + laydate = layui.laydate; + laydate.render({ + elem : $(this)[0], + type:'year' + }); }) diff --git a/admin-core/src/main/resources/static/js/pace.min.js b/admin-core/src/main/resources/static/js/pace.min.js new file mode 100644 index 0000000000000000000000000000000000000000..234f9b3e93f06a85cb2ec01acc872ccdc2bec7cb --- /dev/null +++ b/admin-core/src/main/resources/static/js/pace.min.js @@ -0,0 +1,2 @@ +/*! pace 1.0.2 */ +(function(){var a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X=[].slice,Y={}.hasOwnProperty,Z=function(a,b){function c(){this.constructor=a}for(var d in b)Y.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},$=[].indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(b in this&&this[b]===a)return b;return-1};for(u={catchupTime:100,initialRate:.03,minTime:250,ghostTime:100,maxProgressPerFrame:20,easeFactor:1.25,startOnPageLoad:!0,restartOnPushState:!0,restartOnRequestAfter:500,target:"body",elements:{checkInterval:100,selectors:["body"]},eventLag:{minSamples:10,sampleCount:3,lagThreshold:3},ajax:{trackMethods:["GET"],trackWebSockets:!0,ignoreURLs:[]}},C=function(){var a;return null!=(a="undefined"!=typeof performance&&null!==performance&&"function"==typeof performance.now?performance.now():void 0)?a:+new Date},E=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame,t=window.cancelAnimationFrame||window.mozCancelAnimationFrame,null==E&&(E=function(a){return setTimeout(a,50)},t=function(a){return clearTimeout(a)}),G=function(a){var b,c;return b=C(),(c=function(){var d;return d=C()-b,d>=33?(b=C(),a(d,function(){return E(c)})):setTimeout(c,33-d)})()},F=function(){var a,b,c;return c=arguments[0],b=arguments[1],a=3<=arguments.length?X.call(arguments,2):[],"function"==typeof c[b]?c[b].apply(c,a):c[b]},v=function(){var a,b,c,d,e,f,g;for(b=arguments[0],d=2<=arguments.length?X.call(arguments,1):[],f=0,g=d.length;g>f;f++)if(c=d[f])for(a in c)Y.call(c,a)&&(e=c[a],null!=b[a]&&"object"==typeof b[a]&&null!=e&&"object"==typeof e?v(b[a],e):b[a]=e);return b},q=function(a){var b,c,d,e,f;for(c=b=0,e=0,f=a.length;f>e;e++)d=a[e],c+=Math.abs(d),b++;return c/b},x=function(a,b){var c,d,e;if(null==a&&(a="options"),null==b&&(b=!0),e=document.querySelector("[data-pace-"+a+"]")){if(c=e.getAttribute("data-pace-"+a),!b)return c;try{return JSON.parse(c)}catch(f){return d=f,"undefined"!=typeof console&&null!==console?console.error("Error parsing inline pace options",d):void 0}}},g=function(){function a(){}return a.prototype.on=function(a,b,c,d){var e;return null==d&&(d=!1),null==this.bindings&&(this.bindings={}),null==(e=this.bindings)[a]&&(e[a]=[]),this.bindings[a].push({handler:b,ctx:c,once:d})},a.prototype.once=function(a,b,c){return this.on(a,b,c,!0)},a.prototype.off=function(a,b){var c,d,e;if(null!=(null!=(d=this.bindings)?d[a]:void 0)){if(null==b)return delete this.bindings[a];for(c=0,e=[];cQ;Q++)K=U[Q],D[K]===!0&&(D[K]=u[K]);i=function(a){function b(){return V=b.__super__.constructor.apply(this,arguments)}return Z(b,a),b}(Error),b=function(){function a(){this.progress=0}return a.prototype.getElement=function(){var a;if(null==this.el){if(a=document.querySelector(D.target),!a)throw new i;this.el=document.createElement("div"),this.el.className="pace pace-active",document.body.className=document.body.className.replace(/pace-done/g,""),document.body.className+=" pace-running",this.el.innerHTML='
\n
\n
\n
',null!=a.firstChild?a.insertBefore(this.el,a.firstChild):a.appendChild(this.el)}return this.el},a.prototype.finish=function(){var a;return a=this.getElement(),a.className=a.className.replace("pace-active",""),a.className+=" pace-inactive",document.body.className=document.body.className.replace("pace-running",""),document.body.className+=" pace-done"},a.prototype.update=function(a){return this.progress=a,this.render()},a.prototype.destroy=function(){try{this.getElement().parentNode.removeChild(this.getElement())}catch(a){i=a}return this.el=void 0},a.prototype.render=function(){var a,b,c,d,e,f,g;if(null==document.querySelector(D.target))return!1;for(a=this.getElement(),d="translate3d("+this.progress+"%, 0, 0)",g=["webkitTransform","msTransform","transform"],e=0,f=g.length;f>e;e++)b=g[e],a.children[0].style[b]=d;return(!this.lastRenderedProgress||this.lastRenderedProgress|0!==this.progress|0)&&(a.children[0].setAttribute("data-progress-text",""+(0|this.progress)+"%"),this.progress>=100?c="99":(c=this.progress<10?"0":"",c+=0|this.progress),a.children[0].setAttribute("data-progress",""+c)),this.lastRenderedProgress=this.progress},a.prototype.done=function(){return this.progress>=100},a}(),h=function(){function a(){this.bindings={}}return a.prototype.trigger=function(a,b){var c,d,e,f,g;if(null!=this.bindings[a]){for(f=this.bindings[a],g=[],d=0,e=f.length;e>d;d++)c=f[d],g.push(c.call(this,b));return g}},a.prototype.on=function(a,b){var c;return null==(c=this.bindings)[a]&&(c[a]=[]),this.bindings[a].push(b)},a}(),P=window.XMLHttpRequest,O=window.XDomainRequest,N=window.WebSocket,w=function(a,b){var c,d,e;e=[];for(d in b.prototype)try{e.push(null==a[d]&&"function"!=typeof b[d]?"function"==typeof Object.defineProperty?Object.defineProperty(a,d,{get:function(){return b.prototype[d]},configurable:!0,enumerable:!0}):a[d]=b.prototype[d]:void 0)}catch(f){c=f}return e},A=[],j.ignore=function(){var a,b,c;return b=arguments[0],a=2<=arguments.length?X.call(arguments,1):[],A.unshift("ignore"),c=b.apply(null,a),A.shift(),c},j.track=function(){var a,b,c;return b=arguments[0],a=2<=arguments.length?X.call(arguments,1):[],A.unshift("track"),c=b.apply(null,a),A.shift(),c},J=function(a){var b;if(null==a&&(a="GET"),"track"===A[0])return"force";if(!A.length&&D.ajax){if("socket"===a&&D.ajax.trackWebSockets)return!0;if(b=a.toUpperCase(),$.call(D.ajax.trackMethods,b)>=0)return!0}return!1},k=function(a){function b(){var a,c=this;b.__super__.constructor.apply(this,arguments),a=function(a){var b;return b=a.open,a.open=function(d,e){return J(d)&&c.trigger("request",{type:d,url:e,request:a}),b.apply(a,arguments)}},window.XMLHttpRequest=function(b){var c;return c=new P(b),a(c),c};try{w(window.XMLHttpRequest,P)}catch(d){}if(null!=O){window.XDomainRequest=function(){var b;return b=new O,a(b),b};try{w(window.XDomainRequest,O)}catch(d){}}if(null!=N&&D.ajax.trackWebSockets){window.WebSocket=function(a,b){var d;return d=null!=b?new N(a,b):new N(a),J("socket")&&c.trigger("request",{type:"socket",url:a,protocols:b,request:d}),d};try{w(window.WebSocket,N)}catch(d){}}}return Z(b,a),b}(h),R=null,y=function(){return null==R&&(R=new k),R},I=function(a){var b,c,d,e;for(e=D.ajax.ignoreURLs,c=0,d=e.length;d>c;c++)if(b=e[c],"string"==typeof b){if(-1!==a.indexOf(b))return!0}else if(b.test(a))return!0;return!1},y().on("request",function(b){var c,d,e,f,g;return f=b.type,e=b.request,g=b.url,I(g)?void 0:j.running||D.restartOnRequestAfter===!1&&"force"!==J(f)?void 0:(d=arguments,c=D.restartOnRequestAfter||0,"boolean"==typeof c&&(c=0),setTimeout(function(){var b,c,g,h,i,k;if(b="socket"===f?e.readyState<2:0<(h=e.readyState)&&4>h){for(j.restart(),i=j.sources,k=[],c=0,g=i.length;g>c;c++){if(K=i[c],K instanceof a){K.watch.apply(K,d);break}k.push(void 0)}return k}},c))}),a=function(){function a(){var a=this;this.elements=[],y().on("request",function(){return a.watch.apply(a,arguments)})}return a.prototype.watch=function(a){var b,c,d,e;return d=a.type,b=a.request,e=a.url,I(e)?void 0:(c="socket"===d?new n(b):new o(b),this.elements.push(c))},a}(),o=function(){function a(a){var b,c,d,e,f,g,h=this;if(this.progress=0,null!=window.ProgressEvent)for(c=null,a.addEventListener("progress",function(a){return h.progress=a.lengthComputable?100*a.loaded/a.total:h.progress+(100-h.progress)/2},!1),g=["load","abort","timeout","error"],d=0,e=g.length;e>d;d++)b=g[d],a.addEventListener(b,function(){return h.progress=100},!1);else f=a.onreadystatechange,a.onreadystatechange=function(){var b;return 0===(b=a.readyState)||4===b?h.progress=100:3===a.readyState&&(h.progress=50),"function"==typeof f?f.apply(null,arguments):void 0}}return a}(),n=function(){function a(a){var b,c,d,e,f=this;for(this.progress=0,e=["error","open"],c=0,d=e.length;d>c;c++)b=e[c],a.addEventListener(b,function(){return f.progress=100},!1)}return a}(),d=function(){function a(a){var b,c,d,f;for(null==a&&(a={}),this.elements=[],null==a.selectors&&(a.selectors=[]),f=a.selectors,c=0,d=f.length;d>c;c++)b=f[c],this.elements.push(new e(b))}return a}(),e=function(){function a(a){this.selector=a,this.progress=0,this.check()}return a.prototype.check=function(){var a=this;return document.querySelector(this.selector)?this.done():setTimeout(function(){return a.check()},D.elements.checkInterval)},a.prototype.done=function(){return this.progress=100},a}(),c=function(){function a(){var a,b,c=this;this.progress=null!=(b=this.states[document.readyState])?b:100,a=document.onreadystatechange,document.onreadystatechange=function(){return null!=c.states[document.readyState]&&(c.progress=c.states[document.readyState]),"function"==typeof a?a.apply(null,arguments):void 0}}return a.prototype.states={loading:0,interactive:50,complete:100},a}(),f=function(){function a(){var a,b,c,d,e,f=this;this.progress=0,a=0,e=[],d=0,c=C(),b=setInterval(function(){var g;return g=C()-c-50,c=C(),e.push(g),e.length>D.eventLag.sampleCount&&e.shift(),a=q(e),++d>=D.eventLag.minSamples&&a=100&&(this.done=!0),b===this.last?this.sinceLastUpdate+=a:(this.sinceLastUpdate&&(this.rate=(b-this.last)/this.sinceLastUpdate),this.catchup=(b-this.progress)/D.catchupTime,this.sinceLastUpdate=0,this.last=b),b>this.progress&&(this.progress+=this.catchup*a),c=1-Math.pow(this.progress/100,D.easeFactor),this.progress+=c*this.rate*a,this.progress=Math.min(this.lastProgress+D.maxProgressPerFrame,this.progress),this.progress=Math.max(0,this.progress),this.progress=Math.min(100,this.progress),this.lastProgress=this.progress,this.progress},a}(),L=null,H=null,r=null,M=null,p=null,s=null,j.running=!1,z=function(){return D.restartOnPushState?j.restart():void 0},null!=window.history.pushState&&(T=window.history.pushState,window.history.pushState=function(){return z(),T.apply(window.history,arguments)}),null!=window.history.replaceState&&(W=window.history.replaceState,window.history.replaceState=function(){return z(),W.apply(window.history,arguments)}),l={ajax:a,elements:d,document:c,eventLag:f},(B=function(){var a,c,d,e,f,g,h,i;for(j.sources=L=[],g=["ajax","elements","document","eventLag"],c=0,e=g.length;e>c;c++)a=g[c],D[a]!==!1&&L.push(new l[a](D[a]));for(i=null!=(h=D.extraSources)?h:[],d=0,f=i.length;f>d;d++)K=i[d],L.push(new K(D));return j.bar=r=new b,H=[],M=new m})(),j.stop=function(){return j.trigger("stop"),j.running=!1,r.destroy(),s=!0,null!=p&&("function"==typeof t&&t(p),p=null),B()},j.restart=function(){return j.trigger("restart"),j.stop(),j.start()},j.go=function(){var a;return j.running=!0,r.render(),a=C(),s=!1,p=G(function(b,c){var d,e,f,g,h,i,k,l,n,o,p,q,t,u,v,w;for(l=100-r.progress,e=p=0,f=!0,i=q=0,u=L.length;u>q;i=++q)for(K=L[i],o=null!=H[i]?H[i]:H[i]=[],h=null!=(w=K.elements)?w:[K],k=t=0,v=h.length;v>t;k=++t)g=h[k],n=null!=o[k]?o[k]:o[k]=new m(g),f&=n.done,n.done||(e++,p+=n.tick(b));return d=p/e,r.update(M.tick(b,d)),r.done()||f||s?(r.update(100),j.trigger("done"),setTimeout(function(){return r.finish(),j.running=!1,j.trigger("hide")},Math.max(D.ghostTime,Math.max(D.minTime-(C()-a),0)))):c()})},j.start=function(a){v(D,a),j.running=!0;try{r.render()}catch(b){i=b}return document.querySelector(".pace")?(j.trigger("start"),j.go()):setTimeout(j.start,50)},"function"==typeof define&&define.amd?define(["pace"],function(){return j}):"object"==typeof exports?module.exports=j:D.startOnPageLoad&&j.start()}).call(this); \ No newline at end of file diff --git a/admin-core/src/main/resources/static/plugins/font-awesome/css/font-awesome.css b/admin-core/src/main/resources/static/plugins/font-awesome/css/font-awesome.css new file mode 100644 index 0000000000000000000000000000000000000000..ee906a8196d0fbd581c27a9d5615db4c250860f2 --- /dev/null +++ b/admin-core/src/main/resources/static/plugins/font-awesome/css/font-awesome.css @@ -0,0 +1,2337 @@ +/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */ +/* FONT PATH + * -------------------------- */ +@font-face { + font-family: 'FontAwesome'; + src: url('../fonts/fontawesome-webfont.eot?v=4.7.0'); + src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg'); + font-weight: normal; + font-style: normal; +} +.fa { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +/* makes the font 33% larger relative to the icon container */ +.fa-lg { + font-size: 1.33333333em; + line-height: 0.75em; + vertical-align: -15%; +} +.fa-2x { + font-size: 2em; +} +.fa-3x { + font-size: 3em; +} +.fa-4x { + font-size: 4em; +} +.fa-5x { + font-size: 5em; +} +.fa-fw { + width: 1.28571429em; + text-align: center; +} +.fa-ul { + padding-left: 0; + margin-left: 2.14285714em; + list-style-type: none; +} +.fa-ul > li { + position: relative; +} +.fa-li { + position: absolute; + left: -2.14285714em; + width: 2.14285714em; + top: 0.14285714em; + text-align: center; +} +.fa-li.fa-lg { + left: -1.85714286em; +} +.fa-border { + padding: .2em .25em .15em; + border: solid 0.08em #eeeeee; + border-radius: .1em; +} +.fa-pull-left { + float: left; +} +.fa-pull-right { + float: right; +} +.fa.fa-pull-left { + margin-right: .3em; +} +.fa.fa-pull-right { + margin-left: .3em; +} +/* Deprecated as of 4.4.0 */ +.pull-right { + float: right; +} +.pull-left { + float: left; +} +.fa.pull-left { + margin-right: .3em; +} +.fa.pull-right { + margin-left: .3em; +} +.fa-spin { + -webkit-animation: fa-spin 2s infinite linear; + animation: fa-spin 2s infinite linear; +} +.fa-pulse { + -webkit-animation: fa-spin 1s infinite steps(8); + animation: fa-spin 1s infinite steps(8); +} +@-webkit-keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +@keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +.fa-rotate-90 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"; + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg); +} +.fa-rotate-180 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)"; + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} +.fa-rotate-270 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)"; + -webkit-transform: rotate(270deg); + -ms-transform: rotate(270deg); + transform: rotate(270deg); +} +.fa-flip-horizontal { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)"; + -webkit-transform: scale(-1, 1); + -ms-transform: scale(-1, 1); + transform: scale(-1, 1); +} +.fa-flip-vertical { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; + -webkit-transform: scale(1, -1); + -ms-transform: scale(1, -1); + transform: scale(1, -1); +} +:root .fa-rotate-90, +:root .fa-rotate-180, +:root .fa-rotate-270, +:root .fa-flip-horizontal, +:root .fa-flip-vertical { + filter: none; +} +.fa-stack { + position: relative; + display: inline-block; + width: 2em; + height: 2em; + line-height: 2em; + vertical-align: middle; +} +.fa-stack-1x, +.fa-stack-2x { + position: absolute; + left: 0; + width: 100%; + text-align: center; +} +.fa-stack-1x { + line-height: inherit; +} +.fa-stack-2x { + font-size: 2em; +} +.fa-inverse { + color: #ffffff; +} +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen + readers do not read off random characters that represent icons */ +.fa-glass:before { + content: "\f000"; +} +.fa-music:before { + content: "\f001"; +} +.fa-search:before { + content: "\f002"; +} +.fa-envelope-o:before { + content: "\f003"; +} +.fa-heart:before { + content: "\f004"; +} +.fa-star:before { + content: "\f005"; +} +.fa-star-o:before { + content: "\f006"; +} +.fa-user:before { + content: "\f007"; +} +.fa-film:before { + content: "\f008"; +} +.fa-th-large:before { + content: "\f009"; +} +.fa-th:before { + content: "\f00a"; +} +.fa-th-list:before { + content: "\f00b"; +} +.fa-check:before { + content: "\f00c"; +} +.fa-remove:before, +.fa-close:before, +.fa-times:before { + content: "\f00d"; +} +.fa-search-plus:before { + content: "\f00e"; +} +.fa-search-minus:before { + content: "\f010"; +} +.fa-power-off:before { + content: "\f011"; +} +.fa-signal:before { + content: "\f012"; +} +.fa-gear:before, +.fa-cog:before { + content: "\f013"; +} +.fa-trash-o:before { + content: "\f014"; +} +.fa-home:before { + content: "\f015"; +} +.fa-file-o:before { + content: "\f016"; +} +.fa-clock-o:before { + content: "\f017"; +} +.fa-road:before { + content: "\f018"; +} +.fa-download:before { + content: "\f019"; +} +.fa-arrow-circle-o-down:before { + content: "\f01a"; +} +.fa-arrow-circle-o-up:before { + content: "\f01b"; +} +.fa-inbox:before { + content: "\f01c"; +} +.fa-play-circle-o:before { + content: "\f01d"; +} +.fa-rotate-right:before, +.fa-repeat:before { + content: "\f01e"; +} +.fa-refresh:before { + content: "\f021"; +} +.fa-list-alt:before { + content: "\f022"; +} +.fa-lock:before { + content: "\f023"; +} +.fa-flag:before { + content: "\f024"; +} +.fa-headphones:before { + content: "\f025"; +} +.fa-volume-off:before { + content: "\f026"; +} +.fa-volume-down:before { + content: "\f027"; +} +.fa-volume-up:before { + content: "\f028"; +} +.fa-qrcode:before { + content: "\f029"; +} +.fa-barcode:before { + content: "\f02a"; +} +.fa-tag:before { + content: "\f02b"; +} +.fa-tags:before { + content: "\f02c"; +} +.fa-book:before { + content: "\f02d"; +} +.fa-bookmark:before { + content: "\f02e"; +} +.fa-print:before { + content: "\f02f"; +} +.fa-camera:before { + content: "\f030"; +} +.fa-font:before { + content: "\f031"; +} +.fa-bold:before { + content: "\f032"; +} +.fa-italic:before { + content: "\f033"; +} +.fa-text-height:before { + content: "\f034"; +} +.fa-text-width:before { + content: "\f035"; +} +.fa-align-left:before { + content: "\f036"; +} +.fa-align-center:before { + content: "\f037"; +} +.fa-align-right:before { + content: "\f038"; +} +.fa-align-justify:before { + content: "\f039"; +} +.fa-list:before { + content: "\f03a"; +} +.fa-dedent:before, +.fa-outdent:before { + content: "\f03b"; +} +.fa-indent:before { + content: "\f03c"; +} +.fa-video-camera:before { + content: "\f03d"; +} +.fa-photo:before, +.fa-image:before, +.fa-picture-o:before { + content: "\f03e"; +} +.fa-pencil:before { + content: "\f040"; +} +.fa-map-marker:before { + content: "\f041"; +} +.fa-adjust:before { + content: "\f042"; +} +.fa-tint:before { + content: "\f043"; +} +.fa-edit:before, +.fa-pencil-square-o:before { + content: "\f044"; +} +.fa-share-square-o:before { + content: "\f045"; +} +.fa-check-square-o:before { + content: "\f046"; +} +.fa-arrows:before { + content: "\f047"; +} +.fa-step-backward:before { + content: "\f048"; +} +.fa-fast-backward:before { + content: "\f049"; +} +.fa-backward:before { + content: "\f04a"; +} +.fa-play:before { + content: "\f04b"; +} +.fa-pause:before { + content: "\f04c"; +} +.fa-stop:before { + content: "\f04d"; +} +.fa-forward:before { + content: "\f04e"; +} +.fa-fast-forward:before { + content: "\f050"; +} +.fa-step-forward:before { + content: "\f051"; +} +.fa-eject:before { + content: "\f052"; +} +.fa-chevron-left:before { + content: "\f053"; +} +.fa-chevron-right:before { + content: "\f054"; +} +.fa-plus-circle:before { + content: "\f055"; +} +.fa-minus-circle:before { + content: "\f056"; +} +.fa-times-circle:before { + content: "\f057"; +} +.fa-check-circle:before { + content: "\f058"; +} +.fa-question-circle:before { + content: "\f059"; +} +.fa-info-circle:before { + content: "\f05a"; +} +.fa-crosshairs:before { + content: "\f05b"; +} +.fa-times-circle-o:before { + content: "\f05c"; +} +.fa-check-circle-o:before { + content: "\f05d"; +} +.fa-ban:before { + content: "\f05e"; +} +.fa-arrow-left:before { + content: "\f060"; +} +.fa-arrow-right:before { + content: "\f061"; +} +.fa-arrow-up:before { + content: "\f062"; +} +.fa-arrow-down:before { + content: "\f063"; +} +.fa-mail-forward:before, +.fa-share:before { + content: "\f064"; +} +.fa-expand:before { + content: "\f065"; +} +.fa-compress:before { + content: "\f066"; +} +.fa-plus:before { + content: "\f067"; +} +.fa-minus:before { + content: "\f068"; +} +.fa-asterisk:before { + content: "\f069"; +} +.fa-exclamation-circle:before { + content: "\f06a"; +} +.fa-gift:before { + content: "\f06b"; +} +.fa-leaf:before { + content: "\f06c"; +} +.fa-fire:before { + content: "\f06d"; +} +.fa-eye:before { + content: "\f06e"; +} +.fa-eye-slash:before { + content: "\f070"; +} +.fa-warning:before, +.fa-exclamation-triangle:before { + content: "\f071"; +} +.fa-plane:before { + content: "\f072"; +} +.fa-calendar:before { + content: "\f073"; +} +.fa-random:before { + content: "\f074"; +} +.fa-comment:before { + content: "\f075"; +} +.fa-magnet:before { + content: "\f076"; +} +.fa-chevron-up:before { + content: "\f077"; +} +.fa-chevron-down:before { + content: "\f078"; +} +.fa-retweet:before { + content: "\f079"; +} +.fa-shopping-cart:before { + content: "\f07a"; +} +.fa-folder:before { + content: "\f07b"; +} +.fa-folder-open:before { + content: "\f07c"; +} +.fa-arrows-v:before { + content: "\f07d"; +} +.fa-arrows-h:before { + content: "\f07e"; +} +.fa-bar-chart-o:before, +.fa-bar-chart:before { + content: "\f080"; +} +.fa-twitter-square:before { + content: "\f081"; +} +.fa-facebook-square:before { + content: "\f082"; +} +.fa-camera-retro:before { + content: "\f083"; +} +.fa-key:before { + content: "\f084"; +} +.fa-gears:before, +.fa-cogs:before { + content: "\f085"; +} +.fa-comments:before { + content: "\f086"; +} +.fa-thumbs-o-up:before { + content: "\f087"; +} +.fa-thumbs-o-down:before { + content: "\f088"; +} +.fa-star-half:before { + content: "\f089"; +} +.fa-heart-o:before { + content: "\f08a"; +} +.fa-sign-out:before { + content: "\f08b"; +} +.fa-linkedin-square:before { + content: "\f08c"; +} +.fa-thumb-tack:before { + content: "\f08d"; +} +.fa-external-link:before { + content: "\f08e"; +} +.fa-sign-in:before { + content: "\f090"; +} +.fa-trophy:before { + content: "\f091"; +} +.fa-github-square:before { + content: "\f092"; +} +.fa-upload:before { + content: "\f093"; +} +.fa-lemon-o:before { + content: "\f094"; +} +.fa-phone:before { + content: "\f095"; +} +.fa-square-o:before { + content: "\f096"; +} +.fa-bookmark-o:before { + content: "\f097"; +} +.fa-phone-square:before { + content: "\f098"; +} +.fa-twitter:before { + content: "\f099"; +} +.fa-facebook-f:before, +.fa-facebook:before { + content: "\f09a"; +} +.fa-github:before { + content: "\f09b"; +} +.fa-unlock:before { + content: "\f09c"; +} +.fa-credit-card:before { + content: "\f09d"; +} +.fa-feed:before, +.fa-rss:before { + content: "\f09e"; +} +.fa-hdd-o:before { + content: "\f0a0"; +} +.fa-bullhorn:before { + content: "\f0a1"; +} +.fa-bell:before { + content: "\f0f3"; +} +.fa-certificate:before { + content: "\f0a3"; +} +.fa-hand-o-right:before { + content: "\f0a4"; +} +.fa-hand-o-left:before { + content: "\f0a5"; +} +.fa-hand-o-up:before { + content: "\f0a6"; +} +.fa-hand-o-down:before { + content: "\f0a7"; +} +.fa-arrow-circle-left:before { + content: "\f0a8"; +} +.fa-arrow-circle-right:before { + content: "\f0a9"; +} +.fa-arrow-circle-up:before { + content: "\f0aa"; +} +.fa-arrow-circle-down:before { + content: "\f0ab"; +} +.fa-globe:before { + content: "\f0ac"; +} +.fa-wrench:before { + content: "\f0ad"; +} +.fa-tasks:before { + content: "\f0ae"; +} +.fa-filter:before { + content: "\f0b0"; +} +.fa-briefcase:before { + content: "\f0b1"; +} +.fa-arrows-alt:before { + content: "\f0b2"; +} +.fa-group:before, +.fa-users:before { + content: "\f0c0"; +} +.fa-chain:before, +.fa-link:before { + content: "\f0c1"; +} +.fa-cloud:before { + content: "\f0c2"; +} +.fa-flask:before { + content: "\f0c3"; +} +.fa-cut:before, +.fa-scissors:before { + content: "\f0c4"; +} +.fa-copy:before, +.fa-files-o:before { + content: "\f0c5"; +} +.fa-paperclip:before { + content: "\f0c6"; +} +.fa-save:before, +.fa-floppy-o:before { + content: "\f0c7"; +} +.fa-square:before { + content: "\f0c8"; +} +.fa-navicon:before, +.fa-reorder:before, +.fa-bars:before { + content: "\f0c9"; +} +.fa-list-ul:before { + content: "\f0ca"; +} +.fa-list-ol:before { + content: "\f0cb"; +} +.fa-strikethrough:before { + content: "\f0cc"; +} +.fa-underline:before { + content: "\f0cd"; +} +.fa-table:before { + content: "\f0ce"; +} +.fa-magic:before { + content: "\f0d0"; +} +.fa-truck:before { + content: "\f0d1"; +} +.fa-pinterest:before { + content: "\f0d2"; +} +.fa-pinterest-square:before { + content: "\f0d3"; +} +.fa-google-plus-square:before { + content: "\f0d4"; +} +.fa-google-plus:before { + content: "\f0d5"; +} +.fa-money:before { + content: "\f0d6"; +} +.fa-caret-down:before { + content: "\f0d7"; +} +.fa-caret-up:before { + content: "\f0d8"; +} +.fa-caret-left:before { + content: "\f0d9"; +} +.fa-caret-right:before { + content: "\f0da"; +} +.fa-columns:before { + content: "\f0db"; +} +.fa-unsorted:before, +.fa-sort:before { + content: "\f0dc"; +} +.fa-sort-down:before, +.fa-sort-desc:before { + content: "\f0dd"; +} +.fa-sort-up:before, +.fa-sort-asc:before { + content: "\f0de"; +} +.fa-envelope:before { + content: "\f0e0"; +} +.fa-linkedin:before { + content: "\f0e1"; +} +.fa-rotate-left:before, +.fa-undo:before { + content: "\f0e2"; +} +.fa-legal:before, +.fa-gavel:before { + content: "\f0e3"; +} +.fa-dashboard:before, +.fa-tachometer:before { + content: "\f0e4"; +} +.fa-comment-o:before { + content: "\f0e5"; +} +.fa-comments-o:before { + content: "\f0e6"; +} +.fa-flash:before, +.fa-bolt:before { + content: "\f0e7"; +} +.fa-sitemap:before { + content: "\f0e8"; +} +.fa-umbrella:before { + content: "\f0e9"; +} +.fa-paste:before, +.fa-clipboard:before { + content: "\f0ea"; +} +.fa-lightbulb-o:before { + content: "\f0eb"; +} +.fa-exchange:before { + content: "\f0ec"; +} +.fa-cloud-download:before { + content: "\f0ed"; +} +.fa-cloud-upload:before { + content: "\f0ee"; +} +.fa-user-md:before { + content: "\f0f0"; +} +.fa-stethoscope:before { + content: "\f0f1"; +} +.fa-suitcase:before { + content: "\f0f2"; +} +.fa-bell-o:before { + content: "\f0a2"; +} +.fa-coffee:before { + content: "\f0f4"; +} +.fa-cutlery:before { + content: "\f0f5"; +} +.fa-file-text-o:before { + content: "\f0f6"; +} +.fa-building-o:before { + content: "\f0f7"; +} +.fa-hospital-o:before { + content: "\f0f8"; +} +.fa-ambulance:before { + content: "\f0f9"; +} +.fa-medkit:before { + content: "\f0fa"; +} +.fa-fighter-jet:before { + content: "\f0fb"; +} +.fa-beer:before { + content: "\f0fc"; +} +.fa-h-square:before { + content: "\f0fd"; +} +.fa-plus-square:before { + content: "\f0fe"; +} +.fa-angle-double-left:before { + content: "\f100"; +} +.fa-angle-double-right:before { + content: "\f101"; +} +.fa-angle-double-up:before { + content: "\f102"; +} +.fa-angle-double-down:before { + content: "\f103"; +} +.fa-angle-left:before { + content: "\f104"; +} +.fa-angle-right:before { + content: "\f105"; +} +.fa-angle-up:before { + content: "\f106"; +} +.fa-angle-down:before { + content: "\f107"; +} +.fa-desktop:before { + content: "\f108"; +} +.fa-laptop:before { + content: "\f109"; +} +.fa-tablet:before { + content: "\f10a"; +} +.fa-mobile-phone:before, +.fa-mobile:before { + content: "\f10b"; +} +.fa-circle-o:before { + content: "\f10c"; +} +.fa-quote-left:before { + content: "\f10d"; +} +.fa-quote-right:before { + content: "\f10e"; +} +.fa-spinner:before { + content: "\f110"; +} +.fa-circle:before { + content: "\f111"; +} +.fa-mail-reply:before, +.fa-reply:before { + content: "\f112"; +} +.fa-github-alt:before { + content: "\f113"; +} +.fa-folder-o:before { + content: "\f114"; +} +.fa-folder-open-o:before { + content: "\f115"; +} +.fa-smile-o:before { + content: "\f118"; +} +.fa-frown-o:before { + content: "\f119"; +} +.fa-meh-o:before { + content: "\f11a"; +} +.fa-gamepad:before { + content: "\f11b"; +} +.fa-keyboard-o:before { + content: "\f11c"; +} +.fa-flag-o:before { + content: "\f11d"; +} +.fa-flag-checkered:before { + content: "\f11e"; +} +.fa-terminal:before { + content: "\f120"; +} +.fa-code:before { + content: "\f121"; +} +.fa-mail-reply-all:before, +.fa-reply-all:before { + content: "\f122"; +} +.fa-star-half-empty:before, +.fa-star-half-full:before, +.fa-star-half-o:before { + content: "\f123"; +} +.fa-location-arrow:before { + content: "\f124"; +} +.fa-crop:before { + content: "\f125"; +} +.fa-code-fork:before { + content: "\f126"; +} +.fa-unlink:before, +.fa-chain-broken:before { + content: "\f127"; +} +.fa-question:before { + content: "\f128"; +} +.fa-info:before { + content: "\f129"; +} +.fa-exclamation:before { + content: "\f12a"; +} +.fa-superscript:before { + content: "\f12b"; +} +.fa-subscript:before { + content: "\f12c"; +} +.fa-eraser:before { + content: "\f12d"; +} +.fa-puzzle-piece:before { + content: "\f12e"; +} +.fa-microphone:before { + content: "\f130"; +} +.fa-microphone-slash:before { + content: "\f131"; +} +.fa-shield:before { + content: "\f132"; +} +.fa-calendar-o:before { + content: "\f133"; +} +.fa-fire-extinguisher:before { + content: "\f134"; +} +.fa-rocket:before { + content: "\f135"; +} +.fa-maxcdn:before { + content: "\f136"; +} +.fa-chevron-circle-left:before { + content: "\f137"; +} +.fa-chevron-circle-right:before { + content: "\f138"; +} +.fa-chevron-circle-up:before { + content: "\f139"; +} +.fa-chevron-circle-down:before { + content: "\f13a"; +} +.fa-html5:before { + content: "\f13b"; +} +.fa-css3:before { + content: "\f13c"; +} +.fa-anchor:before { + content: "\f13d"; +} +.fa-unlock-alt:before { + content: "\f13e"; +} +.fa-bullseye:before { + content: "\f140"; +} +.fa-ellipsis-h:before { + content: "\f141"; +} +.fa-ellipsis-v:before { + content: "\f142"; +} +.fa-rss-square:before { + content: "\f143"; +} +.fa-play-circle:before { + content: "\f144"; +} +.fa-ticket:before { + content: "\f145"; +} +.fa-minus-square:before { + content: "\f146"; +} +.fa-minus-square-o:before { + content: "\f147"; +} +.fa-level-up:before { + content: "\f148"; +} +.fa-level-down:before { + content: "\f149"; +} +.fa-check-square:before { + content: "\f14a"; +} +.fa-pencil-square:before { + content: "\f14b"; +} +.fa-external-link-square:before { + content: "\f14c"; +} +.fa-share-square:before { + content: "\f14d"; +} +.fa-compass:before { + content: "\f14e"; +} +.fa-toggle-down:before, +.fa-caret-square-o-down:before { + content: "\f150"; +} +.fa-toggle-up:before, +.fa-caret-square-o-up:before { + content: "\f151"; +} +.fa-toggle-right:before, +.fa-caret-square-o-right:before { + content: "\f152"; +} +.fa-euro:before, +.fa-eur:before { + content: "\f153"; +} +.fa-gbp:before { + content: "\f154"; +} +.fa-dollar:before, +.fa-usd:before { + content: "\f155"; +} +.fa-rupee:before, +.fa-inr:before { + content: "\f156"; +} +.fa-cny:before, +.fa-rmb:before, +.fa-yen:before, +.fa-jpy:before { + content: "\f157"; +} +.fa-ruble:before, +.fa-rouble:before, +.fa-rub:before { + content: "\f158"; +} +.fa-won:before, +.fa-krw:before { + content: "\f159"; +} +.fa-bitcoin:before, +.fa-btc:before { + content: "\f15a"; +} +.fa-file:before { + content: "\f15b"; +} +.fa-file-text:before { + content: "\f15c"; +} +.fa-sort-alpha-asc:before { + content: "\f15d"; +} +.fa-sort-alpha-desc:before { + content: "\f15e"; +} +.fa-sort-amount-asc:before { + content: "\f160"; +} +.fa-sort-amount-desc:before { + content: "\f161"; +} +.fa-sort-numeric-asc:before { + content: "\f162"; +} +.fa-sort-numeric-desc:before { + content: "\f163"; +} +.fa-thumbs-up:before { + content: "\f164"; +} +.fa-thumbs-down:before { + content: "\f165"; +} +.fa-youtube-square:before { + content: "\f166"; +} +.fa-youtube:before { + content: "\f167"; +} +.fa-xing:before { + content: "\f168"; +} +.fa-xing-square:before { + content: "\f169"; +} +.fa-youtube-play:before { + content: "\f16a"; +} +.fa-dropbox:before { + content: "\f16b"; +} +.fa-stack-overflow:before { + content: "\f16c"; +} +.fa-instagram:before { + content: "\f16d"; +} +.fa-flickr:before { + content: "\f16e"; +} +.fa-adn:before { + content: "\f170"; +} +.fa-bitbucket:before { + content: "\f171"; +} +.fa-bitbucket-square:before { + content: "\f172"; +} +.fa-tumblr:before { + content: "\f173"; +} +.fa-tumblr-square:before { + content: "\f174"; +} +.fa-long-arrow-down:before { + content: "\f175"; +} +.fa-long-arrow-up:before { + content: "\f176"; +} +.fa-long-arrow-left:before { + content: "\f177"; +} +.fa-long-arrow-right:before { + content: "\f178"; +} +.fa-apple:before { + content: "\f179"; +} +.fa-windows:before { + content: "\f17a"; +} +.fa-android:before { + content: "\f17b"; +} +.fa-linux:before { + content: "\f17c"; +} +.fa-dribbble:before { + content: "\f17d"; +} +.fa-skype:before { + content: "\f17e"; +} +.fa-foursquare:before { + content: "\f180"; +} +.fa-trello:before { + content: "\f181"; +} +.fa-female:before { + content: "\f182"; +} +.fa-male:before { + content: "\f183"; +} +.fa-gittip:before, +.fa-gratipay:before { + content: "\f184"; +} +.fa-sun-o:before { + content: "\f185"; +} +.fa-moon-o:before { + content: "\f186"; +} +.fa-archive:before { + content: "\f187"; +} +.fa-bug:before { + content: "\f188"; +} +.fa-vk:before { + content: "\f189"; +} +.fa-weibo:before { + content: "\f18a"; +} +.fa-renren:before { + content: "\f18b"; +} +.fa-pagelines:before { + content: "\f18c"; +} +.fa-stack-exchange:before { + content: "\f18d"; +} +.fa-arrow-circle-o-right:before { + content: "\f18e"; +} +.fa-arrow-circle-o-left:before { + content: "\f190"; +} +.fa-toggle-left:before, +.fa-caret-square-o-left:before { + content: "\f191"; +} +.fa-dot-circle-o:before { + content: "\f192"; +} +.fa-wheelchair:before { + content: "\f193"; +} +.fa-vimeo-square:before { + content: "\f194"; +} +.fa-turkish-lira:before, +.fa-try:before { + content: "\f195"; +} +.fa-plus-square-o:before { + content: "\f196"; +} +.fa-space-shuttle:before { + content: "\f197"; +} +.fa-slack:before { + content: "\f198"; +} +.fa-envelope-square:before { + content: "\f199"; +} +.fa-wordpress:before { + content: "\f19a"; +} +.fa-openid:before { + content: "\f19b"; +} +.fa-institution:before, +.fa-bank:before, +.fa-university:before { + content: "\f19c"; +} +.fa-mortar-board:before, +.fa-graduation-cap:before { + content: "\f19d"; +} +.fa-yahoo:before { + content: "\f19e"; +} +.fa-google:before { + content: "\f1a0"; +} +.fa-reddit:before { + content: "\f1a1"; +} +.fa-reddit-square:before { + content: "\f1a2"; +} +.fa-stumbleupon-circle:before { + content: "\f1a3"; +} +.fa-stumbleupon:before { + content: "\f1a4"; +} +.fa-delicious:before { + content: "\f1a5"; +} +.fa-digg:before { + content: "\f1a6"; +} +.fa-pied-piper-pp:before { + content: "\f1a7"; +} +.fa-pied-piper-alt:before { + content: "\f1a8"; +} +.fa-drupal:before { + content: "\f1a9"; +} +.fa-joomla:before { + content: "\f1aa"; +} +.fa-language:before { + content: "\f1ab"; +} +.fa-fax:before { + content: "\f1ac"; +} +.fa-building:before { + content: "\f1ad"; +} +.fa-child:before { + content: "\f1ae"; +} +.fa-paw:before { + content: "\f1b0"; +} +.fa-spoon:before { + content: "\f1b1"; +} +.fa-cube:before { + content: "\f1b2"; +} +.fa-cubes:before { + content: "\f1b3"; +} +.fa-behance:before { + content: "\f1b4"; +} +.fa-behance-square:before { + content: "\f1b5"; +} +.fa-steam:before { + content: "\f1b6"; +} +.fa-steam-square:before { + content: "\f1b7"; +} +.fa-recycle:before { + content: "\f1b8"; +} +.fa-automobile:before, +.fa-car:before { + content: "\f1b9"; +} +.fa-cab:before, +.fa-taxi:before { + content: "\f1ba"; +} +.fa-tree:before { + content: "\f1bb"; +} +.fa-spotify:before { + content: "\f1bc"; +} +.fa-deviantart:before { + content: "\f1bd"; +} +.fa-soundcloud:before { + content: "\f1be"; +} +.fa-database:before { + content: "\f1c0"; +} +.fa-file-pdf-o:before { + content: "\f1c1"; +} +.fa-file-word-o:before { + content: "\f1c2"; +} +.fa-file-excel-o:before { + content: "\f1c3"; +} +.fa-file-powerpoint-o:before { + content: "\f1c4"; +} +.fa-file-photo-o:before, +.fa-file-picture-o:before, +.fa-file-image-o:before { + content: "\f1c5"; +} +.fa-file-zip-o:before, +.fa-file-archive-o:before { + content: "\f1c6"; +} +.fa-file-sound-o:before, +.fa-file-audio-o:before { + content: "\f1c7"; +} +.fa-file-movie-o:before, +.fa-file-video-o:before { + content: "\f1c8"; +} +.fa-file-code-o:before { + content: "\f1c9"; +} +.fa-vine:before { + content: "\f1ca"; +} +.fa-codepen:before { + content: "\f1cb"; +} +.fa-jsfiddle:before { + content: "\f1cc"; +} +.fa-life-bouy:before, +.fa-life-buoy:before, +.fa-life-saver:before, +.fa-support:before, +.fa-life-ring:before { + content: "\f1cd"; +} +.fa-circle-o-notch:before { + content: "\f1ce"; +} +.fa-ra:before, +.fa-resistance:before, +.fa-rebel:before { + content: "\f1d0"; +} +.fa-ge:before, +.fa-empire:before { + content: "\f1d1"; +} +.fa-git-square:before { + content: "\f1d2"; +} +.fa-git:before { + content: "\f1d3"; +} +.fa-y-combinator-square:before, +.fa-yc-square:before, +.fa-hacker-news:before { + content: "\f1d4"; +} +.fa-tencent-weibo:before { + content: "\f1d5"; +} +.fa-qq:before { + content: "\f1d6"; +} +.fa-wechat:before, +.fa-weixin:before { + content: "\f1d7"; +} +.fa-send:before, +.fa-paper-plane:before { + content: "\f1d8"; +} +.fa-send-o:before, +.fa-paper-plane-o:before { + content: "\f1d9"; +} +.fa-history:before { + content: "\f1da"; +} +.fa-circle-thin:before { + content: "\f1db"; +} +.fa-header:before { + content: "\f1dc"; +} +.fa-paragraph:before { + content: "\f1dd"; +} +.fa-sliders:before { + content: "\f1de"; +} +.fa-share-alt:before { + content: "\f1e0"; +} +.fa-share-alt-square:before { + content: "\f1e1"; +} +.fa-bomb:before { + content: "\f1e2"; +} +.fa-soccer-ball-o:before, +.fa-futbol-o:before { + content: "\f1e3"; +} +.fa-tty:before { + content: "\f1e4"; +} +.fa-binoculars:before { + content: "\f1e5"; +} +.fa-plug:before { + content: "\f1e6"; +} +.fa-slideshare:before { + content: "\f1e7"; +} +.fa-twitch:before { + content: "\f1e8"; +} +.fa-yelp:before { + content: "\f1e9"; +} +.fa-newspaper-o:before { + content: "\f1ea"; +} +.fa-wifi:before { + content: "\f1eb"; +} +.fa-calculator:before { + content: "\f1ec"; +} +.fa-paypal:before { + content: "\f1ed"; +} +.fa-google-wallet:before { + content: "\f1ee"; +} +.fa-cc-visa:before { + content: "\f1f0"; +} +.fa-cc-mastercard:before { + content: "\f1f1"; +} +.fa-cc-discover:before { + content: "\f1f2"; +} +.fa-cc-amex:before { + content: "\f1f3"; +} +.fa-cc-paypal:before { + content: "\f1f4"; +} +.fa-cc-stripe:before { + content: "\f1f5"; +} +.fa-bell-slash:before { + content: "\f1f6"; +} +.fa-bell-slash-o:before { + content: "\f1f7"; +} +.fa-trash:before { + content: "\f1f8"; +} +.fa-copyright:before { + content: "\f1f9"; +} +.fa-at:before { + content: "\f1fa"; +} +.fa-eyedropper:before { + content: "\f1fb"; +} +.fa-paint-brush:before { + content: "\f1fc"; +} +.fa-birthday-cake:before { + content: "\f1fd"; +} +.fa-area-chart:before { + content: "\f1fe"; +} +.fa-pie-chart:before { + content: "\f200"; +} +.fa-line-chart:before { + content: "\f201"; +} +.fa-lastfm:before { + content: "\f202"; +} +.fa-lastfm-square:before { + content: "\f203"; +} +.fa-toggle-off:before { + content: "\f204"; +} +.fa-toggle-on:before { + content: "\f205"; +} +.fa-bicycle:before { + content: "\f206"; +} +.fa-bus:before { + content: "\f207"; +} +.fa-ioxhost:before { + content: "\f208"; +} +.fa-angellist:before { + content: "\f209"; +} +.fa-cc:before { + content: "\f20a"; +} +.fa-shekel:before, +.fa-sheqel:before, +.fa-ils:before { + content: "\f20b"; +} +.fa-meanpath:before { + content: "\f20c"; +} +.fa-buysellads:before { + content: "\f20d"; +} +.fa-connectdevelop:before { + content: "\f20e"; +} +.fa-dashcube:before { + content: "\f210"; +} +.fa-forumbee:before { + content: "\f211"; +} +.fa-leanpub:before { + content: "\f212"; +} +.fa-sellsy:before { + content: "\f213"; +} +.fa-shirtsinbulk:before { + content: "\f214"; +} +.fa-simplybuilt:before { + content: "\f215"; +} +.fa-skyatlas:before { + content: "\f216"; +} +.fa-cart-plus:before { + content: "\f217"; +} +.fa-cart-arrow-down:before { + content: "\f218"; +} +.fa-diamond:before { + content: "\f219"; +} +.fa-ship:before { + content: "\f21a"; +} +.fa-user-secret:before { + content: "\f21b"; +} +.fa-motorcycle:before { + content: "\f21c"; +} +.fa-street-view:before { + content: "\f21d"; +} +.fa-heartbeat:before { + content: "\f21e"; +} +.fa-venus:before { + content: "\f221"; +} +.fa-mars:before { + content: "\f222"; +} +.fa-mercury:before { + content: "\f223"; +} +.fa-intersex:before, +.fa-transgender:before { + content: "\f224"; +} +.fa-transgender-alt:before { + content: "\f225"; +} +.fa-venus-double:before { + content: "\f226"; +} +.fa-mars-double:before { + content: "\f227"; +} +.fa-venus-mars:before { + content: "\f228"; +} +.fa-mars-stroke:before { + content: "\f229"; +} +.fa-mars-stroke-v:before { + content: "\f22a"; +} +.fa-mars-stroke-h:before { + content: "\f22b"; +} +.fa-neuter:before { + content: "\f22c"; +} +.fa-genderless:before { + content: "\f22d"; +} +.fa-facebook-official:before { + content: "\f230"; +} +.fa-pinterest-p:before { + content: "\f231"; +} +.fa-whatsapp:before { + content: "\f232"; +} +.fa-server:before { + content: "\f233"; +} +.fa-user-plus:before { + content: "\f234"; +} +.fa-user-times:before { + content: "\f235"; +} +.fa-hotel:before, +.fa-bed:before { + content: "\f236"; +} +.fa-viacoin:before { + content: "\f237"; +} +.fa-train:before { + content: "\f238"; +} +.fa-subway:before { + content: "\f239"; +} +.fa-medium:before { + content: "\f23a"; +} +.fa-yc:before, +.fa-y-combinator:before { + content: "\f23b"; +} +.fa-optin-monster:before { + content: "\f23c"; +} +.fa-opencart:before { + content: "\f23d"; +} +.fa-expeditedssl:before { + content: "\f23e"; +} +.fa-battery-4:before, +.fa-battery:before, +.fa-battery-full:before { + content: "\f240"; +} +.fa-battery-3:before, +.fa-battery-three-quarters:before { + content: "\f241"; +} +.fa-battery-2:before, +.fa-battery-half:before { + content: "\f242"; +} +.fa-battery-1:before, +.fa-battery-quarter:before { + content: "\f243"; +} +.fa-battery-0:before, +.fa-battery-empty:before { + content: "\f244"; +} +.fa-mouse-pointer:before { + content: "\f245"; +} +.fa-i-cursor:before { + content: "\f246"; +} +.fa-object-group:before { + content: "\f247"; +} +.fa-object-ungroup:before { + content: "\f248"; +} +.fa-sticky-note:before { + content: "\f249"; +} +.fa-sticky-note-o:before { + content: "\f24a"; +} +.fa-cc-jcb:before { + content: "\f24b"; +} +.fa-cc-diners-club:before { + content: "\f24c"; +} +.fa-clone:before { + content: "\f24d"; +} +.fa-balance-scale:before { + content: "\f24e"; +} +.fa-hourglass-o:before { + content: "\f250"; +} +.fa-hourglass-1:before, +.fa-hourglass-start:before { + content: "\f251"; +} +.fa-hourglass-2:before, +.fa-hourglass-half:before { + content: "\f252"; +} +.fa-hourglass-3:before, +.fa-hourglass-end:before { + content: "\f253"; +} +.fa-hourglass:before { + content: "\f254"; +} +.fa-hand-grab-o:before, +.fa-hand-rock-o:before { + content: "\f255"; +} +.fa-hand-stop-o:before, +.fa-hand-paper-o:before { + content: "\f256"; +} +.fa-hand-scissors-o:before { + content: "\f257"; +} +.fa-hand-lizard-o:before { + content: "\f258"; +} +.fa-hand-spock-o:before { + content: "\f259"; +} +.fa-hand-pointer-o:before { + content: "\f25a"; +} +.fa-hand-peace-o:before { + content: "\f25b"; +} +.fa-trademark:before { + content: "\f25c"; +} +.fa-registered:before { + content: "\f25d"; +} +.fa-creative-commons:before { + content: "\f25e"; +} +.fa-gg:before { + content: "\f260"; +} +.fa-gg-circle:before { + content: "\f261"; +} +.fa-tripadvisor:before { + content: "\f262"; +} +.fa-odnoklassniki:before { + content: "\f263"; +} +.fa-odnoklassniki-square:before { + content: "\f264"; +} +.fa-get-pocket:before { + content: "\f265"; +} +.fa-wikipedia-w:before { + content: "\f266"; +} +.fa-safari:before { + content: "\f267"; +} +.fa-chrome:before { + content: "\f268"; +} +.fa-firefox:before { + content: "\f269"; +} +.fa-opera:before { + content: "\f26a"; +} +.fa-internet-explorer:before { + content: "\f26b"; +} +.fa-tv:before, +.fa-television:before { + content: "\f26c"; +} +.fa-contao:before { + content: "\f26d"; +} +.fa-500px:before { + content: "\f26e"; +} +.fa-amazon:before { + content: "\f270"; +} +.fa-calendar-plus-o:before { + content: "\f271"; +} +.fa-calendar-minus-o:before { + content: "\f272"; +} +.fa-calendar-times-o:before { + content: "\f273"; +} +.fa-calendar-check-o:before { + content: "\f274"; +} +.fa-industry:before { + content: "\f275"; +} +.fa-map-pin:before { + content: "\f276"; +} +.fa-map-signs:before { + content: "\f277"; +} +.fa-map-o:before { + content: "\f278"; +} +.fa-map:before { + content: "\f279"; +} +.fa-commenting:before { + content: "\f27a"; +} +.fa-commenting-o:before { + content: "\f27b"; +} +.fa-houzz:before { + content: "\f27c"; +} +.fa-vimeo:before { + content: "\f27d"; +} +.fa-black-tie:before { + content: "\f27e"; +} +.fa-fonticons:before { + content: "\f280"; +} +.fa-reddit-alien:before { + content: "\f281"; +} +.fa-edge:before { + content: "\f282"; +} +.fa-credit-card-alt:before { + content: "\f283"; +} +.fa-codiepie:before { + content: "\f284"; +} +.fa-modx:before { + content: "\f285"; +} +.fa-fort-awesome:before { + content: "\f286"; +} +.fa-usb:before { + content: "\f287"; +} +.fa-product-hunt:before { + content: "\f288"; +} +.fa-mixcloud:before { + content: "\f289"; +} +.fa-scribd:before { + content: "\f28a"; +} +.fa-pause-circle:before { + content: "\f28b"; +} +.fa-pause-circle-o:before { + content: "\f28c"; +} +.fa-stop-circle:before { + content: "\f28d"; +} +.fa-stop-circle-o:before { + content: "\f28e"; +} +.fa-shopping-bag:before { + content: "\f290"; +} +.fa-shopping-basket:before { + content: "\f291"; +} +.fa-hashtag:before { + content: "\f292"; +} +.fa-bluetooth:before { + content: "\f293"; +} +.fa-bluetooth-b:before { + content: "\f294"; +} +.fa-percent:before { + content: "\f295"; +} +.fa-gitlab:before { + content: "\f296"; +} +.fa-wpbeginner:before { + content: "\f297"; +} +.fa-wpforms:before { + content: "\f298"; +} +.fa-envira:before { + content: "\f299"; +} +.fa-universal-access:before { + content: "\f29a"; +} +.fa-wheelchair-alt:before { + content: "\f29b"; +} +.fa-question-circle-o:before { + content: "\f29c"; +} +.fa-blind:before { + content: "\f29d"; +} +.fa-audio-description:before { + content: "\f29e"; +} +.fa-volume-control-phone:before { + content: "\f2a0"; +} +.fa-braille:before { + content: "\f2a1"; +} +.fa-assistive-listening-systems:before { + content: "\f2a2"; +} +.fa-asl-interpreting:before, +.fa-american-sign-language-interpreting:before { + content: "\f2a3"; +} +.fa-deafness:before, +.fa-hard-of-hearing:before, +.fa-deaf:before { + content: "\f2a4"; +} +.fa-glide:before { + content: "\f2a5"; +} +.fa-glide-g:before { + content: "\f2a6"; +} +.fa-signing:before, +.fa-sign-language:before { + content: "\f2a7"; +} +.fa-low-vision:before { + content: "\f2a8"; +} +.fa-viadeo:before { + content: "\f2a9"; +} +.fa-viadeo-square:before { + content: "\f2aa"; +} +.fa-snapchat:before { + content: "\f2ab"; +} +.fa-snapchat-ghost:before { + content: "\f2ac"; +} +.fa-snapchat-square:before { + content: "\f2ad"; +} +.fa-pied-piper:before { + content: "\f2ae"; +} +.fa-first-order:before { + content: "\f2b0"; +} +.fa-yoast:before { + content: "\f2b1"; +} +.fa-themeisle:before { + content: "\f2b2"; +} +.fa-google-plus-circle:before, +.fa-google-plus-official:before { + content: "\f2b3"; +} +.fa-fa:before, +.fa-font-awesome:before { + content: "\f2b4"; +} +.fa-handshake-o:before { + content: "\f2b5"; +} +.fa-envelope-open:before { + content: "\f2b6"; +} +.fa-envelope-open-o:before { + content: "\f2b7"; +} +.fa-linode:before { + content: "\f2b8"; +} +.fa-address-book:before { + content: "\f2b9"; +} +.fa-address-book-o:before { + content: "\f2ba"; +} +.fa-vcard:before, +.fa-address-card:before { + content: "\f2bb"; +} +.fa-vcard-o:before, +.fa-address-card-o:before { + content: "\f2bc"; +} +.fa-user-circle:before { + content: "\f2bd"; +} +.fa-user-circle-o:before { + content: "\f2be"; +} +.fa-user-o:before { + content: "\f2c0"; +} +.fa-id-badge:before { + content: "\f2c1"; +} +.fa-drivers-license:before, +.fa-id-card:before { + content: "\f2c2"; +} +.fa-drivers-license-o:before, +.fa-id-card-o:before { + content: "\f2c3"; +} +.fa-quora:before { + content: "\f2c4"; +} +.fa-free-code-camp:before { + content: "\f2c5"; +} +.fa-telegram:before { + content: "\f2c6"; +} +.fa-thermometer-4:before, +.fa-thermometer:before, +.fa-thermometer-full:before { + content: "\f2c7"; +} +.fa-thermometer-3:before, +.fa-thermometer-three-quarters:before { + content: "\f2c8"; +} +.fa-thermometer-2:before, +.fa-thermometer-half:before { + content: "\f2c9"; +} +.fa-thermometer-1:before, +.fa-thermometer-quarter:before { + content: "\f2ca"; +} +.fa-thermometer-0:before, +.fa-thermometer-empty:before { + content: "\f2cb"; +} +.fa-shower:before { + content: "\f2cc"; +} +.fa-bathtub:before, +.fa-s15:before, +.fa-bath:before { + content: "\f2cd"; +} +.fa-podcast:before { + content: "\f2ce"; +} +.fa-window-maximize:before { + content: "\f2d0"; +} +.fa-window-minimize:before { + content: "\f2d1"; +} +.fa-window-restore:before { + content: "\f2d2"; +} +.fa-times-rectangle:before, +.fa-window-close:before { + content: "\f2d3"; +} +.fa-times-rectangle-o:before, +.fa-window-close-o:before { + content: "\f2d4"; +} +.fa-bandcamp:before { + content: "\f2d5"; +} +.fa-grav:before { + content: "\f2d6"; +} +.fa-etsy:before { + content: "\f2d7"; +} +.fa-imdb:before { + content: "\f2d8"; +} +.fa-ravelry:before { + content: "\f2d9"; +} +.fa-eercast:before { + content: "\f2da"; +} +.fa-microchip:before { + content: "\f2db"; +} +.fa-snowflake-o:before { + content: "\f2dc"; +} +.fa-superpowers:before { + content: "\f2dd"; +} +.fa-wpexplorer:before { + content: "\f2de"; +} +.fa-meetup:before { + content: "\f2e0"; +} +.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; +} diff --git a/admin-core/src/main/resources/static/plugins/font-awesome/css/font-awesome.min.css b/admin-core/src/main/resources/static/plugins/font-awesome/css/font-awesome.min.css new file mode 100644 index 0000000000000000000000000000000000000000..540440ce89f2a408aa699b65100e18f15e0f09ca --- /dev/null +++ b/admin-core/src/main/resources/static/plugins/font-awesome/css/font-awesome.min.css @@ -0,0 +1,4 @@ +/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.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} diff --git a/admin-core/src/main/resources/static/plugins/font-awesome/fonts/FontAwesome.otf b/admin-core/src/main/resources/static/plugins/font-awesome/fonts/FontAwesome.otf new file mode 100644 index 0000000000000000000000000000000000000000..401ec0f36e4f73b8efa40bd6f604fe80d286db70 Binary files /dev/null and b/admin-core/src/main/resources/static/plugins/font-awesome/fonts/FontAwesome.otf differ diff --git a/admin-core/src/main/resources/static/plugins/font-awesome/fonts/fontawesome-webfont.eot b/admin-core/src/main/resources/static/plugins/font-awesome/fonts/fontawesome-webfont.eot new file mode 100644 index 0000000000000000000000000000000000000000..e9f60ca953f93e35eab4108bd414bc02ddcf3928 Binary files /dev/null and b/admin-core/src/main/resources/static/plugins/font-awesome/fonts/fontawesome-webfont.eot differ diff --git a/admin-core/src/main/resources/static/plugins/font-awesome/fonts/fontawesome-webfont.svg b/admin-core/src/main/resources/static/plugins/font-awesome/fonts/fontawesome-webfont.svg new file mode 100644 index 0000000000000000000000000000000000000000..855c845e538b65548118279537a04eab2ec6ef0d --- /dev/null +++ b/admin-core/src/main/resources/static/plugins/font-awesome/fonts/fontawesome-webfont.svg @@ -0,0 +1,2671 @@ + + + + +Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 + By ,,, +Copyright Dave Gandy 2016. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/admin-core/src/main/resources/static/plugins/font-awesome/fonts/fontawesome-webfont.ttf b/admin-core/src/main/resources/static/plugins/font-awesome/fonts/fontawesome-webfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..35acda2fa1196aad98c2adf4378a7611dd713aa3 Binary files /dev/null and b/admin-core/src/main/resources/static/plugins/font-awesome/fonts/fontawesome-webfont.ttf differ diff --git a/admin-core/src/main/resources/static/plugins/font-awesome/fonts/fontawesome-webfont.woff b/admin-core/src/main/resources/static/plugins/font-awesome/fonts/fontawesome-webfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..400014a4b06eee3d0c0d54402a47ab2601b2862b Binary files /dev/null and b/admin-core/src/main/resources/static/plugins/font-awesome/fonts/fontawesome-webfont.woff differ diff --git a/admin-core/src/main/resources/static/plugins/font-awesome/fonts/fontawesome-webfont.woff2 b/admin-core/src/main/resources/static/plugins/font-awesome/fonts/fontawesome-webfont.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..4d13fc60404b91e398a37200c4a77b645cfd9586 Binary files /dev/null and b/admin-core/src/main/resources/static/plugins/font-awesome/fonts/fontawesome-webfont.woff2 differ diff --git a/admin-core/src/main/resources/static/plugins/frame/js/fsTab.js b/admin-core/src/main/resources/static/plugins/frame/js/fsTab.js index 6b832a57dbeba5c9588b7908cc0b51b7d4c082ad..dbe994243d003e90fe315c7023ec1262225aa37e 100644 --- a/admin-core/src/main/resources/static/plugins/frame/js/fsTab.js +++ b/admin-core/src/main/resources/static/plugins/frame/js/fsTab.js @@ -6,120 +6,120 @@ * @License:MIT */ layui.define(['element'], function(exports){ - var element = layui.element, - FsTab = function (){ - this.config = { - topMenuFilter:"fsTopMenu",//头部菜单 - leftMenuFilter:"fsLeftMenu",//左边菜单 - tabFilter:"fsTab"//导航栏 - } - }; - - - - FsTab.prototype.render = function(options){ - var thisTab = this; - $.extend(true, thisTab.config, options); - - thisTab.bindDeleteFilter(); - - thisTab.bindTabFilter(); - - - //绑定左边菜单点击。 - element.on('nav('+thisTab.config.leftMenuFilter+')', function(elem){ - elem = $(elem).parent(); - var layId = $(elem).attr("lay-id"); - if($.isEmpty(layId)){ - layId = $.uuid(); - $(elem).attr("lay-id",layId); - var dom =$(elem).find("a"); - var title = $(elem).find("a").html(); - var dataUrl = dom.attr("dataUrl"); - if(!$.isEmpty(dataUrl)){ - thisTab.add(title,dom.attr("dataUrl"),layId); - } - } - thisTab.tabChange(layId); - $('body').removeClass('site-mobile'); - }); - - - }; - - /** - * 切换tab - */ - FsTab.prototype.tabChange = function(layId) { - element.tabChange(this.config.tabFilter, layId); - } - - - /** - * 新增 - */ - FsTab.prototype.add = function(title,dataUrl,layId) { - - element.tabAdd(this.config.tabFilter, { - title: title - ,content: '' //支持传入html - ,id: layId - }); - }; - - - /** - * 删除监听 - */ - FsTab.prototype.bindDeleteFilter = function(){ - element.on('tabDelete('+this.config.tabFilter+')', function(data){ - var layId = $(this).parentsUntil().attr("lay-id"); - $('.fsMenu .layui-nav-child>dd[lay-id="'+ layId +'"],.fsMenu>li[lay-id="'+ layId +'"]').removeAttr("lay-id"); - }); - } - - /** - * 监听tab切换,处理菜单选中 - */ - FsTab.prototype.bindTabFilter = function(){ - var thisTab = this; - element.on('tab('+this.config.tabFilter+')', function(data){ - var layId = $(this).attr("lay-id"); - - thisTab.menuSelectCss(layId); - - }); - } - - /** - * 菜单选中样式 - */ - FsTab.prototype.menuSelectCss = function(layId){ - if(!$.isEmpty(layId)){ - $('.fsMenu .layui-this').removeClass("layui-this");//清除样式 - - var dom =$('.fsMenu .layui-nav-child>dd[lay-id="'+ layId +'"],.fsMenu>li[lay-id="'+ layId +'"]'); - dom.addClass("layui-this");//追加样式 - - //处理头部菜单 - if(dom.length==1){ - var dataPid = null; - var tagName = dom.get(0).tagName; - if(tagName == "LI"){ - dataPid = dom.attr("dataPid"); - }else if(tagName == "DD"){ - dataPid = dom.parentsUntil('li').parent().attr("dataPid"); - } - if(!$.isEmpty(dataPid)){ - $('#fsTopMenu li[dataPid="'+ dataPid +'"]').click(); - } - } - } - } - - - var fsTab = new FsTab(); - //绑定按钮 - exports("fsTab",fsTab); - + var element = layui.element, + FsTab = function (){ + this.config = { + topMenuFilter:"fsTopMenu",//头部菜单 + leftMenuFilter:"fsLeftMenu",//左边菜单 + tabFilter:"fsTab"//导航栏 + } + }; + + + + FsTab.prototype.render = function(options){ + var thisTab = this; + $.extend(true, thisTab.config, options); + + thisTab.bindDeleteFilter(); + + thisTab.bindTabFilter(); + + + //绑定左边菜单点击。 + element.on('nav('+thisTab.config.leftMenuFilter+')', function(elem){ + elem = $(elem).parent(); + var layId = $(elem).attr("lay-id"); + if($.isEmpty(layId)){ + layId = $.uuid(); + $(elem).attr("lay-id",layId); + var dom =$(elem).find("a"); + var title = $(elem).find("a").html(); + var dataUrl = dom.attr("dataUrl"); + if(!$.isEmpty(dataUrl)){ + thisTab.add(title,dom.attr("dataUrl"),layId); + } + } + thisTab.tabChange(layId); + $('body').removeClass('site-mobile'); + }); + + + }; + + /** + * 切换tab + */ + FsTab.prototype.tabChange = function(layId) { + element.tabChange(this.config.tabFilter, layId); + } + + + /** + * 新增 + */ + FsTab.prototype.add = function(title,dataUrl,layId) { + + element.tabAdd(this.config.tabFilter, { + title: title + ,content: '' //支持传入html + ,id: layId + }); + }; + + + /** + * 删除监听 + */ + FsTab.prototype.bindDeleteFilter = function(){ + element.on('tabDelete('+this.config.tabFilter+')', function(data){ + var layId = $(this).parentsUntil().attr("lay-id"); + $('.layui-nav-child').find('dd[lay-id="'+ layId +'"]').removeAttr("lay-id"); + }); + } + + /** + * 监听tab切换,处理菜单选中 + */ + FsTab.prototype.bindTabFilter = function(){ + var thisTab = this; + element.on('tab('+this.config.tabFilter+')', function(data){ + var layId = $(this).attr("lay-id"); + + thisTab.menuSelectCss(layId); + + }); + } + + /** + * 菜单选中样式 + */ + FsTab.prototype.menuSelectCss = function(layId){ + if(!$.isEmpty(layId)){ + $('.fsMenu .layui-this').removeClass("layui-this");//清除样式 + + var dom =$('.fsMenu .layui-nav-child>dd[lay-id="'+ layId +'"],.fsMenu>li[lay-id="'+ layId +'"]'); + dom.addClass("layui-this");//追加样式 + + //处理头部菜单 + if(dom.length==1){ + var dataPid = null; + var tagName = dom.get(0).tagName; + if(tagName == "LI"){ + dataPid = dom.attr("dataPid"); + }else if(tagName == "DD"){ + dataPid = dom.parentsUntil('li').parent().attr("dataPid"); + } + if(!$.isEmpty(dataPid)){ + $('#fsTopMenu li[dataPid="'+ dataPid +'"]').click(); + } + } + } + } + + + var fsTab = new FsTab(); + //绑定按钮 + exports("fsTab",fsTab); + }); \ No newline at end of file diff --git a/admin-core/src/main/resources/static/plugins/frame/js/main.js b/admin-core/src/main/resources/static/plugins/frame/js/main.js index 62354f94180e09ed3bed8b05a29cc7fc141bfc0b..be35a390623fa965f16d825cb8ab11ca81941f5e 100644 --- a/admin-core/src/main/resources/static/plugins/frame/js/main.js +++ b/admin-core/src/main/resources/static/plugins/frame/js/main.js @@ -40,6 +40,11 @@ layui.use(['layer','fsTab',"element","form"], function(){ } }); }); + $("#changePassword").click(function(){ + var id = $(this).find("a").attr("id"); + var url = "/admin/user/changePassword.do?id="+id; + Common.openMinDlg(url,"用户管理>更改密码"); + }) } function hashChanged(){ diff --git a/admin-core/src/main/resources/static/plugins/layui/css/layui.css b/admin-core/src/main/resources/static/plugins/layui/css/layui.css index f297bf6e96f8a0326f8c2807424dd22ce3882890..850fa1bbba2302695152590060d213b73c8537a3 100644 --- a/admin-core/src/main/resources/static/plugins/layui/css/layui.css +++ b/admin-core/src/main/resources/static/plugins/layui/css/layui.css @@ -1,2 +1,2 @@ /** layui-v2.4.5 MIT License By https://www.layui.com */ - .layui-inline,img{display:inline-block;vertical-align:middle}h1,h2,h3,h4,h5,h6{font-weight:400}.layui-edge,.layui-header,.layui-inline,.layui-main{position:relative}.layui-elip,.layui-form-checkbox span,.layui-form-pane .layui-form-label{text-overflow:ellipsis;white-space:nowrap}.layui-btn,.layui-edge,.layui-inline,img{vertical-align:middle}.layui-btn,.layui-disabled,.layui-icon,.layui-unselect{-webkit-user-select:none;-ms-user-select:none;-moz-user-select:none}blockquote,body,button,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,input,li,ol,p,pre,td,textarea,th,ul{margin:0;padding:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}a:active,a:hover{outline:0}img{border:none}li{list-style:none}table{border-collapse:collapse;border-spacing:0}h4,h5,h6{font-size:100%}button,input,optgroup,option,select,textarea{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;outline:0}pre{white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}body{line-height:24px;font:14px Helvetica Neue,Helvetica,PingFang SC,Tahoma,Arial,sans-serif}hr{height:1px;margin:10px 0;border:0;clear:both}a{color:#333;text-decoration:none}a:hover{color:#777}a cite{font-style:normal;*cursor:pointer}.layui-border-box,.layui-border-box *{box-sizing:border-box}.layui-box,.layui-box *{box-sizing:content-box}.layui-clear{clear:both;*zoom:1}.layui-clear:after{content:'\20';clear:both;*zoom:1;display:block;height:0}.layui-inline{*display:inline;*zoom:1}.layui-edge{display:inline-block;width:0;height:0;border-width:6px;border-style:dashed;border-color:transparent;overflow:hidden}.layui-edge-top{top:-4px;border-bottom-color:#999;border-bottom-style:solid}.layui-edge-right{border-left-color:#999;border-left-style:solid}.layui-edge-bottom{top:2px;border-top-color:#999;border-top-style:solid}.layui-edge-left{border-right-color:#999;border-right-style:solid}.layui-elip{overflow:hidden}.layui-disabled,.layui-disabled:hover{color:#d2d2d2!important;cursor:not-allowed!important}.layui-circle{border-radius:100%}.layui-show{display:block!important}.layui-hide{display:none!important}@font-face{font-family:layui-icon;src:url(../font/iconfont.eot?v=240);src:url(../font/iconfont.eot?v=240#iefix) format('embedded-opentype'),url(../font/iconfont.svg?v=240#iconfont) format('svg'),url(../font/iconfont.woff?v=240) format('woff'),url(../font/iconfont.ttf?v=240) format('truetype')}.layui-icon{font-family:layui-icon!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.layui-icon-reply-fill:before{content:"\e611"}.layui-icon-set-fill:before{content:"\e614"}.layui-icon-menu-fill:before{content:"\e60f"}.layui-icon-search:before{content:"\e615"}.layui-icon-share:before{content:"\e641"}.layui-icon-set-sm:before{content:"\e620"}.layui-icon-engine:before{content:"\e628"}.layui-icon-close:before{content:"\1006"}.layui-icon-close-fill:before{content:"\1007"}.layui-icon-chart-screen:before{content:"\e629"}.layui-icon-star:before{content:"\e600"}.layui-icon-circle-dot:before{content:"\e617"}.layui-icon-chat:before{content:"\e606"}.layui-icon-release:before{content:"\e609"}.layui-icon-list:before{content:"\e60a"}.layui-icon-chart:before{content:"\e62c"}.layui-icon-ok-circle:before{content:"\1005"}.layui-icon-layim-theme:before{content:"\e61b"}.layui-icon-table:before{content:"\e62d"}.layui-icon-right:before{content:"\e602"}.layui-icon-left:before{content:"\e603"}.layui-icon-cart-simple:before{content:"\e698"}.layui-icon-face-cry:before{content:"\e69c"}.layui-icon-face-smile:before{content:"\e6af"}.layui-icon-survey:before{content:"\e6b2"}.layui-icon-tree:before{content:"\e62e"}.layui-icon-upload-circle:before{content:"\e62f"}.layui-icon-add-circle:before{content:"\e61f"}.layui-icon-download-circle:before{content:"\e601"}.layui-icon-templeate-1:before{content:"\e630"}.layui-icon-util:before{content:"\e631"}.layui-icon-face-surprised:before{content:"\e664"}.layui-icon-edit:before{content:"\e642"}.layui-icon-speaker:before{content:"\e645"}.layui-icon-down:before{content:"\e61a"}.layui-icon-file:before{content:"\e621"}.layui-icon-layouts:before{content:"\e632"}.layui-icon-rate-half:before{content:"\e6c9"}.layui-icon-add-circle-fine:before{content:"\e608"}.layui-icon-prev-circle:before{content:"\e633"}.layui-icon-read:before{content:"\e705"}.layui-icon-404:before{content:"\e61c"}.layui-icon-carousel:before{content:"\e634"}.layui-icon-help:before{content:"\e607"}.layui-icon-code-circle:before{content:"\e635"}.layui-icon-water:before{content:"\e636"}.layui-icon-username:before{content:"\e66f"}.layui-icon-find-fill:before{content:"\e670"}.layui-icon-about:before{content:"\e60b"}.layui-icon-location:before{content:"\e715"}.layui-icon-up:before{content:"\e619"}.layui-icon-pause:before{content:"\e651"}.layui-icon-date:before{content:"\e637"}.layui-icon-layim-uploadfile:before{content:"\e61d"}.layui-icon-delete:before{content:"\e640"}.layui-icon-play:before{content:"\e652"}.layui-icon-top:before{content:"\e604"}.layui-icon-friends:before{content:"\e612"}.layui-icon-refresh-3:before{content:"\e9aa"}.layui-icon-ok:before{content:"\e605"}.layui-icon-layer:before{content:"\e638"}.layui-icon-face-smile-fine:before{content:"\e60c"}.layui-icon-dollar:before{content:"\e659"}.layui-icon-group:before{content:"\e613"}.layui-icon-layim-download:before{content:"\e61e"}.layui-icon-picture-fine:before{content:"\e60d"}.layui-icon-link:before{content:"\e64c"}.layui-icon-diamond:before{content:"\e735"}.layui-icon-log:before{content:"\e60e"}.layui-icon-rate-solid:before{content:"\e67a"}.layui-icon-fonts-del:before{content:"\e64f"}.layui-icon-unlink:before{content:"\e64d"}.layui-icon-fonts-clear:before{content:"\e639"}.layui-icon-triangle-r:before{content:"\e623"}.layui-icon-circle:before{content:"\e63f"}.layui-icon-radio:before{content:"\e643"}.layui-icon-align-center:before{content:"\e647"}.layui-icon-align-right:before{content:"\e648"}.layui-icon-align-left:before{content:"\e649"}.layui-icon-loading-1:before{content:"\e63e"}.layui-icon-return:before{content:"\e65c"}.layui-icon-fonts-strong:before{content:"\e62b"}.layui-icon-upload:before{content:"\e67c"}.layui-icon-dialogue:before{content:"\e63a"}.layui-icon-video:before{content:"\e6ed"}.layui-icon-headset:before{content:"\e6fc"}.layui-icon-cellphone-fine:before{content:"\e63b"}.layui-icon-add-1:before{content:"\e654"}.layui-icon-face-smile-b:before{content:"\e650"}.layui-icon-fonts-html:before{content:"\e64b"}.layui-icon-form:before{content:"\e63c"}.layui-icon-cart:before{content:"\e657"}.layui-icon-camera-fill:before{content:"\e65d"}.layui-icon-tabs:before{content:"\e62a"}.layui-icon-fonts-code:before{content:"\e64e"}.layui-icon-fire:before{content:"\e756"}.layui-icon-set:before{content:"\e716"}.layui-icon-fonts-u:before{content:"\e646"}.layui-icon-triangle-d:before{content:"\e625"}.layui-icon-tips:before{content:"\e702"}.layui-icon-picture:before{content:"\e64a"}.layui-icon-more-vertical:before{content:"\e671"}.layui-icon-flag:before{content:"\e66c"}.layui-icon-loading:before{content:"\e63d"}.layui-icon-fonts-i:before{content:"\e644"}.layui-icon-refresh-1:before{content:"\e666"}.layui-icon-rmb:before{content:"\e65e"}.layui-icon-home:before{content:"\e68e"}.layui-icon-user:before{content:"\e770"}.layui-icon-notice:before{content:"\e667"}.layui-icon-login-weibo:before{content:"\e675"}.layui-icon-voice:before{content:"\e688"}.layui-icon-upload-drag:before{content:"\e681"}.layui-icon-login-qq:before{content:"\e676"}.layui-icon-snowflake:before{content:"\e6b1"}.layui-icon-file-b:before{content:"\e655"}.layui-icon-template:before{content:"\e663"}.layui-icon-auz:before{content:"\e672"}.layui-icon-console:before{content:"\e665"}.layui-icon-app:before{content:"\e653"}.layui-icon-prev:before{content:"\e65a"}.layui-icon-website:before{content:"\e7ae"}.layui-icon-next:before{content:"\e65b"}.layui-icon-component:before{content:"\e857"}.layui-icon-more:before{content:"\e65f"}.layui-icon-login-wechat:before{content:"\e677"}.layui-icon-shrink-right:before{content:"\e668"}.layui-icon-spread-left:before{content:"\e66b"}.layui-icon-camera:before{content:"\e660"}.layui-icon-note:before{content:"\e66e"}.layui-icon-refresh:before{content:"\e669"}.layui-icon-female:before{content:"\e661"}.layui-icon-male:before{content:"\e662"}.layui-icon-password:before{content:"\e673"}.layui-icon-senior:before{content:"\e674"}.layui-icon-theme:before{content:"\e66a"}.layui-icon-tread:before{content:"\e6c5"}.layui-icon-praise:before{content:"\e6c6"}.layui-icon-star-fill:before{content:"\e658"}.layui-icon-rate:before{content:"\e67b"}.layui-icon-template-1:before{content:"\e656"}.layui-icon-vercode:before{content:"\e679"}.layui-icon-cellphone:before{content:"\e678"}.layui-icon-screen-full:before{content:"\e622"}.layui-icon-screen-restore:before{content:"\e758"}.layui-icon-cols:before{content:"\e610"}.layui-icon-export:before{content:"\e67d"}.layui-icon-print:before{content:"\e66d"}.layui-icon-slider:before{content:"\e714"}.layui-main{width:1140px;margin:0 auto}.layui-header{z-index:1000;height:60px}.layui-header a:hover{transition:all .5s;-webkit-transition:all .5s}.layui-side{position:fixed;left:0;top:0;bottom:0;z-index:999;width:200px;overflow-x:hidden}.layui-side-scroll{position:relative;width:220px;height:100%;overflow-x:hidden}.layui-body{position:absolute;left:200px;right:0;top:0;bottom:0;z-index:998;width:auto;overflow:hidden;overflow-y:auto;box-sizing:border-box}.layui-layout-body{overflow:hidden}.layui-layout-admin .layui-header{background-color:#23262E}.layui-layout-admin .layui-side{top:60px;width:200px;overflow-x:hidden}.layui-layout-admin .layui-body{top:60px;bottom:44px}.layui-layout-admin .layui-main{width:auto;margin:0 15px}.layui-layout-admin .layui-footer{position:fixed;left:200px;right:0;bottom:0;height:44px;line-height:44px;padding:0 15px;background-color:#eee}.layui-layout-admin .layui-logo{position:absolute;left:0;top:0;width:200px;height:100%;line-height:60px;text-align:center;color:#009688;font-size:16px}.layui-layout-admin .layui-header .layui-nav{background:0 0}.layui-layout-left{position:absolute!important;left:200px;top:0}.layui-layout-right{position:absolute!important;right:0;top:0}.layui-container{position:relative;margin:0 auto;padding:0 15px;box-sizing:border-box}.layui-fluid{position:relative;margin:0 auto;padding:0 15px}.layui-row:after,.layui-row:before{content:'';display:block;clear:both}.layui-col-lg1,.layui-col-lg10,.layui-col-lg11,.layui-col-lg12,.layui-col-lg2,.layui-col-lg3,.layui-col-lg4,.layui-col-lg5,.layui-col-lg6,.layui-col-lg7,.layui-col-lg8,.layui-col-lg9,.layui-col-md1,.layui-col-md10,.layui-col-md11,.layui-col-md12,.layui-col-md2,.layui-col-md3,.layui-col-md4,.layui-col-md5,.layui-col-md6,.layui-col-md7,.layui-col-md8,.layui-col-md9,.layui-col-sm1,.layui-col-sm10,.layui-col-sm11,.layui-col-sm12,.layui-col-sm2,.layui-col-sm3,.layui-col-sm4,.layui-col-sm5,.layui-col-sm6,.layui-col-sm7,.layui-col-sm8,.layui-col-sm9,.layui-col-xs1,.layui-col-xs10,.layui-col-xs11,.layui-col-xs12,.layui-col-xs2,.layui-col-xs3,.layui-col-xs4,.layui-col-xs5,.layui-col-xs6,.layui-col-xs7,.layui-col-xs8,.layui-col-xs9{position:relative;display:block;box-sizing:border-box}.layui-col-xs1,.layui-col-xs10,.layui-col-xs11,.layui-col-xs12,.layui-col-xs2,.layui-col-xs3,.layui-col-xs4,.layui-col-xs5,.layui-col-xs6,.layui-col-xs7,.layui-col-xs8,.layui-col-xs9{float:left}.layui-col-xs1{width:8.33333333%}.layui-col-xs2{width:16.66666667%}.layui-col-xs3{width:25%}.layui-col-xs4{width:33.33333333%}.layui-col-xs5{width:41.66666667%}.layui-col-xs6{width:50%}.layui-col-xs7{width:58.33333333%}.layui-col-xs8{width:66.66666667%}.layui-col-xs9{width:75%}.layui-col-xs10{width:83.33333333%}.layui-col-xs11{width:91.66666667%}.layui-col-xs12{width:100%}.layui-col-xs-offset1{margin-left:8.33333333%}.layui-col-xs-offset2{margin-left:16.66666667%}.layui-col-xs-offset3{margin-left:25%}.layui-col-xs-offset4{margin-left:33.33333333%}.layui-col-xs-offset5{margin-left:41.66666667%}.layui-col-xs-offset6{margin-left:50%}.layui-col-xs-offset7{margin-left:58.33333333%}.layui-col-xs-offset8{margin-left:66.66666667%}.layui-col-xs-offset9{margin-left:75%}.layui-col-xs-offset10{margin-left:83.33333333%}.layui-col-xs-offset11{margin-left:91.66666667%}.layui-col-xs-offset12{margin-left:100%}@media screen and (max-width:768px){.layui-hide-xs{display:none!important}.layui-show-xs-block{display:block!important}.layui-show-xs-inline{display:inline!important}.layui-show-xs-inline-block{display:inline-block!important}}@media screen and (min-width:768px){.layui-container{width:750px}.layui-hide-sm{display:none!important}.layui-show-sm-block{display:block!important}.layui-show-sm-inline{display:inline!important}.layui-show-sm-inline-block{display:inline-block!important}.layui-col-sm1,.layui-col-sm10,.layui-col-sm11,.layui-col-sm12,.layui-col-sm2,.layui-col-sm3,.layui-col-sm4,.layui-col-sm5,.layui-col-sm6,.layui-col-sm7,.layui-col-sm8,.layui-col-sm9{float:left}.layui-col-sm1{width:8.33333333%}.layui-col-sm2{width:16.66666667%}.layui-col-sm3{width:25%}.layui-col-sm4{width:33.33333333%}.layui-col-sm5{width:41.66666667%}.layui-col-sm6{width:50%}.layui-col-sm7{width:58.33333333%}.layui-col-sm8{width:66.66666667%}.layui-col-sm9{width:75%}.layui-col-sm10{width:83.33333333%}.layui-col-sm11{width:91.66666667%}.layui-col-sm12{width:100%}.layui-col-sm-offset1{margin-left:8.33333333%}.layui-col-sm-offset2{margin-left:16.66666667%}.layui-col-sm-offset3{margin-left:25%}.layui-col-sm-offset4{margin-left:33.33333333%}.layui-col-sm-offset5{margin-left:41.66666667%}.layui-col-sm-offset6{margin-left:50%}.layui-col-sm-offset7{margin-left:58.33333333%}.layui-col-sm-offset8{margin-left:66.66666667%}.layui-col-sm-offset9{margin-left:75%}.layui-col-sm-offset10{margin-left:83.33333333%}.layui-col-sm-offset11{margin-left:91.66666667%}.layui-col-sm-offset12{margin-left:100%}}@media screen and (min-width:992px){.layui-container{width:970px}.layui-hide-md{display:none!important}.layui-show-md-block{display:block!important}.layui-show-md-inline{display:inline!important}.layui-show-md-inline-block{display:inline-block!important}.layui-col-md1,.layui-col-md10,.layui-col-md11,.layui-col-md12,.layui-col-md2,.layui-col-md3,.layui-col-md4,.layui-col-md5,.layui-col-md6,.layui-col-md7,.layui-col-md8,.layui-col-md9{float:left}.layui-col-md1{width:8.33333333%}.layui-col-md2{width:16.66666667%}.layui-col-md3{width:25%}.layui-col-md4{width:33.33333333%}.layui-col-md5{width:41.66666667%}.layui-col-md6{width:50%}.layui-col-md7{width:58.33333333%}.layui-col-md8{width:66.66666667%}.layui-col-md9{width:75%}.layui-col-md10{width:83.33333333%}.layui-col-md11{width:91.66666667%}.layui-col-md12{width:100%}.layui-col-md-offset1{margin-left:8.33333333%}.layui-col-md-offset2{margin-left:16.66666667%}.layui-col-md-offset3{margin-left:25%}.layui-col-md-offset4{margin-left:33.33333333%}.layui-col-md-offset5{margin-left:41.66666667%}.layui-col-md-offset6{margin-left:50%}.layui-col-md-offset7{margin-left:58.33333333%}.layui-col-md-offset8{margin-left:66.66666667%}.layui-col-md-offset9{margin-left:75%}.layui-col-md-offset10{margin-left:83.33333333%}.layui-col-md-offset11{margin-left:91.66666667%}.layui-col-md-offset12{margin-left:100%}}@media screen and (min-width:1200px){.layui-container{width:1170px}.layui-hide-lg{display:none!important}.layui-show-lg-block{display:block!important}.layui-show-lg-inline{display:inline!important}.layui-show-lg-inline-block{display:inline-block!important}.layui-col-lg1,.layui-col-lg10,.layui-col-lg11,.layui-col-lg12,.layui-col-lg2,.layui-col-lg3,.layui-col-lg4,.layui-col-lg5,.layui-col-lg6,.layui-col-lg7,.layui-col-lg8,.layui-col-lg9{float:left}.layui-col-lg1{width:8.33333333%}.layui-col-lg2{width:16.66666667%}.layui-col-lg3{width:25%}.layui-col-lg4{width:33.33333333%}.layui-col-lg5{width:41.66666667%}.layui-col-lg6{width:50%}.layui-col-lg7{width:58.33333333%}.layui-col-lg8{width:66.66666667%}.layui-col-lg9{width:75%}.layui-col-lg10{width:83.33333333%}.layui-col-lg11{width:91.66666667%}.layui-col-lg12{width:100%}.layui-col-lg-offset1{margin-left:8.33333333%}.layui-col-lg-offset2{margin-left:16.66666667%}.layui-col-lg-offset3{margin-left:25%}.layui-col-lg-offset4{margin-left:33.33333333%}.layui-col-lg-offset5{margin-left:41.66666667%}.layui-col-lg-offset6{margin-left:50%}.layui-col-lg-offset7{margin-left:58.33333333%}.layui-col-lg-offset8{margin-left:66.66666667%}.layui-col-lg-offset9{margin-left:75%}.layui-col-lg-offset10{margin-left:83.33333333%}.layui-col-lg-offset11{margin-left:91.66666667%}.layui-col-lg-offset12{margin-left:100%}}.layui-col-space1{margin:-.5px}.layui-col-space1>*{padding:.5px}.layui-col-space3{margin:-1.5px}.layui-col-space3>*{padding:1.5px}.layui-col-space5{margin:-2.5px}.layui-col-space5>*{padding:2.5px}.layui-col-space8{margin:-3.5px}.layui-col-space8>*{padding:3.5px}.layui-col-space10{margin:-5px}.layui-col-space10>*{padding:5px}.layui-col-space12{margin:-6px}.layui-col-space12>*{padding:6px}.layui-col-space15{margin:-7.5px}.layui-col-space15>*{padding:7.5px}.layui-col-space18{margin:-9px}.layui-col-space18>*{padding:9px}.layui-col-space20{margin:-10px}.layui-col-space20>*{padding:10px}.layui-col-space22{margin:-11px}.layui-col-space22>*{padding:11px}.layui-col-space25{margin:-12.5px}.layui-col-space25>*{padding:12.5px}.layui-col-space30{margin:-15px}.layui-col-space30>*{padding:15px}.layui-btn,.layui-input,.layui-select,.layui-textarea,.layui-upload-button{outline:0;-webkit-appearance:none;transition:all .3s;-webkit-transition:all .3s;box-sizing:border-box}.layui-elem-quote{margin-bottom:10px;padding:15px;line-height:22px;border-left:5px solid #009688;border-radius:0 2px 2px 0;background-color:#f2f2f2}.layui-quote-nm{border-style:solid;border-width:1px 1px 1px 5px;background:0 0}.layui-elem-field{margin-bottom:10px;padding:0;border-width:1px;border-style:solid}.layui-elem-field legend{margin-left:20px;padding:0 10px;font-size:20px;font-weight:300}.layui-field-title{margin:10px 0 20px;border-width:1px 0 0}.layui-field-box{padding:10px 15px}.layui-field-title .layui-field-box{padding:10px 0}.layui-progress{position:relative;height:6px;border-radius:20px;background-color:#e2e2e2}.layui-progress-bar{position:absolute;left:0;top:0;width:0;max-width:100%;height:6px;border-radius:20px;text-align:right;background-color:#5FB878;transition:all .3s;-webkit-transition:all .3s}.layui-progress-big,.layui-progress-big .layui-progress-bar{height:18px;line-height:18px}.layui-progress-text{position:relative;top:-20px;line-height:18px;font-size:12px;color:#666}.layui-progress-big .layui-progress-text{position:static;padding:0 10px;color:#fff}.layui-collapse{border-width:1px;border-style:solid;border-radius:2px}.layui-colla-content,.layui-colla-item{border-top-width:1px;border-top-style:solid}.layui-colla-item:first-child{border-top:none}.layui-colla-title{position:relative;height:42px;line-height:42px;padding:0 15px 0 35px;color:#333;background-color:#f2f2f2;cursor:pointer;font-size:14px;overflow:hidden}.layui-colla-content{display:none;padding:10px 15px;line-height:22px;color:#666}.layui-colla-icon{position:absolute;left:15px;top:0;font-size:14px}.layui-card{margin-bottom:15px;border-radius:2px;background-color:#fff;box-shadow:0 1px 2px 0 rgba(0,0,0,.05)}.layui-card:last-child{margin-bottom:0}.layui-card-header{position:relative;height:42px;line-height:42px;padding:0 15px;border-bottom:1px solid #f6f6f6;color:#333;border-radius:2px 2px 0 0;font-size:14px}.layui-bg-black,.layui-bg-blue,.layui-bg-cyan,.layui-bg-green,.layui-bg-orange,.layui-bg-red{color:#fff!important}.layui-card-body{position:relative;padding:10px 15px;line-height:24px}.layui-card-body[pad15]{padding:15px}.layui-card-body[pad20]{padding:20px}.layui-card-body .layui-table{margin:5px 0}.layui-card .layui-tab{margin:0}.layui-panel-window{position:relative;padding:15px;border-radius:0;border-top:5px solid #E6E6E6;background-color:#fff}.layui-auxiliar-moving{position:fixed;left:0;right:0;top:0;bottom:0;width:100%;height:100%;background:0 0;z-index:9999999999}.layui-form-label,.layui-form-mid,.layui-form-select,.layui-input-block,.layui-input-inline,.layui-textarea{position:relative}.layui-bg-red{background-color:#FF5722!important}.layui-bg-orange{background-color:#FFB800!important}.layui-bg-green{background-color:#009688!important}.layui-bg-cyan{background-color:#2F4056!important}.layui-bg-blue{background-color:#1E9FFF!important}.layui-bg-black{background-color:#393D49!important}.layui-bg-gray{background-color:#eee!important;color:#666!important}.layui-badge-rim,.layui-colla-content,.layui-colla-item,.layui-collapse,.layui-elem-field,.layui-form-pane .layui-form-item[pane],.layui-form-pane .layui-form-label,.layui-input,.layui-layedit,.layui-layedit-tool,.layui-quote-nm,.layui-select,.layui-tab-bar,.layui-tab-card,.layui-tab-title,.layui-tab-title .layui-this:after,.layui-textarea{border-color:#e6e6e6}.layui-timeline-item:before,hr{background-color:#e6e6e6}.layui-text{line-height:22px;font-size:14px;color:#666}.layui-text h1,.layui-text h2,.layui-text h3{font-weight:500;color:#333}.layui-text h1{font-size:30px}.layui-text h2{font-size:24px}.layui-text h3{font-size:18px}.layui-text a:not(.layui-btn){color:#01AAED}.layui-text a:not(.layui-btn):hover{text-decoration:underline}.layui-text ul{padding:5px 0 5px 15px}.layui-text ul li{margin-top:5px;list-style-type:disc}.layui-text em,.layui-word-aux{color:#999!important;padding:0 5px!important}.layui-btn{display:inline-block;height:38px;line-height:38px;padding:0 18px;background-color:#009688;color:#fff;white-space:nowrap;text-align:center;font-size:14px;border:none;border-radius:2px;cursor:pointer}.layui-btn:hover{opacity:.8;filter:alpha(opacity=80);color:#fff}.layui-btn:active{opacity:1;filter:alpha(opacity=100)}.layui-btn+.layui-btn{margin-left:10px}.layui-btn-container{font-size:0}.layui-btn-container .layui-btn{margin-right:10px;margin-bottom:10px}.layui-btn-container .layui-btn+.layui-btn{margin-left:0}.layui-table .layui-btn-container .layui-btn{margin-bottom:9px}.layui-btn-radius{border-radius:100px}.layui-btn .layui-icon{margin-right:3px;font-size:18px;vertical-align:bottom;vertical-align:middle\9}.layui-btn-primary{border:1px solid #C9C9C9;background-color:#fff;color:#555}.layui-btn-primary:hover{border-color:#009688;color:#333}.layui-btn-normal{background-color:#1E9FFF}.layui-btn-warm{background-color:#FFB800}.layui-btn-danger{background-color:#FF5722}.layui-btn-disabled,.layui-btn-disabled:active,.layui-btn-disabled:hover{border:1px solid #e6e6e6;background-color:#FBFBFB;color:#C9C9C9;cursor:not-allowed;opacity:1}.layui-btn-lg{height:44px;line-height:44px;padding:0 25px;font-size:16px}.layui-btn-sm{height:30px;line-height:30px;padding:0 10px;font-size:12px}.layui-btn-sm i{font-size:16px!important}.layui-btn-xs{height:22px;line-height:22px;padding:0 5px;font-size:12px}.layui-btn-xs i{font-size:14px!important}.layui-btn-group{display:inline-block;vertical-align:middle;font-size:0}.layui-btn-group .layui-btn{margin-left:0!important;margin-right:0!important;border-left:1px solid rgba(255,255,255,.5);border-radius:0}.layui-btn-group .layui-btn-primary{border-left:none}.layui-btn-group .layui-btn-primary:hover{border-color:#C9C9C9;color:#009688}.layui-btn-group .layui-btn:first-child{border-left:none;border-radius:2px 0 0 2px}.layui-btn-group .layui-btn-primary:first-child{border-left:1px solid #c9c9c9}.layui-btn-group .layui-btn:last-child{border-radius:0 2px 2px 0}.layui-btn-group .layui-btn+.layui-btn{margin-left:0}.layui-btn-group+.layui-btn-group{margin-left:10px}.layui-btn-fluid{width:100%}.layui-input,.layui-select,.layui-textarea{height:38px;line-height:1.3;line-height:38px\9;border-width:1px;border-style:solid;background-color:#fff;border-radius:2px}.layui-input::-webkit-input-placeholder,.layui-select::-webkit-input-placeholder,.layui-textarea::-webkit-input-placeholder{line-height:1.3}.layui-input,.layui-textarea{display:block;width:100%;padding-left:10px}.layui-input:hover,.layui-textarea:hover{border-color:#D2D2D2!important}.layui-input:focus,.layui-textarea:focus{border-color:#C9C9C9!important}.layui-textarea{min-height:100px;height:auto;line-height:20px;padding:6px 10px;resize:vertical}.layui-select{padding:0 10px}.layui-form input[type=checkbox],.layui-form input[type=radio],.layui-form select{display:none}.layui-form [lay-ignore]{display:initial}.layui-form-item{margin-bottom:15px;clear:both;*zoom:1}.layui-form-item:after{content:'\20';clear:both;*zoom:1;display:block;height:0}.layui-form-label{float:left;display:block;padding:9px 15px;width:80px;font-weight:400;line-height:20px;text-align:right}.layui-form-label-col{display:block;float:none;padding:9px 0;line-height:20px;text-align:left}.layui-form-item .layui-inline{margin-bottom:5px;margin-right:10px}.layui-input-block{margin-left:110px;min-height:36px}.layui-input-inline{display:inline-block;vertical-align:middle}.layui-form-item .layui-input-inline{float:left;width:190px;margin-right:10px}.layui-form-text .layui-input-inline{width:auto}.layui-form-mid{float:left;display:block;padding:9px 0!important;line-height:20px;margin-right:10px}.layui-form-danger+.layui-form-select .layui-input,.layui-form-danger:focus{border-color:#FF5722!important}.layui-form-select .layui-input{padding-right:30px;cursor:pointer}.layui-form-select .layui-edge{position:absolute;right:10px;top:50%;margin-top:-3px;cursor:pointer;border-width:6px;border-top-color:#c2c2c2;border-top-style:solid;transition:all .3s;-webkit-transition:all .3s}.layui-form-select dl{display:none;position:absolute;left:0;top:42px;padding:5px 0;z-index:899;min-width:100%;border:1px solid #d2d2d2;max-height:300px;overflow-y:auto;background-color:#fff;border-radius:2px;box-shadow:0 2px 4px rgba(0,0,0,.12);box-sizing:border-box}.layui-form-select dl dd,.layui-form-select dl dt{padding:0 10px;line-height:36px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.layui-form-select dl dt{font-size:12px;color:#999}.layui-form-select dl dd{cursor:pointer}.layui-form-select dl dd:hover{background-color:#f2f2f2;-webkit-transition:.5s all;transition:.5s all}.layui-form-select .layui-select-group dd{padding-left:20px}.layui-form-select dl dd.layui-select-tips{padding-left:10px!important;color:#999}.layui-form-select dl dd.layui-this{background-color:#5FB878;color:#fff}.layui-form-checkbox,.layui-form-select dl dd.layui-disabled{background-color:#fff}.layui-form-selected dl{display:block}.layui-form-checkbox,.layui-form-checkbox *,.layui-form-switch{display:inline-block;vertical-align:middle}.layui-form-selected .layui-edge{margin-top:-9px;-webkit-transform:rotate(180deg);transform:rotate(180deg);margin-top:-3px\9}:root .layui-form-selected .layui-edge{margin-top:-9px\0/IE9}.layui-form-selectup dl{top:auto;bottom:42px}.layui-select-none{margin:5px 0;text-align:center;color:#999}.layui-select-disabled .layui-disabled{border-color:#eee!important}.layui-select-disabled .layui-edge{border-top-color:#d2d2d2}.layui-form-checkbox{position:relative;height:30px;line-height:30px;margin-right:10px;padding-right:30px;cursor:pointer;font-size:0;-webkit-transition:.1s linear;transition:.1s linear;box-sizing:border-box}.layui-form-checkbox span{padding:0 10px;height:100%;font-size:14px;border-radius:2px 0 0 2px;background-color:#d2d2d2;color:#fff;overflow:hidden}.layui-form-checkbox:hover span{background-color:#c2c2c2}.layui-form-checkbox i{position:absolute;right:0;top:0;width:30px;height:28px;border:1px solid #d2d2d2;border-left:none;border-radius:0 2px 2px 0;color:#fff;font-size:20px;text-align:center}.layui-form-checkbox:hover i{border-color:#c2c2c2;color:#c2c2c2}.layui-form-checked,.layui-form-checked:hover{border-color:#5FB878}.layui-form-checked span,.layui-form-checked:hover span{background-color:#5FB878}.layui-form-checked i,.layui-form-checked:hover i{color:#5FB878}.layui-form-item .layui-form-checkbox{margin-top:4px}.layui-form-checkbox[lay-skin=primary]{height:auto!important;line-height:normal!important;min-width:18px;min-height:18px;border:none!important;margin-right:0;padding-left:28px;padding-right:0;background:0 0}.layui-form-checkbox[lay-skin=primary] span{padding-left:0;padding-right:15px;line-height:18px;background:0 0;color:#666}.layui-form-checkbox[lay-skin=primary] i{right:auto;left:0;width:16px;height:16px;line-height:16px;border:1px solid #d2d2d2;font-size:12px;border-radius:2px;background-color:#fff;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-checkbox[lay-skin=primary]:hover i{border-color:#5FB878;color:#fff}.layui-form-checked[lay-skin=primary] i{border-color:#5FB878;background-color:#5FB878;color:#fff}.layui-checkbox-disbaled[lay-skin=primary] span{background:0 0!important;color:#c2c2c2}.layui-checkbox-disbaled[lay-skin=primary]:hover i{border-color:#d2d2d2}.layui-form-item .layui-form-checkbox[lay-skin=primary]{margin-top:10px}.layui-form-switch{position:relative;height:22px;line-height:22px;min-width:35px;padding:0 5px;margin-top:8px;border:1px solid #d2d2d2;border-radius:20px;cursor:pointer;background-color:#fff;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-switch i{position:absolute;left:5px;top:3px;width:16px;height:16px;border-radius:20px;background-color:#d2d2d2;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-switch em{position:relative;top:0;width:25px;margin-left:21px;padding:0!important;text-align:center!important;color:#999!important;font-style:normal!important;font-size:12px}.layui-form-onswitch{border-color:#5FB878;background-color:#5FB878}.layui-checkbox-disbaled,.layui-checkbox-disbaled i{border-color:#e2e2e2!important}.layui-form-onswitch i{left:100%;margin-left:-21px;background-color:#fff}.layui-form-onswitch em{margin-left:5px;margin-right:21px;color:#fff!important}.layui-checkbox-disbaled span{background-color:#e2e2e2!important}.layui-checkbox-disbaled:hover i{color:#fff!important}[lay-radio]{display:none}.layui-form-radio,.layui-form-radio *{display:inline-block;vertical-align:middle}.layui-form-radio{line-height:28px;margin:6px 10px 0 0;padding-right:10px;cursor:pointer;font-size:0}.layui-form-radio *{font-size:14px}.layui-form-radio>i{margin-right:8px;font-size:22px;color:#c2c2c2}.layui-form-radio>i:hover,.layui-form-radioed>i{color:#5FB878}.layui-radio-disbaled>i{color:#e2e2e2!important}.layui-form-pane .layui-form-label{width:110px;padding:8px 15px;height:38px;line-height:20px;border-width:1px;border-style:solid;border-radius:2px 0 0 2px;text-align:center;background-color:#FBFBFB;overflow:hidden;box-sizing:border-box}.layui-form-pane .layui-input-inline{margin-left:-1px}.layui-form-pane .layui-input-block{margin-left:110px;left:-1px}.layui-form-pane .layui-input{border-radius:0 2px 2px 0}.layui-form-pane .layui-form-text .layui-form-label{float:none;width:100%;border-radius:2px;box-sizing:border-box;text-align:left}.layui-form-pane .layui-form-text .layui-input-inline{display:block;margin:0;top:-1px;clear:both}.layui-form-pane .layui-form-text .layui-input-block{margin:0;left:0;top:-1px}.layui-form-pane .layui-form-text .layui-textarea{min-height:100px;border-radius:0 0 2px 2px}.layui-form-pane .layui-form-checkbox{margin:4px 0 4px 10px}.layui-form-pane .layui-form-radio,.layui-form-pane .layui-form-switch{margin-top:6px;margin-left:10px}.layui-form-pane .layui-form-item[pane]{position:relative;border-width:1px;border-style:solid}.layui-form-pane .layui-form-item[pane] .layui-form-label{position:absolute;left:0;top:0;height:100%;border-width:0 1px 0 0}.layui-form-pane .layui-form-item[pane] .layui-input-inline{margin-left:110px}@media screen and (max-width:450px){.layui-form-item .layui-form-label{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-form-item .layui-inline{display:block;margin-right:0;margin-bottom:20px;clear:both}.layui-form-item .layui-inline:after{content:'\20';clear:both;display:block;height:0}.layui-form-item .layui-input-inline{display:block;float:none;left:-3px;width:auto;margin:0 0 10px 112px}.layui-form-item .layui-input-inline+.layui-form-mid{margin-left:110px;top:-5px;padding:0}.layui-form-item .layui-form-checkbox{margin-right:5px;margin-bottom:5px}}.layui-layedit{border-width:1px;border-style:solid;border-radius:2px}.layui-layedit-tool{padding:3px 5px;border-bottom-width:1px;border-bottom-style:solid;font-size:0}.layedit-tool-fixed{position:fixed;top:0;border-top:1px solid #e2e2e2}.layui-layedit-tool .layedit-tool-mid,.layui-layedit-tool .layui-icon{display:inline-block;vertical-align:middle;text-align:center;font-size:14px}.layui-layedit-tool .layui-icon{position:relative;width:32px;height:30px;line-height:30px;margin:3px 5px;color:#777;cursor:pointer;border-radius:2px}.layui-layedit-tool .layui-icon:hover{color:#393D49}.layui-layedit-tool .layui-icon:active{color:#000}.layui-layedit-tool .layedit-tool-active{background-color:#e2e2e2;color:#000}.layui-layedit-tool .layui-disabled,.layui-layedit-tool .layui-disabled:hover{color:#d2d2d2;cursor:not-allowed}.layui-layedit-tool .layedit-tool-mid{width:1px;height:18px;margin:0 10px;background-color:#d2d2d2}.layedit-tool-html{width:50px!important;font-size:30px!important}.layedit-tool-b,.layedit-tool-code,.layedit-tool-help{font-size:16px!important}.layedit-tool-d,.layedit-tool-face,.layedit-tool-image,.layedit-tool-unlink{font-size:18px!important}.layedit-tool-image input{position:absolute;font-size:0;left:0;top:0;width:100%;height:100%;opacity:.01;filter:Alpha(opacity=1);cursor:pointer}.layui-layedit-iframe iframe{display:block;width:100%}#LAY_layedit_code{overflow:hidden}.layui-laypage{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;margin:10px 0;font-size:0}.layui-laypage>a:first-child,.layui-laypage>a:first-child em{border-radius:2px 0 0 2px}.layui-laypage>a:last-child,.layui-laypage>a:last-child em{border-radius:0 2px 2px 0}.layui-laypage>:first-child{margin-left:0!important}.layui-laypage>:last-child{margin-right:0!important}.layui-laypage a,.layui-laypage button,.layui-laypage input,.layui-laypage select,.layui-laypage span{border:1px solid #e2e2e2}.layui-laypage a,.layui-laypage span{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;padding:0 15px;height:28px;line-height:28px;margin:0 -1px 5px 0;background-color:#fff;color:#333;font-size:12px}.layui-flow-more a *,.layui-laypage input,.layui-table-view select[lay-ignore]{display:inline-block}.layui-laypage a:hover{color:#009688}.layui-laypage em{font-style:normal}.layui-laypage .layui-laypage-spr{color:#999;font-weight:700}.layui-laypage a{text-decoration:none}.layui-laypage .layui-laypage-curr{position:relative}.layui-laypage .layui-laypage-curr em{position:relative;color:#fff}.layui-laypage .layui-laypage-curr .layui-laypage-em{position:absolute;left:-1px;top:-1px;padding:1px;width:100%;height:100%;background-color:#009688}.layui-laypage-em{border-radius:2px}.layui-laypage-next em,.layui-laypage-prev em{font-family:Sim sun;font-size:16px}.layui-laypage .layui-laypage-count,.layui-laypage .layui-laypage-limits,.layui-laypage .layui-laypage-refresh,.layui-laypage .layui-laypage-skip{margin-left:10px;margin-right:10px;padding:0;border:none}.layui-laypage .layui-laypage-limits,.layui-laypage .layui-laypage-refresh{vertical-align:top}.layui-laypage .layui-laypage-refresh i{font-size:18px;cursor:pointer}.layui-laypage select{height:22px;padding:3px;border-radius:2px;cursor:pointer}.layui-laypage .layui-laypage-skip{height:30px;line-height:30px;color:#999}.layui-laypage button,.layui-laypage input{height:30px;line-height:30px;border-radius:2px;vertical-align:top;background-color:#fff;box-sizing:border-box}.layui-laypage input{width:40px;margin:0 10px;padding:0 3px;text-align:center}.layui-laypage input:focus,.layui-laypage select:focus{border-color:#009688!important}.layui-laypage button{margin-left:10px;padding:0 10px;cursor:pointer}.layui-table,.layui-table-view{margin:10px 0}.layui-flow-more{margin:10px 0;text-align:center;color:#999;font-size:14px}.layui-flow-more a{height:32px;line-height:32px}.layui-flow-more a *{vertical-align:top}.layui-flow-more a cite{padding:0 20px;border-radius:3px;background-color:#eee;color:#333;font-style:normal}.layui-flow-more a cite:hover{opacity:.8}.layui-flow-more a i{font-size:30px;color:#737383}.layui-table{width:100%;background-color:#fff;color:#666}.layui-table tr{transition:all .3s;-webkit-transition:all .3s}.layui-table th{text-align:left;font-weight:400}.layui-table tbody tr:hover,.layui-table thead tr,.layui-table-click,.layui-table-header,.layui-table-hover,.layui-table-mend,.layui-table-patch,.layui-table-tool,.layui-table-total,.layui-table-total tr,.layui-table[lay-even] tr:nth-child(even){background-color:#f2f2f2}.layui-table td,.layui-table th,.layui-table-col-set,.layui-table-fixed-r,.layui-table-grid-down,.layui-table-header,.layui-table-page,.layui-table-tips-main,.layui-table-tool,.layui-table-total,.layui-table-view,.layui-table[lay-skin=line],.layui-table[lay-skin=row]{border-width:1px;border-style:solid;border-color:#e6e6e6}.layui-table td,.layui-table th{position:relative;padding:9px 15px;min-height:20px;line-height:20px;font-size:14px}.layui-table[lay-skin=line] td,.layui-table[lay-skin=line] th{border-width:0 0 1px}.layui-table[lay-skin=row] td,.layui-table[lay-skin=row] th{border-width:0 1px 0 0}.layui-table[lay-skin=nob] td,.layui-table[lay-skin=nob] th{border:none}.layui-table img{max-width:100px}.layui-table[lay-size=lg] td,.layui-table[lay-size=lg] th{padding:15px 30px}.layui-table-view .layui-table[lay-size=lg] .layui-table-cell{height:40px;line-height:40px}.layui-table[lay-size=sm] td,.layui-table[lay-size=sm] th{font-size:12px;padding:5px 10px}.layui-table-view .layui-table[lay-size=sm] .layui-table-cell{height:20px;line-height:20px}.layui-table[lay-data]{display:none}.layui-table-box{position:relative;overflow:hidden}.layui-table-view .layui-table{position:relative;width:auto;margin:0}.layui-table-view .layui-table[lay-skin=line]{border-width:0 1px 0 0}.layui-table-view .layui-table[lay-skin=row]{border-width:0 0 1px}.layui-table-view .layui-table td,.layui-table-view .layui-table th{padding:5px 0;border-top:none;border-left:none}.layui-table-view .layui-table th.layui-unselect .layui-table-cell span{cursor:pointer}.layui-table-view .layui-table td{cursor:default}.layui-table-view .layui-form-checkbox[lay-skin=primary] i{width:18px;height:18px}.layui-table-view .layui-form-radio{line-height:0;padding:0}.layui-table-view .layui-form-radio>i{margin:0;font-size:20px}.layui-table-init{position:absolute;left:0;top:0;width:100%;height:100%;text-align:center;z-index:110}.layui-table-init .layui-icon{position:absolute;left:50%;top:50%;margin:-15px 0 0 -15px;font-size:30px;color:#c2c2c2}.layui-table-header{border-width:0 0 1px;overflow:hidden}.layui-table-header .layui-table{margin-bottom:-1px}.layui-table-tool .layui-inline[lay-event]{position:relative;width:26px;height:26px;padding:5px;line-height:16px;margin-right:10px;text-align:center;color:#333;border:1px solid #ccc;cursor:pointer;-webkit-transition:.5s all;transition:.5s all}.layui-table-tool .layui-inline[lay-event]:hover{border:1px solid #999}.layui-table-tool-temp{padding-right:120px}.layui-table-tool-self{position:absolute;right:17px;top:10px}.layui-table-tool .layui-table-tool-self .layui-inline[lay-event]{margin:0 0 0 10px}.layui-table-tool-panel{position:absolute;top:29px;left:-1px;padding:5px 0;min-width:150px;min-height:40px;border:1px solid #d2d2d2;text-align:left;overflow-y:auto;background-color:#fff;box-shadow:0 2px 4px rgba(0,0,0,.12)}.layui-table-cell,.layui-table-tool-panel li{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.layui-table-tool-panel li{padding:0 10px;line-height:30px;-webkit-transition:.5s all;transition:.5s all}.layui-table-tool-panel li .layui-form-checkbox[lay-skin=primary]{width:100%;padding-left:28px}.layui-table-tool-panel li:hover{background-color:#f2f2f2}.layui-table-tool-panel li .layui-form-checkbox[lay-skin=primary] i{position:absolute;left:0;top:0}.layui-table-tool-panel li .layui-form-checkbox[lay-skin=primary] span{padding:0}.layui-table-tool .layui-table-tool-self .layui-table-tool-panel{left:auto;right:-1px}.layui-table-col-set{position:absolute;right:0;top:0;width:20px;height:100%;border-width:0 0 0 1px;background-color:#fff}.layui-table-sort{width:10px;height:20px;margin-left:5px;cursor:pointer!important}.layui-table-sort .layui-edge{position:absolute;left:5px;border-width:5px}.layui-table-sort .layui-table-sort-asc{top:3px;border-top:none;border-bottom-style:solid;border-bottom-color:#b2b2b2}.layui-table-sort .layui-table-sort-asc:hover{border-bottom-color:#666}.layui-table-sort .layui-table-sort-desc{bottom:5px;border-bottom:none;border-top-style:solid;border-top-color:#b2b2b2}.layui-table-sort .layui-table-sort-desc:hover{border-top-color:#666}.layui-table-sort[lay-sort=asc] .layui-table-sort-asc{border-bottom-color:#000}.layui-table-sort[lay-sort=desc] .layui-table-sort-desc{border-top-color:#000}.layui-table-cell{height:28px;line-height:28px;padding:0 15px;position:relative;box-sizing:border-box}.layui-table-cell .layui-form-checkbox[lay-skin=primary]{top:-1px;padding:0}.layui-table-cell .layui-table-link{color:#01AAED}.laytable-cell-checkbox,.laytable-cell-numbers,.laytable-cell-radio,.laytable-cell-space{padding:0;text-align:center}.layui-table-body{position:relative;overflow:auto;margin-right:-1px;margin-bottom:-1px}.layui-table-body .layui-none{line-height:26px;padding:15px;text-align:center;color:#999}.layui-table-fixed{position:absolute;left:0;top:0;z-index:101}.layui-table-fixed .layui-table-body{overflow:hidden}.layui-table-fixed-l{box-shadow:0 -1px 8px rgba(0,0,0,.08)}.layui-table-fixed-r{left:auto;right:-1px;border-width:0 0 0 1px;box-shadow:-1px 0 8px rgba(0,0,0,.08)}.layui-table-fixed-r .layui-table-header{position:relative;overflow:visible}.layui-table-mend{position:absolute;right:-49px;top:0;height:100%;width:50px}.layui-table-tool{position:relative;z-index:890;width:100%;min-height:50px;line-height:30px;padding:10px 15px;border-width:0 0 1px}.layui-table-tool .layui-btn-container{margin-bottom:-10px}.layui-table-page,.layui-table-total{border-width:1px 0 0;margin-bottom:-1px;overflow:hidden}.layui-table-page{position:relative;width:100%;padding:7px 7px 0;height:41px;font-size:12px;white-space:nowrap}.layui-table-page>div{height:26px}.layui-table-page .layui-laypage{margin:0}.layui-table-page .layui-laypage a,.layui-table-page .layui-laypage span{height:26px;line-height:26px;margin-bottom:10px;border:none;background:0 0}.layui-table-page .layui-laypage a,.layui-table-page .layui-laypage span.layui-laypage-curr{padding:0 12px}.layui-table-page .layui-laypage span{margin-left:0;padding:0}.layui-table-page .layui-laypage .layui-laypage-prev{margin-left:-7px!important}.layui-table-page .layui-laypage .layui-laypage-curr .layui-laypage-em{left:0;top:0;padding:0}.layui-table-page .layui-laypage button,.layui-table-page .layui-laypage input{height:26px;line-height:26px}.layui-table-page .layui-laypage input{width:40px}.layui-table-page .layui-laypage button{padding:0 10px}.layui-table-page select{height:18px}.layui-table-patch .layui-table-cell{padding:0;width:30px}.layui-table-edit{position:absolute;left:0;top:0;width:100%;height:100%;padding:0 14px 1px;border-radius:0;box-shadow:1px 1px 20px rgba(0,0,0,.15)}.layui-table-edit:focus{border-color:#5FB878!important}select.layui-table-edit{padding:0 0 0 10px;border-color:#C9C9C9}.layui-table-view .layui-form-checkbox,.layui-table-view .layui-form-radio,.layui-table-view .layui-form-switch{top:0;margin:0;box-sizing:content-box}.layui-table-view .layui-form-checkbox{top:-1px;height:26px;line-height:26px}.layui-table-view .layui-form-checkbox i{height:26px}.layui-table-grid .layui-table-cell{overflow:visible}.layui-table-grid-down{position:absolute;top:0;right:0;width:26px;height:100%;padding:5px 0;border-width:0 0 0 1px;text-align:center;background-color:#fff;color:#999;cursor:pointer}.layui-table-grid-down .layui-icon{position:absolute;top:50%;left:50%;margin:-8px 0 0 -8px}.layui-table-grid-down:hover{background-color:#fbfbfb}body .layui-table-tips .layui-layer-content{background:0 0;padding:0;box-shadow:0 1px 6px rgba(0,0,0,.12)}.layui-table-tips-main{margin:-44px 0 0 -1px;max-height:150px;padding:8px 15px;font-size:14px;overflow-y:scroll;background-color:#fff;color:#666}.layui-table-tips-c{position:absolute;right:-3px;top:-13px;width:20px;height:20px;padding:3px;cursor:pointer;background-color:#666;border-radius:50%;color:#fff}.layui-table-tips-c:hover{background-color:#777}.layui-table-tips-c:before{position:relative;right:-2px}.layui-upload-file{display:none!important;opacity:.01;filter:Alpha(opacity=1)}.layui-upload-drag,.layui-upload-form,.layui-upload-wrap{display:inline-block}.layui-upload-list{margin:10px 0}.layui-upload-choose{padding:0 10px;color:#999}.layui-upload-drag{position:relative;padding:30px;border:1px dashed #e2e2e2;background-color:#fff;text-align:center;cursor:pointer;color:#999}.layui-upload-drag .layui-icon{font-size:50px;color:#009688}.layui-upload-drag[lay-over]{border-color:#009688}.layui-upload-iframe{position:absolute;width:0;height:0;border:0;visibility:hidden}.layui-upload-wrap{position:relative;vertical-align:middle}.layui-upload-wrap .layui-upload-file{display:block!important;position:absolute;left:0;top:0;z-index:10;font-size:100px;width:100%;height:100%;opacity:.01;filter:Alpha(opacity=1);cursor:pointer}.layui-tree{line-height:26px}.layui-tree li{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-tree li .layui-tree-spread,.layui-tree li a{display:inline-block;vertical-align:top;height:26px;*display:inline;*zoom:1;cursor:pointer}.layui-tree li a{font-size:0}.layui-tree li a i{font-size:16px}.layui-tree li a cite{padding:0 6px;font-size:14px;font-style:normal}.layui-tree li i{padding-left:6px;color:#333;-moz-user-select:none}.layui-tree li .layui-tree-check{font-size:13px}.layui-tree li .layui-tree-check:hover{color:#009E94}.layui-tree li ul{display:none;margin-left:20px}.layui-tree li .layui-tree-enter{line-height:24px;border:1px dotted #000}.layui-tree-drag{display:none;position:absolute;left:-666px;top:-666px;background-color:#f2f2f2;padding:5px 10px;border:1px dotted #000;white-space:nowrap}.layui-tree-drag i{padding-right:5px}.layui-nav{position:relative;padding:0 20px;background-color:#393D49;color:#fff;border-radius:2px;font-size:0;box-sizing:border-box}.layui-nav *{font-size:14px}.layui-nav .layui-nav-item{position:relative;display:inline-block;*display:inline;*zoom:1;vertical-align:middle;line-height:60px}.layui-nav .layui-nav-item a{display:block;padding:0 20px;color:#fff;color:rgba(255,255,255,.7);transition:all .3s;-webkit-transition:all .3s}.layui-nav .layui-this:after,.layui-nav-bar,.layui-nav-tree .layui-nav-itemed:after{position:absolute;left:0;top:0;width:0;height:5px;background-color:#5FB878;transition:all .2s;-webkit-transition:all .2s}.layui-nav-bar{z-index:1000}.layui-nav .layui-nav-item a:hover,.layui-nav .layui-this a{color:#fff}.layui-nav .layui-this:after{content:'';top:auto;bottom:0;width:100%}.layui-nav-img{width:30px;height:30px;margin-right:10px;border-radius:50%}.layui-nav .layui-nav-more{content:'';width:0;height:0;border-style:solid dashed dashed;border-color:#fff transparent transparent;overflow:hidden;cursor:pointer;transition:all .2s;-webkit-transition:all .2s;position:absolute;top:50%;right:3px;margin-top:-3px;border-width:6px;border-top-color:rgba(255,255,255,.7)}.layui-nav .layui-nav-mored,.layui-nav-itemed>a .layui-nav-more{margin-top:-9px;border-style:dashed dashed solid;border-color:transparent transparent #fff}.layui-nav-child{display:none;position:absolute;left:0;top:65px;min-width:100%;line-height:36px;padding:5px 0;box-shadow:0 2px 4px rgba(0,0,0,.12);border:1px solid #d2d2d2;background-color:#fff;z-index:100;border-radius:2px;white-space:nowrap}.layui-nav .layui-nav-child a{color:#333}.layui-nav .layui-nav-child a:hover{background-color:#f2f2f2;color:#000}.layui-nav-child dd{position:relative}.layui-nav .layui-nav-child dd.layui-this a,.layui-nav-child dd.layui-this{background-color:#5FB878;color:#fff}.layui-nav-child dd.layui-this:after{display:none}.layui-nav-tree{width:200px;padding:0}.layui-nav-tree .layui-nav-item{display:block;width:100%;line-height:45px}.layui-nav-tree .layui-nav-item a{position:relative;height:45px;line-height:45px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-nav-tree .layui-nav-item a:hover{background-color:#4E5465}.layui-nav-tree .layui-nav-bar{width:5px;height:0;background-color:#009688}.layui-nav-tree .layui-nav-child dd.layui-this,.layui-nav-tree .layui-nav-child dd.layui-this a,.layui-nav-tree .layui-this,.layui-nav-tree .layui-this>a,.layui-nav-tree .layui-this>a:hover{background-color:#009688;color:#fff}.layui-nav-tree .layui-this:after{display:none}.layui-nav-itemed>a,.layui-nav-tree .layui-nav-title a,.layui-nav-tree .layui-nav-title a:hover{color:#fff!important}.layui-nav-tree .layui-nav-child{position:relative;z-index:0;top:0;border:none;box-shadow:none}.layui-nav-tree .layui-nav-child a{height:40px;line-height:40px;color:#fff;color:rgba(255,255,255,.7)}.layui-nav-tree .layui-nav-child,.layui-nav-tree .layui-nav-child a:hover{background:0 0;color:#fff}.layui-nav-tree .layui-nav-more{right:10px}.layui-nav-itemed>.layui-nav-child{display:block;padding:0;background-color:rgba(0,0,0,.3)!important}.layui-nav-itemed>.layui-nav-child>.layui-this>.layui-nav-child{display:block}.layui-nav-side{position:fixed;top:0;bottom:0;left:0;overflow-x:hidden;z-index:999}.layui-bg-blue .layui-nav-bar,.layui-bg-blue .layui-nav-itemed:after,.layui-bg-blue .layui-this:after{background-color:#93D1FF}.layui-bg-blue .layui-nav-child dd.layui-this{background-color:#1E9FFF}.layui-bg-blue .layui-nav-itemed>a,.layui-nav-tree.layui-bg-blue .layui-nav-title a,.layui-nav-tree.layui-bg-blue .layui-nav-title a:hover{background-color:#007DDB!important}.layui-breadcrumb{visibility:hidden;font-size:0}.layui-breadcrumb>*{font-size:14px}.layui-breadcrumb a{color:#999!important}.layui-breadcrumb a:hover{color:#5FB878!important}.layui-breadcrumb a cite{color:#666;font-style:normal}.layui-breadcrumb span[lay-separator]{margin:0 10px;color:#999}.layui-tab{margin:10px 0;text-align:left!important}.layui-tab[overflow]>.layui-tab-title{overflow:hidden}.layui-tab-title{position:relative;left:0;height:40px;white-space:nowrap;font-size:0;border-bottom-width:1px;border-bottom-style:solid;transition:all .2s;-webkit-transition:all .2s}.layui-tab-title li{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;font-size:14px;transition:all .2s;-webkit-transition:all .2s;position:relative;line-height:40px;min-width:65px;padding:0 15px;text-align:center;cursor:pointer}.layui-tab-title li a{display:block}.layui-tab-title .layui-this{color:#000}.layui-tab-title .layui-this:after{position:absolute;left:0;top:0;content:'';width:100%;height:41px;border-width:1px;border-style:solid;border-bottom-color:#fff;border-radius:2px 2px 0 0;box-sizing:border-box;pointer-events:none}.layui-tab-bar{position:absolute;right:0;top:0;z-index:10;width:30px;height:39px;line-height:39px;border-width:1px;border-style:solid;border-radius:2px;text-align:center;background-color:#fff;cursor:pointer}.layui-tab-bar .layui-icon{position:relative;display:inline-block;top:3px;transition:all .3s;-webkit-transition:all .3s}.layui-tab-item{display:none}.layui-tab-more{padding-right:30px;height:auto!important;white-space:normal!important}.layui-tab-more li.layui-this:after{border-bottom-color:#e2e2e2;border-radius:2px}.layui-tab-more .layui-tab-bar .layui-icon{top:-2px;top:3px\9;-webkit-transform:rotate(180deg);transform:rotate(180deg)}:root .layui-tab-more .layui-tab-bar .layui-icon{top:-2px\0/IE9}.layui-tab-content{padding:10px}.layui-tab-title li .layui-tab-close{position:relative;display:inline-block;width:18px;height:18px;line-height:20px;margin-left:8px;top:1px;text-align:center;font-size:14px;color:#c2c2c2;transition:all .2s;-webkit-transition:all .2s}.layui-tab-title li .layui-tab-close:hover{border-radius:2px;background-color:#FF5722;color:#fff}.layui-tab-brief>.layui-tab-title .layui-this{color:#009688}.layui-tab-brief>.layui-tab-more li.layui-this:after,.layui-tab-brief>.layui-tab-title .layui-this:after{border:none;border-radius:0;border-bottom:2px solid #5FB878}.layui-tab-brief[overflow]>.layui-tab-title .layui-this:after{top:-1px}.layui-tab-card{border-width:1px;border-style:solid;border-radius:2px;box-shadow:0 2px 5px 0 rgba(0,0,0,.1)}.layui-tab-card>.layui-tab-title{background-color:#f2f2f2}.layui-tab-card>.layui-tab-title li{margin-right:-1px;margin-left:-1px}.layui-tab-card>.layui-tab-title .layui-this{background-color:#fff}.layui-tab-card>.layui-tab-title .layui-this:after{border-top:none;border-width:1px;border-bottom-color:#fff}.layui-tab-card>.layui-tab-title .layui-tab-bar{height:40px;line-height:40px;border-radius:0;border-top:none;border-right:none}.layui-tab-card>.layui-tab-more .layui-this{background:0 0;color:#5FB878}.layui-tab-card>.layui-tab-more .layui-this:after{border:none}.layui-timeline{padding-left:5px}.layui-timeline-item{position:relative;padding-bottom:20px}.layui-timeline-axis{position:absolute;left:-5px;top:0;z-index:10;width:20px;height:20px;line-height:20px;background-color:#fff;color:#5FB878;border-radius:50%;text-align:center;cursor:pointer}.layui-timeline-axis:hover{color:#FF5722}.layui-timeline-item:before{content:'';position:absolute;left:5px;top:0;z-index:0;width:1px;height:100%}.layui-timeline-item:last-child:before{display:none}.layui-timeline-item:first-child:before{display:block}.layui-timeline-content{padding-left:25px}.layui-timeline-title{position:relative;margin-bottom:10px}.layui-badge,.layui-badge-dot,.layui-badge-rim{position:relative;display:inline-block;padding:0 6px;font-size:12px;text-align:center;background-color:#FF5722;color:#fff;border-radius:2px}.layui-badge{height:18px;line-height:18px}.layui-badge-dot{width:8px;height:8px;padding:0;border-radius:50%}.layui-badge-rim{height:18px;line-height:18px;border-width:1px;border-style:solid;background-color:#fff;color:#666}.layui-btn .layui-badge,.layui-btn .layui-badge-dot{margin-left:5px}.layui-nav .layui-badge,.layui-nav .layui-badge-dot{position:absolute;top:50%;margin:-8px 6px 0}.layui-tab-title .layui-badge,.layui-tab-title .layui-badge-dot{left:5px;top:-2px}.layui-carousel{position:relative;left:0;top:0;background-color:#f8f8f8}.layui-carousel>[carousel-item]{position:relative;width:100%;height:100%;overflow:hidden}.layui-carousel>[carousel-item]:before{position:absolute;content:'\e63d';left:50%;top:50%;width:100px;line-height:20px;margin:-10px 0 0 -50px;text-align:center;color:#c2c2c2;font-family:layui-icon!important;font-size:30px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.layui-carousel>[carousel-item]>*{display:none;position:absolute;left:0;top:0;width:100%;height:100%;background-color:#f8f8f8;transition-duration:.3s;-webkit-transition-duration:.3s}.layui-carousel-updown>*{-webkit-transition:.3s ease-in-out up;transition:.3s ease-in-out up}.layui-carousel-arrow{display:none\9;opacity:0;position:absolute;left:10px;top:50%;margin-top:-18px;width:36px;height:36px;line-height:36px;text-align:center;font-size:20px;border:0;border-radius:50%;background-color:rgba(0,0,0,.2);color:#fff;-webkit-transition-duration:.3s;transition-duration:.3s;cursor:pointer}.layui-carousel-arrow[lay-type=add]{left:auto!important;right:10px}.layui-carousel:hover .layui-carousel-arrow[lay-type=add],.layui-carousel[lay-arrow=always] .layui-carousel-arrow[lay-type=add]{right:20px}.layui-carousel[lay-arrow=always] .layui-carousel-arrow{opacity:1;left:20px}.layui-carousel[lay-arrow=none] .layui-carousel-arrow{display:none}.layui-carousel-arrow:hover,.layui-carousel-ind ul:hover{background-color:rgba(0,0,0,.35)}.layui-carousel:hover .layui-carousel-arrow{display:block\9;opacity:1;left:20px}.layui-carousel-ind{position:relative;top:-35px;width:100%;line-height:0!important;text-align:center;font-size:0}.layui-carousel[lay-indicator=outside]{margin-bottom:30px}.layui-carousel[lay-indicator=outside] .layui-carousel-ind{top:10px}.layui-carousel[lay-indicator=outside] .layui-carousel-ind ul{background-color:rgba(0,0,0,.5)}.layui-carousel[lay-indicator=none] .layui-carousel-ind{display:none}.layui-carousel-ind ul{display:inline-block;padding:5px;background-color:rgba(0,0,0,.2);border-radius:10px;-webkit-transition-duration:.3s;transition-duration:.3s}.layui-carousel-ind li{display:inline-block;width:10px;height:10px;margin:0 3px;font-size:14px;background-color:#e2e2e2;background-color:rgba(255,255,255,.5);border-radius:50%;cursor:pointer;-webkit-transition-duration:.3s;transition-duration:.3s}.layui-carousel-ind li:hover{background-color:rgba(255,255,255,.7)}.layui-carousel-ind li.layui-this{background-color:#fff}.layui-carousel>[carousel-item]>.layui-carousel-next,.layui-carousel>[carousel-item]>.layui-carousel-prev,.layui-carousel>[carousel-item]>.layui-this{display:block}.layui-carousel>[carousel-item]>.layui-this{left:0}.layui-carousel>[carousel-item]>.layui-carousel-prev{left:-100%}.layui-carousel>[carousel-item]>.layui-carousel-next{left:100%}.layui-carousel>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel>[carousel-item]>.layui-carousel-prev.layui-carousel-right{left:0}.layui-carousel>[carousel-item]>.layui-this.layui-carousel-left{left:-100%}.layui-carousel>[carousel-item]>.layui-this.layui-carousel-right{left:100%}.layui-carousel[lay-anim=updown] .layui-carousel-arrow{left:50%!important;top:20px;margin:0 0 0 -18px}.layui-carousel[lay-anim=updown]>[carousel-item]>*,.layui-carousel[lay-anim=fade]>[carousel-item]>*{left:0!important}.layui-carousel[lay-anim=updown] .layui-carousel-arrow[lay-type=add]{top:auto!important;bottom:20px}.layui-carousel[lay-anim=updown] .layui-carousel-ind{position:absolute;top:50%;right:20px;width:auto;height:auto}.layui-carousel[lay-anim=updown] .layui-carousel-ind ul{padding:3px 5px}.layui-carousel[lay-anim=updown] .layui-carousel-ind li{display:block;margin:6px 0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this{top:0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-prev{top:-100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-next{top:100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-prev.layui-carousel-right{top:0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this.layui-carousel-left{top:-100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this.layui-carousel-right{top:100%}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-next,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-prev{opacity:0}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-prev.layui-carousel-right{opacity:1}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-this.layui-carousel-left,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-this.layui-carousel-right{opacity:0}.layui-fixbar{position:fixed;right:15px;bottom:15px;z-index:999999}.layui-fixbar li{width:50px;height:50px;line-height:50px;margin-bottom:1px;text-align:center;cursor:pointer;font-size:30px;background-color:#9F9F9F;color:#fff;border-radius:2px;opacity:.95}.layui-fixbar li:hover{opacity:.85}.layui-fixbar li:active{opacity:1}.layui-fixbar .layui-fixbar-top{display:none;font-size:40px}body .layui-util-face{border:none;background:0 0}body .layui-util-face .layui-layer-content{padding:0;background-color:#fff;color:#666;box-shadow:none}.layui-util-face .layui-layer-TipsG{display:none}.layui-util-face ul{position:relative;width:372px;padding:10px;border:1px solid #D9D9D9;background-color:#fff;box-shadow:0 0 20px rgba(0,0,0,.2)}.layui-util-face ul li{cursor:pointer;float:left;border:1px solid #e8e8e8;height:22px;width:26px;overflow:hidden;margin:-1px 0 0 -1px;padding:4px 2px;text-align:center}.layui-util-face ul li:hover{position:relative;z-index:2;border:1px solid #eb7350;background:#fff9ec}.layui-code{position:relative;margin:10px 0;padding:15px;line-height:20px;border:1px solid #ddd;border-left-width:6px;background-color:#F2F2F2;color:#333;font-family:Courier New;font-size:12px}.layui-rate,.layui-rate *{display:inline-block;vertical-align:middle}.layui-rate{padding:10px 5px 10px 0;font-size:0}.layui-rate li i.layui-icon{font-size:20px;color:#FFB800;margin-right:5px;transition:all .3s;-webkit-transition:all .3s}.layui-rate li i:hover{cursor:pointer;transform:scale(1.12);-webkit-transform:scale(1.12)}.layui-rate[readonly] li i:hover{cursor:default;transform:scale(1)}.layui-colorpicker{width:26px;height:26px;border:1px solid #e6e6e6;padding:5px;border-radius:2px;line-height:24px;display:inline-block;cursor:pointer;transition:all .3s;-webkit-transition:all .3s}.layui-colorpicker:hover{border-color:#d2d2d2}.layui-colorpicker.layui-colorpicker-lg{width:34px;height:34px;line-height:32px}.layui-colorpicker.layui-colorpicker-sm{width:24px;height:24px;line-height:22px}.layui-colorpicker.layui-colorpicker-xs{width:22px;height:22px;line-height:20px}.layui-colorpicker-trigger-bgcolor{display:block;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);border-radius:2px}.layui-colorpicker-trigger-span{display:block;height:100%;box-sizing:border-box;border:1px solid rgba(0,0,0,.15);border-radius:2px;text-align:center}.layui-colorpicker-trigger-i{display:inline-block;color:#FFF;font-size:12px}.layui-colorpicker-trigger-i.layui-icon-close{color:#999}.layui-colorpicker-main{position:absolute;z-index:66666666;width:280px;padding:7px;background:#FFF;border:1px solid #d2d2d2;border-radius:2px;box-shadow:0 2px 4px rgba(0,0,0,.12)}.layui-colorpicker-main-wrapper{height:180px;position:relative}.layui-colorpicker-basis{width:260px;height:100%;position:relative}.layui-colorpicker-basis-white{width:100%;height:100%;position:absolute;top:0;left:0;background:linear-gradient(90deg,#FFF,hsla(0,0%,100%,0))}.layui-colorpicker-basis-black{width:100%;height:100%;position:absolute;top:0;left:0;background:linear-gradient(0deg,#000,transparent)}.layui-colorpicker-basis-cursor{width:10px;height:10px;border:1px solid #FFF;border-radius:50%;position:absolute;top:-3px;right:-3px;cursor:pointer}.layui-colorpicker-side{position:absolute;top:0;right:0;width:12px;height:100%;background:linear-gradient(red,#FF0,#0F0,#0FF,#00F,#F0F,red)}.layui-colorpicker-side-slider{width:100%;height:5px;box-shadow:0 0 1px #888;box-sizing:border-box;background:#FFF;border-radius:1px;border:1px solid #f0f0f0;cursor:pointer;position:absolute;left:0}.layui-colorpicker-main-alpha{display:none;height:12px;margin-top:7px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.layui-colorpicker-alpha-bgcolor{height:100%;position:relative}.layui-colorpicker-alpha-slider{width:5px;height:100%;box-shadow:0 0 1px #888;box-sizing:border-box;background:#FFF;border-radius:1px;border:1px solid #f0f0f0;cursor:pointer;position:absolute;top:0}.layui-colorpicker-main-pre{padding-top:7px;font-size:0}.layui-colorpicker-pre{width:20px;height:20px;border-radius:2px;display:inline-block;margin-left:6px;margin-bottom:7px;cursor:pointer}.layui-colorpicker-pre:nth-child(11n+1){margin-left:0}.layui-colorpicker-pre-isalpha{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.layui-colorpicker-pre.layui-this{box-shadow:0 0 3px 2px rgba(0,0,0,.15)}.layui-colorpicker-pre>div{height:100%;border-radius:2px}.layui-colorpicker-main-input{text-align:right;padding-top:7px}.layui-colorpicker-main-input .layui-btn-container .layui-btn{margin:0 0 0 10px}.layui-colorpicker-main-input div.layui-inline{float:left;margin-right:10px;font-size:14px}.layui-colorpicker-main-input input.layui-input{width:150px;height:30px;color:#666}.layui-slider{height:4px;background:#e2e2e2;border-radius:3px;position:relative;cursor:pointer}.layui-slider-bar{border-radius:3px;position:absolute;height:100%}.layui-slider-step{position:absolute;top:0;width:4px;height:4px;border-radius:50%;background:#FFF;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.layui-slider-wrap{width:36px;height:36px;position:absolute;top:-16px;-webkit-transform:translateX(-50%);transform:translateX(-50%);z-index:10;text-align:center}.layui-slider-wrap-btn{width:12px;height:12px;border-radius:50%;background:#FFF;display:inline-block;vertical-align:middle;cursor:pointer;transition:.3s}.layui-slider-wrap:after{content:"";height:100%;display:inline-block;vertical-align:middle}.layui-slider-wrap-btn.layui-slider-hover,.layui-slider-wrap-btn:hover{transform:scale(1.2)}.layui-slider-wrap-btn.layui-disabled:hover{transform:scale(1)!important}.layui-slider-tips{position:absolute;top:-42px;z-index:66666666;white-space:nowrap;display:none;-webkit-transform:translateX(-50%);transform:translateX(-50%);color:#FFF;background:#000;border-radius:3px;height:25px;line-height:25px;padding:0 10px}.layui-slider-tips:after{content:'';position:absolute;bottom:-12px;left:50%;margin-left:-6px;width:0;height:0;border-width:6px;border-style:solid;border-color:#000 transparent transparent}.layui-slider-input{width:70px;height:32px;border:1px solid #e6e6e6;border-radius:3px;font-size:16px;line-height:32px;position:absolute;right:0;top:-15px}.layui-slider-input-btn{display:none;position:absolute;top:0;right:0;width:20px;height:100%;border-left:1px solid #d2d2d2}.layui-slider-input-btn i{cursor:pointer;position:absolute;right:0;bottom:0;width:20px;height:50%;font-size:12px;line-height:16px;text-align:center;color:#999}.layui-slider-input-btn i:first-child{top:0;border-bottom:1px solid #d2d2d2}.layui-slider-input-txt{height:100%;font-size:14px}.layui-slider-input-txt input{height:100%;border:none}.layui-slider-input-btn i:hover{color:#009688}.layui-slider-vertical{width:4px;margin-left:34px}.layui-slider-vertical .layui-slider-bar{width:4px}.layui-slider-vertical .layui-slider-step{top:auto;left:0;-webkit-transform:translateY(50%);transform:translateY(50%)}.layui-slider-vertical .layui-slider-wrap{top:auto;left:-16px;-webkit-transform:translateY(50%);transform:translateY(50%)}.layui-slider-vertical .layui-slider-tips{top:auto;left:2px}@media \0screen{.layui-slider-wrap-btn{margin-left:-20px}.layui-slider-vertical .layui-slider-wrap-btn{margin-left:0;margin-bottom:-20px}.layui-slider-vertical .layui-slider-tips{margin-left:-8px}.layui-slider>span{margin-left:8px}}.layui-anim{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.layui-anim.layui-icon{display:inline-block}.layui-anim-loop{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.layui-trans,.layui-trans a{transition:all .3s;-webkit-transition:all .3s}@-webkit-keyframes layui-rotate{from{-webkit-transform:rotate(0)}to{-webkit-transform:rotate(360deg)}}@keyframes layui-rotate{from{transform:rotate(0)}to{transform:rotate(360deg)}}.layui-anim-rotate{-webkit-animation-name:layui-rotate;animation-name:layui-rotate;-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-timing-function:linear;animation-timing-function:linear}@-webkit-keyframes layui-up{from{-webkit-transform:translate3d(0,100%,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes layui-up{from{transform:translate3d(0,100%,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-anim-up{-webkit-animation-name:layui-up;animation-name:layui-up}@-webkit-keyframes layui-upbit{from{-webkit-transform:translate3d(0,30px,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes layui-upbit{from{transform:translate3d(0,30px,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-anim-upbit{-webkit-animation-name:layui-upbit;animation-name:layui-upbit}@-webkit-keyframes layui-scale{0%{opacity:.3;-webkit-transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes layui-scale{0%{opacity:.3;-ms-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-ms-transform:scale(1);transform:scale(1)}}.layui-anim-scale{-webkit-animation-name:layui-scale;animation-name:layui-scale}@-webkit-keyframes layui-scale-spring{0%{opacity:.5;-webkit-transform:scale(.5)}80%{opacity:.8;-webkit-transform:scale(1.1)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes layui-scale-spring{0%{opacity:.5;transform:scale(.5)}80%{opacity:.8;transform:scale(1.1)}100%{opacity:1;transform:scale(1)}}.layui-anim-scaleSpring{-webkit-animation-name:layui-scale-spring;animation-name:layui-scale-spring}@-webkit-keyframes layui-fadein{0%{opacity:0}100%{opacity:1}}@keyframes layui-fadein{0%{opacity:0}100%{opacity:1}}.layui-anim-fadein{-webkit-animation-name:layui-fadein;animation-name:layui-fadein}@-webkit-keyframes layui-fadeout{0%{opacity:1}100%{opacity:0}}@keyframes layui-fadeout{0%{opacity:1}100%{opacity:0}}.layui-anim-fadeout{-webkit-animation-name:layui-fadeout;animation-name:layui-fadeout} \ No newline at end of file + .layui-inline,img{display:inline-block;vertical-align:middle}h1,h2,h3,h4,h5,h6{font-weight:400}.layui-edge,.layui-header,.layui-inline,.layui-main{position:relative}.layui-elip,.layui-form-checkbox span,.layui-form-pane .layui-form-label{text-overflow:clip;white-space:nowrap}.layui-btn,.layui-edge,.layui-inline,img{vertical-align:middle}.layui-btn,.layui-disabled,.layui-icon,.layui-unselect{-webkit-user-select:none;-ms-user-select:none;-moz-user-select:none}blockquote,body,button,dd,div,dl,dt,form,h1,h2,h3,h4,h5,h6,input,li,ol,p,pre,td,textarea,th,ul{margin:0;padding:0;-webkit-tap-highlight-color:rgba(0,0,0,0)}a:active,a:hover{outline:0}img{border:none}li{list-style:none}table{border-collapse:collapse;border-spacing:0}h4,h5,h6{font-size:100%}button,input,optgroup,option,select,textarea{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;outline:0}pre{white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}body{line-height:24px;font:14px Helvetica Neue,Helvetica,PingFang SC,Tahoma,Arial,sans-serif}hr{height:1px;margin:10px 0;border:0;clear:both}a{color:#333;text-decoration:none}a:hover{color:#777}a cite{font-style:normal;*cursor:pointer}.layui-border-box,.layui-border-box *{box-sizing:border-box}.layui-box,.layui-box *{box-sizing:content-box}.layui-clear{clear:both;*zoom:1}.layui-clear:after{content:'\20';clear:both;*zoom:1;display:block;height:0}.layui-inline{*display:inline;*zoom:1}.layui-edge{display:inline-block;width:0;height:0;border-width:6px;border-style:dashed;border-color:transparent;overflow:hidden}.layui-edge-top{top:-4px;border-bottom-color:#999;border-bottom-style:solid}.layui-edge-right{border-left-color:#999;border-left-style:solid}.layui-edge-bottom{top:2px;border-top-color:#999;border-top-style:solid}.layui-edge-left{border-right-color:#999;border-right-style:solid}.layui-elip{overflow:hidden}.layui-disabled,.layui-disabled:hover{color:#d2d2d2!important;cursor:not-allowed!important}.layui-circle{border-radius:100%}.layui-show{display:block!important}.layui-hide{display:none!important}@font-face{font-family:layui-icon;src:url(../font/iconfont.eot?v=240);src:url(../font/iconfont.eot?v=240#iefix) format('embedded-opentype'),url(../font/iconfont.svg?v=240#iconfont) format('svg'),url(../font/iconfont.woff?v=240) format('woff'),url(../font/iconfont.ttf?v=240) format('truetype')}.layui-icon{font-family:layui-icon!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.layui-icon-reply-fill:before{content:"\e611"}.layui-icon-set-fill:before{content:"\e614"}.layui-icon-menu-fill:before{content:"\e60f"}.layui-icon-search:before{content:"\e615"}.layui-icon-share:before{content:"\e641"}.layui-icon-set-sm:before{content:"\e620"}.layui-icon-engine:before{content:"\e628"}.layui-icon-close:before{content:"\1006"}.layui-icon-close-fill:before{content:"\1007"}.layui-icon-chart-screen:before{content:"\e629"}.layui-icon-star:before{content:"\e600"}.layui-icon-circle-dot:before{content:"\e617"}.layui-icon-chat:before{content:"\e606"}.layui-icon-release:before{content:"\e609"}.layui-icon-list:before{content:"\e60a"}.layui-icon-chart:before{content:"\e62c"}.layui-icon-ok-circle:before{content:"\1005"}.layui-icon-layim-theme:before{content:"\e61b"}.layui-icon-table:before{content:"\e62d"}.layui-icon-right:before{content:"\e602"}.layui-icon-left:before{content:"\e603"}.layui-icon-cart-simple:before{content:"\e698"}.layui-icon-face-cry:before{content:"\e69c"}.layui-icon-face-smile:before{content:"\e6af"}.layui-icon-survey:before{content:"\e6b2"}.layui-icon-tree:before{content:"\e62e"}.layui-icon-upload-circle:before{content:"\e62f"}.layui-icon-add-circle:before{content:"\e61f"}.layui-icon-download-circle:before{content:"\e601"}.layui-icon-templeate-1:before{content:"\e630"}.layui-icon-util:before{content:"\e631"}.layui-icon-face-surprised:before{content:"\e664"}.layui-icon-edit:before{content:"\e642"}.layui-icon-speaker:before{content:"\e645"}.layui-icon-down:before{content:"\e61a"}.layui-icon-file:before{content:"\e621"}.layui-icon-layouts:before{content:"\e632"}.layui-icon-rate-half:before{content:"\e6c9"}.layui-icon-add-circle-fine:before{content:"\e608"}.layui-icon-prev-circle:before{content:"\e633"}.layui-icon-read:before{content:"\e705"}.layui-icon-404:before{content:"\e61c"}.layui-icon-carousel:before{content:"\e634"}.layui-icon-help:before{content:"\e607"}.layui-icon-code-circle:before{content:"\e635"}.layui-icon-water:before{content:"\e636"}.layui-icon-username:before{content:"\e66f"}.layui-icon-find-fill:before{content:"\e670"}.layui-icon-about:before{content:"\e60b"}.layui-icon-location:before{content:"\e715"}.layui-icon-up:before{content:"\e619"}.layui-icon-pause:before{content:"\e651"}.layui-icon-date:before{content:"\e637"}.layui-icon-layim-uploadfile:before{content:"\e61d"}.layui-icon-delete:before{content:"\e640"}.layui-icon-play:before{content:"\e652"}.layui-icon-top:before{content:"\e604"}.layui-icon-friends:before{content:"\e612"}.layui-icon-refresh-3:before{content:"\e9aa"}.layui-icon-ok:before{content:"\e605"}.layui-icon-layer:before{content:"\e638"}.layui-icon-face-smile-fine:before{content:"\e60c"}.layui-icon-dollar:before{content:"\e659"}.layui-icon-group:before{content:"\e613"}.layui-icon-layim-download:before{content:"\e61e"}.layui-icon-picture-fine:before{content:"\e60d"}.layui-icon-link:before{content:"\e64c"}.layui-icon-diamond:before{content:"\e735"}.layui-icon-log:before{content:"\e60e"}.layui-icon-rate-solid:before{content:"\e67a"}.layui-icon-fonts-del:before{content:"\e64f"}.layui-icon-unlink:before{content:"\e64d"}.layui-icon-fonts-clear:before{content:"\e639"}.layui-icon-triangle-r:before{content:"\e623"}.layui-icon-circle:before{content:"\e63f"}.layui-icon-radio:before{content:"\e643"}.layui-icon-align-center:before{content:"\e647"}.layui-icon-align-right:before{content:"\e648"}.layui-icon-align-left:before{content:"\e649"}.layui-icon-loading-1:before{content:"\e63e"}.layui-icon-return:before{content:"\e65c"}.layui-icon-fonts-strong:before{content:"\e62b"}.layui-icon-upload:before{content:"\e67c"}.layui-icon-dialogue:before{content:"\e63a"}.layui-icon-video:before{content:"\e6ed"}.layui-icon-headset:before{content:"\e6fc"}.layui-icon-cellphone-fine:before{content:"\e63b"}.layui-icon-add-1:before{content:"\e654"}.layui-icon-face-smile-b:before{content:"\e650"}.layui-icon-fonts-html:before{content:"\e64b"}.layui-icon-form:before{content:"\e63c"}.layui-icon-cart:before{content:"\e657"}.layui-icon-camera-fill:before{content:"\e65d"}.layui-icon-tabs:before{content:"\e62a"}.layui-icon-fonts-code:before{content:"\e64e"}.layui-icon-fire:before{content:"\e756"}.layui-icon-set:before{content:"\e716"}.layui-icon-fonts-u:before{content:"\e646"}.layui-icon-triangle-d:before{content:"\e625"}.layui-icon-tips:before{content:"\e702"}.layui-icon-picture:before{content:"\e64a"}.layui-icon-more-vertical:before{content:"\e671"}.layui-icon-flag:before{content:"\e66c"}.layui-icon-loading:before{content:"\e63d"}.layui-icon-fonts-i:before{content:"\e644"}.layui-icon-refresh-1:before{content:"\e666"}.layui-icon-rmb:before{content:"\e65e"}.layui-icon-home:before{content:"\e68e"}.layui-icon-user:before{content:"\e770"}.layui-icon-notice:before{content:"\e667"}.layui-icon-login-weibo:before{content:"\e675"}.layui-icon-voice:before{content:"\e688"}.layui-icon-upload-drag:before{content:"\e681"}.layui-icon-login-qq:before{content:"\e676"}.layui-icon-snowflake:before{content:"\e6b1"}.layui-icon-file-b:before{content:"\e655"}.layui-icon-template:before{content:"\e663"}.layui-icon-auz:before{content:"\e672"}.layui-icon-console:before{content:"\e665"}.layui-icon-app:before{content:"\e653"}.layui-icon-prev:before{content:"\e65a"}.layui-icon-website:before{content:"\e7ae"}.layui-icon-next:before{content:"\e65b"}.layui-icon-component:before{content:"\e857"}.layui-icon-more:before{content:"\e65f"}.layui-icon-login-wechat:before{content:"\e677"}.layui-icon-shrink-right:before{content:"\e668"}.layui-icon-spread-left:before{content:"\e66b"}.layui-icon-camera:before{content:"\e660"}.layui-icon-note:before{content:"\e66e"}.layui-icon-refresh:before{content:"\e669"}.layui-icon-female:before{content:"\e661"}.layui-icon-male:before{content:"\e662"}.layui-icon-password:before{content:"\e673"}.layui-icon-senior:before{content:"\e674"}.layui-icon-theme:before{content:"\e66a"}.layui-icon-tread:before{content:"\e6c5"}.layui-icon-praise:before{content:"\e6c6"}.layui-icon-star-fill:before{content:"\e658"}.layui-icon-rate:before{content:"\e67b"}.layui-icon-template-1:before{content:"\e656"}.layui-icon-vercode:before{content:"\e679"}.layui-icon-cellphone:before{content:"\e678"}.layui-icon-screen-full:before{content:"\e622"}.layui-icon-screen-restore:before{content:"\e758"}.layui-icon-cols:before{content:"\e610"}.layui-icon-export:before{content:"\e67d"}.layui-icon-print:before{content:"\e66d"}.layui-icon-slider:before{content:"\e714"}.layui-main{width:1140px;margin:0 auto}.layui-header{z-index:1000;height:60px}.layui-header a:hover{transition:all .5s;-webkit-transition:all .5s}.layui-side{position:fixed;left:0;top:0;bottom:0;z-index:999;width:200px;overflow-x:hidden}.layui-side-scroll{position:relative;width:220px;height:100%;overflow-x:hidden}.layui-body{position:absolute;left:200px;right:0;top:0;bottom:0;z-index:998;width:auto;overflow:hidden;overflow-y:auto;box-sizing:border-box}.layui-layout-body{overflow:hidden}.layui-layout-admin .layui-header{background-color:#23262E}.layui-layout-admin .layui-side{top:60px;width:200px;overflow-x:hidden}.layui-layout-admin .layui-body{top:60px;bottom:44px}.layui-layout-admin .layui-main{width:auto;margin:0 15px}.layui-layout-admin .layui-footer{position:fixed;left:200px;right:0;bottom:0;height:44px;line-height:44px;padding:0 15px;background-color:#eee}.layui-layout-admin .layui-logo{position:absolute;left:0;top:0;width:200px;height:100%;line-height:60px;text-align:center;color:#009688;font-size:16px}.layui-layout-admin .layui-header .layui-nav{background:0 0}.layui-layout-left{position:absolute!important;left:200px;top:0}.layui-layout-right{position:absolute!important;right:0;top:0}.layui-container{position:relative;margin:0 auto;padding:0 15px;box-sizing:border-box}.layui-fluid{position:relative;margin:0 auto;padding:0 15px}.layui-row:after,.layui-row:before{content:'';display:block;clear:both}.layui-col-lg1,.layui-col-lg10,.layui-col-lg11,.layui-col-lg12,.layui-col-lg2,.layui-col-lg3,.layui-col-lg4,.layui-col-lg5,.layui-col-lg6,.layui-col-lg7,.layui-col-lg8,.layui-col-lg9,.layui-col-md1,.layui-col-md10,.layui-col-md11,.layui-col-md12,.layui-col-md2,.layui-col-md3,.layui-col-md4,.layui-col-md5,.layui-col-md6,.layui-col-md7,.layui-col-md8,.layui-col-md9,.layui-col-sm1,.layui-col-sm10,.layui-col-sm11,.layui-col-sm12,.layui-col-sm2,.layui-col-sm3,.layui-col-sm4,.layui-col-sm5,.layui-col-sm6,.layui-col-sm7,.layui-col-sm8,.layui-col-sm9,.layui-col-xs1,.layui-col-xs10,.layui-col-xs11,.layui-col-xs12,.layui-col-xs2,.layui-col-xs3,.layui-col-xs4,.layui-col-xs5,.layui-col-xs6,.layui-col-xs7,.layui-col-xs8,.layui-col-xs9{position:relative;display:block;box-sizing:border-box}.layui-col-xs1,.layui-col-xs10,.layui-col-xs11,.layui-col-xs12,.layui-col-xs2,.layui-col-xs3,.layui-col-xs4,.layui-col-xs5,.layui-col-xs6,.layui-col-xs7,.layui-col-xs8,.layui-col-xs9{float:left}.layui-col-xs1{width:8.33333333%}.layui-col-xs2{width:16.66666667%}.layui-col-xs3{width:25%}.layui-col-xs4{width:33.33333333%}.layui-col-xs5{width:41.66666667%}.layui-col-xs6{width:50%}.layui-col-xs7{width:58.33333333%}.layui-col-xs8{width:66.66666667%}.layui-col-xs9{width:75%}.layui-col-xs10{width:83.33333333%}.layui-col-xs11{width:91.66666667%}.layui-col-xs12{width:100%}.layui-col-xs-offset1{margin-left:8.33333333%}.layui-col-xs-offset2{margin-left:16.66666667%}.layui-col-xs-offset3{margin-left:25%}.layui-col-xs-offset4{margin-left:33.33333333%}.layui-col-xs-offset5{margin-left:41.66666667%}.layui-col-xs-offset6{margin-left:50%}.layui-col-xs-offset7{margin-left:58.33333333%}.layui-col-xs-offset8{margin-left:66.66666667%}.layui-col-xs-offset9{margin-left:75%}.layui-col-xs-offset10{margin-left:83.33333333%}.layui-col-xs-offset11{margin-left:91.66666667%}.layui-col-xs-offset12{margin-left:100%}@media screen and (max-width:768px){.layui-hide-xs{display:none!important}.layui-show-xs-block{display:block!important}.layui-show-xs-inline{display:inline!important}.layui-show-xs-inline-block{display:inline-block!important}}@media screen and (min-width:768px){.layui-container{width:750px}.layui-hide-sm{display:none!important}.layui-show-sm-block{display:block!important}.layui-show-sm-inline{display:inline!important}.layui-show-sm-inline-block{display:inline-block!important}.layui-col-sm1,.layui-col-sm10,.layui-col-sm11,.layui-col-sm12,.layui-col-sm2,.layui-col-sm3,.layui-col-sm4,.layui-col-sm5,.layui-col-sm6,.layui-col-sm7,.layui-col-sm8,.layui-col-sm9{float:left}.layui-col-sm1{width:8.33333333%}.layui-col-sm2{width:16.66666667%}.layui-col-sm3{width:25%}.layui-col-sm4{width:33.33333333%}.layui-col-sm5{width:41.66666667%}.layui-col-sm6{width:50%}.layui-col-sm7{width:58.33333333%}.layui-col-sm8{width:66.66666667%}.layui-col-sm9{width:75%}.layui-col-sm10{width:83.33333333%}.layui-col-sm11{width:91.66666667%}.layui-col-sm12{width:100%}.layui-col-sm-offset1{margin-left:8.33333333%}.layui-col-sm-offset2{margin-left:16.66666667%}.layui-col-sm-offset3{margin-left:25%}.layui-col-sm-offset4{margin-left:33.33333333%}.layui-col-sm-offset5{margin-left:41.66666667%}.layui-col-sm-offset6{margin-left:50%}.layui-col-sm-offset7{margin-left:58.33333333%}.layui-col-sm-offset8{margin-left:66.66666667%}.layui-col-sm-offset9{margin-left:75%}.layui-col-sm-offset10{margin-left:83.33333333%}.layui-col-sm-offset11{margin-left:91.66666667%}.layui-col-sm-offset12{margin-left:100%}}@media screen and (min-width:992px){.layui-container{width:970px}.layui-hide-md{display:none!important}.layui-show-md-block{display:block!important}.layui-show-md-inline{display:inline!important}.layui-show-md-inline-block{display:inline-block!important}.layui-col-md1,.layui-col-md10,.layui-col-md11,.layui-col-md12,.layui-col-md2,.layui-col-md3,.layui-col-md4,.layui-col-md5,.layui-col-md6,.layui-col-md7,.layui-col-md8,.layui-col-md9{float:left}.layui-col-md1{width:8.33333333%}.layui-col-md2{width:16.66666667%}.layui-col-md3{width:25%}.layui-col-md4{width:33.33333333%}.layui-col-md5{width:41.66666667%}.layui-col-md6{width:50%}.layui-col-md7{width:58.33333333%}.layui-col-md8{width:66.66666667%}.layui-col-md9{width:75%}.layui-col-md10{width:83.33333333%}.layui-col-md11{width:91.66666667%}.layui-col-md12{width:100%}.layui-col-md-offset1{margin-left:8.33333333%}.layui-col-md-offset2{margin-left:16.66666667%}.layui-col-md-offset3{margin-left:25%}.layui-col-md-offset4{margin-left:33.33333333%}.layui-col-md-offset5{margin-left:41.66666667%}.layui-col-md-offset6{margin-left:50%}.layui-col-md-offset7{margin-left:58.33333333%}.layui-col-md-offset8{margin-left:66.66666667%}.layui-col-md-offset9{margin-left:75%}.layui-col-md-offset10{margin-left:83.33333333%}.layui-col-md-offset11{margin-left:91.66666667%}.layui-col-md-offset12{margin-left:100%}}@media screen and (min-width:1200px){.layui-container{width:1170px}.layui-hide-lg{display:none!important}.layui-show-lg-block{display:block!important}.layui-show-lg-inline{display:inline!important}.layui-show-lg-inline-block{display:inline-block!important}.layui-col-lg1,.layui-col-lg10,.layui-col-lg11,.layui-col-lg12,.layui-col-lg2,.layui-col-lg3,.layui-col-lg4,.layui-col-lg5,.layui-col-lg6,.layui-col-lg7,.layui-col-lg8,.layui-col-lg9{float:left}.layui-col-lg1{width:8.33333333%}.layui-col-lg2{width:16.66666667%}.layui-col-lg3{width:25%}.layui-col-lg4{width:33.33333333%}.layui-col-lg5{width:41.66666667%}.layui-col-lg6{width:50%}.layui-col-lg7{width:58.33333333%}.layui-col-lg8{width:66.66666667%}.layui-col-lg9{width:75%}.layui-col-lg10{width:83.33333333%}.layui-col-lg11{width:91.66666667%}.layui-col-lg12{width:100%}.layui-col-lg-offset1{margin-left:8.33333333%}.layui-col-lg-offset2{margin-left:16.66666667%}.layui-col-lg-offset3{margin-left:25%}.layui-col-lg-offset4{margin-left:33.33333333%}.layui-col-lg-offset5{margin-left:41.66666667%}.layui-col-lg-offset6{margin-left:50%}.layui-col-lg-offset7{margin-left:58.33333333%}.layui-col-lg-offset8{margin-left:66.66666667%}.layui-col-lg-offset9{margin-left:75%}.layui-col-lg-offset10{margin-left:83.33333333%}.layui-col-lg-offset11{margin-left:91.66666667%}.layui-col-lg-offset12{margin-left:100%}}.layui-col-space1{margin:-.5px}.layui-col-space1>*{padding:.5px}.layui-col-space3{margin:-1.5px}.layui-col-space3>*{padding:1.5px}.layui-col-space5{margin:-2.5px}.layui-col-space5>*{padding:2.5px}.layui-col-space8{margin:-3.5px}.layui-col-space8>*{padding:3.5px}.layui-col-space10{margin:-5px}.layui-col-space10>*{padding:5px}.layui-col-space12{margin:-6px}.layui-col-space12>*{padding:6px}.layui-col-space15{margin:-7.5px}.layui-col-space15>*{padding:7.5px}.layui-col-space18{margin:-9px}.layui-col-space18>*{padding:9px}.layui-col-space20{margin:-10px}.layui-col-space20>*{padding:10px}.layui-col-space22{margin:-11px}.layui-col-space22>*{padding:11px}.layui-col-space25{margin:-12.5px}.layui-col-space25>*{padding:12.5px}.layui-col-space30{margin:-15px}.layui-col-space30>*{padding:15px}.layui-btn,.layui-input,.layui-select,.layui-textarea,.layui-upload-button{outline:0;-webkit-appearance:none;transition:all .3s;-webkit-transition:all .3s;box-sizing:border-box}.layui-elem-quote{margin-bottom:10px;padding:15px;line-height:22px;border-left:5px solid #009688;border-radius:0 2px 2px 0;background-color:#f2f2f2}.layui-quote-nm{border-style:solid;border-width:1px 1px 1px 5px;background:0 0}.layui-elem-field{margin-bottom:10px;padding:0;border-width:1px;border-style:solid}.layui-elem-field legend{margin-left:20px;padding:0 10px;font-size:20px;font-weight:300}.layui-field-title{margin:10px 0 20px;border-width:1px 0 0}.layui-field-box{padding:10px 15px}.layui-field-title .layui-field-box{padding:10px 0}.layui-progress{position:relative;height:6px;border-radius:20px;background-color:#e2e2e2}.layui-progress-bar{position:absolute;left:0;top:0;width:0;max-width:100%;height:6px;border-radius:20px;text-align:right;background-color:#5FB878;transition:all .3s;-webkit-transition:all .3s}.layui-progress-big,.layui-progress-big .layui-progress-bar{height:18px;line-height:18px}.layui-progress-text{position:relative;top:-20px;line-height:18px;font-size:12px;color:#666}.layui-progress-big .layui-progress-text{position:static;padding:0 10px;color:#fff}.layui-collapse{border-width:1px;border-style:solid;border-radius:2px}.layui-colla-content,.layui-colla-item{border-top-width:1px;border-top-style:solid}.layui-colla-item:first-child{border-top:none}.layui-colla-title{position:relative;height:42px;line-height:42px;padding:0 15px 0 35px;color:#333;background-color:#f2f2f2;cursor:pointer;font-size:14px;overflow:hidden}.layui-colla-content{display:none;padding:10px 15px;line-height:22px;color:#666}.layui-colla-icon{position:absolute;left:15px;top:0;font-size:14px}.layui-card{margin-bottom:15px;border-radius:2px;background-color:#fff;box-shadow:0 1px 2px 0 rgba(0,0,0,.05)}.layui-card:last-child{margin-bottom:0}.layui-card-header{position:relative;height:42px;line-height:42px;padding:0 15px;border-bottom:1px solid #f6f6f6;color:#333;border-radius:2px 2px 0 0;font-size:14px}.layui-bg-black,.layui-bg-blue,.layui-bg-cyan,.layui-bg-green,.layui-bg-orange,.layui-bg-red{color:#fff!important}.layui-card-body{position:relative;padding:10px 15px;line-height:24px}.layui-card-body[pad15]{padding:15px}.layui-card-body[pad20]{padding:20px}.layui-card-body .layui-table{margin:5px 0}.layui-card .layui-tab{margin:0}.layui-panel-window{position:relative;padding:15px;border-radius:0;border-top:5px solid #E6E6E6;background-color:#fff}.layui-auxiliar-moving{position:fixed;left:0;right:0;top:0;bottom:0;width:100%;height:100%;background:0 0;z-index:9999999999}.layui-form-label,.layui-form-mid,.layui-form-select,.layui-input-block,.layui-input-inline,.layui-textarea{position:relative}.layui-bg-red{background-color:#FF5722!important}.layui-bg-orange{background-color:#FFB800!important}.layui-bg-green{background-color:#009688!important}.layui-bg-cyan{background-color:#2F4056!important}.layui-bg-blue{background-color:#1E9FFF!important}.layui-bg-black{background-color:#393D49!important}.layui-bg-gray{background-color:#eee!important;color:#666!important}.layui-badge-rim,.layui-colla-content,.layui-colla-item,.layui-collapse,.layui-elem-field,.layui-form-pane .layui-form-item[pane],.layui-form-pane .layui-form-label,.layui-input,.layui-layedit,.layui-layedit-tool,.layui-quote-nm,.layui-select,.layui-tab-bar,.layui-tab-card,.layui-tab-title,.layui-tab-title .layui-this:after,.layui-textarea{border-color:#e6e6e6}.layui-timeline-item:before,hr{background-color:#e6e6e6}.layui-text{line-height:22px;font-size:14px;color:#666}.layui-text h1,.layui-text h2,.layui-text h3{font-weight:500;color:#333}.layui-text h1{font-size:30px}.layui-text h2{font-size:24px}.layui-text h3{font-size:18px}.layui-text a:not(.layui-btn){color:#01AAED}.layui-text a:not(.layui-btn):hover{text-decoration:underline}.layui-text ul{padding:5px 0 5px 15px}.layui-text ul li{margin-top:5px;list-style-type:disc}.layui-text em,.layui-word-aux{color:#999!important;padding:0 5px!important}.layui-btn{display:inline-block;height:38px;line-height:38px;padding:0 18px;background-color:#009688;color:#fff;white-space:nowrap;text-align:center;font-size:14px;border:none;border-radius:2px;cursor:pointer}.layui-btn:hover{opacity:.8;filter:alpha(opacity=80);color:#fff}.layui-btn:active{opacity:1;filter:alpha(opacity=100)}.layui-btn+.layui-btn{margin-left:10px}.layui-btn-container{font-size:0}.layui-btn-container .layui-btn{margin-right:10px;margin-bottom:10px}.layui-btn-container .layui-btn+.layui-btn{margin-left:0}.layui-table .layui-btn-container .layui-btn{margin-bottom:9px}.layui-btn-radius{border-radius:100px}.layui-btn .layui-icon{margin-right:3px;font-size:18px;vertical-align:bottom;vertical-align:middle\9}.layui-btn-primary{border:1px solid #C9C9C9;background-color:#fff;color:#555}.layui-btn-primary:hover{border-color:#009688;color:#333}.layui-btn-normal{background-color:#1E9FFF}.layui-btn-warm{background-color:#FFB800}.layui-btn-danger{background-color:#FF5722}.layui-btn-disabled,.layui-btn-disabled:active,.layui-btn-disabled:hover{border:1px solid #e6e6e6;background-color:#FBFBFB;color:#C9C9C9;cursor:not-allowed;opacity:1}.layui-btn-lg{height:44px;line-height:44px;padding:0 25px;font-size:16px}.layui-btn-sm{height:30px;line-height:30px;padding:0 10px;font-size:12px}.layui-btn-sm i{font-size:16px!important}.layui-btn-xs{height:22px;line-height:22px;padding:0 5px;font-size:12px}.layui-btn-xs i{font-size:14px!important}.layui-btn-group{display:inline-block;vertical-align:middle;font-size:0}.layui-btn-group .layui-btn{margin-left:0!important;margin-right:0!important;border-left:1px solid rgba(255,255,255,.5);border-radius:0}.layui-btn-group .layui-btn-primary{border-left:none}.layui-btn-group .layui-btn-primary:hover{border-color:#C9C9C9;color:#009688}.layui-btn-group .layui-btn:first-child{border-left:none;border-radius:2px 0 0 2px}.layui-btn-group .layui-btn-primary:first-child{border-left:1px solid #c9c9c9}.layui-btn-group .layui-btn:last-child{border-radius:0 2px 2px 0}.layui-btn-group .layui-btn+.layui-btn{margin-left:0}.layui-btn-group+.layui-btn-group{margin-left:10px}.layui-btn-fluid{width:100%}.layui-input,.layui-select,.layui-textarea{height:38px;line-height:1.3;line-height:38px\9;border-width:1px;border-style:solid;background-color:#fff;border-radius:2px}.layui-input::-webkit-input-placeholder,.layui-select::-webkit-input-placeholder,.layui-textarea::-webkit-input-placeholder{line-height:1.3}.layui-input,.layui-textarea{display:block;width:100%;padding-left:10px}.layui-input:hover,.layui-textarea:hover{border-color:#D2D2D2!important}.layui-input:focus,.layui-textarea:focus{border-color:#C9C9C9!important}.layui-textarea{min-height:100px;height:auto;line-height:20px;padding:6px 10px;resize:vertical}.layui-select{padding:0 10px}.layui-form input[type=checkbox],.layui-form input[type=radio],.layui-form select{display:none}.layui-form [lay-ignore]{display:initial}.layui-form-item{margin-bottom:15px;clear:both;*zoom:1}.layui-form-item:after{content:'\20';clear:both;*zoom:1;display:block;height:0}.layui-form-label{float:left;display:block;padding:9px 15px;width:80px;font-weight:400;line-height:20px;text-align:right}.layui-form-label-col{display:block;float:none;padding:9px 0;line-height:20px;text-align:left}.layui-form-item .layui-inline{margin-bottom:5px;margin-right:10px}.layui-input-block{margin-left:110px;min-height:36px}.layui-input-inline{display:inline-block;vertical-align:middle}.layui-form-item .layui-input-inline{float:left;width:190px;margin-right:10px}.layui-form-text .layui-input-inline{width:auto}.layui-form-mid{float:left;display:block;padding:9px 0!important;line-height:20px;margin-right:10px}.layui-form-danger+.layui-form-select .layui-input,.layui-form-danger:focus{border-color:#FF5722!important}.layui-form-select .layui-input{padding-right:30px;cursor:pointer}.layui-form-select .layui-edge{position:absolute;right:10px;top:50%;margin-top:-3px;cursor:pointer;border-width:6px;border-top-color:#c2c2c2;border-top-style:solid;transition:all .3s;-webkit-transition:all .3s}.layui-form-select dl{display:none;position:absolute;left:0;top:42px;padding:5px 0;z-index:899;min-width:100%;border:1px solid #d2d2d2;max-height:300px;overflow-y:auto;background-color:#fff;border-radius:2px;box-shadow:0 2px 4px rgba(0,0,0,.12);box-sizing:border-box}.layui-form-select dl dd,.layui-form-select dl dt{padding:0 10px;line-height:36px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.layui-form-select dl dt{font-size:12px;color:#999}.layui-form-select dl dd{cursor:pointer}.layui-form-select dl dd:hover{background-color:#f2f2f2;-webkit-transition:.5s all;transition:.5s all}.layui-form-select .layui-select-group dd{padding-left:20px}.layui-form-select dl dd.layui-select-tips{padding-left:10px!important;color:#999}.layui-form-select dl dd.layui-this{background-color:#5FB878;color:#fff}.layui-form-checkbox,.layui-form-select dl dd.layui-disabled{background-color:#fff}.layui-form-selected dl{display:block}.layui-form-checkbox,.layui-form-checkbox *,.layui-form-switch{display:inline-block;vertical-align:middle}.layui-form-selected .layui-edge{margin-top:-9px;-webkit-transform:rotate(180deg);transform:rotate(180deg);margin-top:-3px\9}:root .layui-form-selected .layui-edge{margin-top:-9px\0/IE9}.layui-form-selectup dl{top:auto;bottom:42px}.layui-select-none{margin:5px 0;text-align:center;color:#999}.layui-select-disabled .layui-disabled{border-color:#eee!important}.layui-select-disabled .layui-edge{border-top-color:#d2d2d2}.layui-form-checkbox{position:relative;height:30px;line-height:30px;margin-right:10px;padding-right:30px;cursor:pointer;font-size:0;-webkit-transition:.1s linear;transition:.1s linear;box-sizing:border-box}.layui-form-checkbox span{padding:0 10px;height:100%;font-size:14px;border-radius:2px 0 0 2px;background-color:#d2d2d2;color:#fff;overflow:hidden}.layui-form-checkbox:hover span{background-color:#c2c2c2}.layui-form-checkbox i{position:absolute;right:0;top:0;width:30px;height:28px;border:1px solid #d2d2d2;border-left:none;border-radius:0 2px 2px 0;color:#fff;font-size:20px;text-align:center}.layui-form-checkbox:hover i{border-color:#c2c2c2;color:#c2c2c2}.layui-form-checked,.layui-form-checked:hover{border-color:#5FB878}.layui-form-checked span,.layui-form-checked:hover span{background-color:#5FB878}.layui-form-checked i,.layui-form-checked:hover i{color:#5FB878}.layui-form-item .layui-form-checkbox{margin-top:4px}.layui-form-checkbox[lay-skin=primary]{height:auto!important;line-height:normal!important;min-width:18px;min-height:18px;border:none!important;margin-right:0;padding-left:28px;padding-right:0;background:0 0}.layui-form-checkbox[lay-skin=primary] span{padding-left:0;padding-right:15px;line-height:18px;background:0 0;color:#666}.layui-form-checkbox[lay-skin=primary] i{right:auto;left:0;width:16px;height:16px;line-height:16px;border:1px solid #d2d2d2;font-size:12px;border-radius:2px;background-color:#fff;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-checkbox[lay-skin=primary]:hover i{border-color:#5FB878;color:#fff}.layui-form-checked[lay-skin=primary] i{border-color:#5FB878;background-color:#5FB878;color:#fff}.layui-checkbox-disbaled[lay-skin=primary] span{background:0 0!important;color:#c2c2c2}.layui-checkbox-disbaled[lay-skin=primary]:hover i{border-color:#d2d2d2}.layui-form-item .layui-form-checkbox[lay-skin=primary]{margin-top:10px}.layui-form-switch{position:relative;height:22px;line-height:22px;min-width:35px;padding:0 5px;margin-top:8px;border:1px solid #d2d2d2;border-radius:20px;cursor:pointer;background-color:#fff;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-switch i{position:absolute;left:5px;top:3px;width:16px;height:16px;border-radius:20px;background-color:#d2d2d2;-webkit-transition:.1s linear;transition:.1s linear}.layui-form-switch em{position:relative;top:0;width:25px;margin-left:21px;padding:0!important;text-align:center!important;color:#999!important;font-style:normal!important;font-size:12px}.layui-form-onswitch{border-color:#5FB878;background-color:#5FB878}.layui-checkbox-disbaled,.layui-checkbox-disbaled i{border-color:#e2e2e2!important}.layui-form-onswitch i{left:100%;margin-left:-21px;background-color:#fff}.layui-form-onswitch em{margin-left:5px;margin-right:21px;color:#fff!important}.layui-checkbox-disbaled span{background-color:#e2e2e2!important}.layui-checkbox-disbaled:hover i{color:#fff!important}[lay-radio]{display:none}.layui-form-radio,.layui-form-radio *{display:inline-block;vertical-align:middle}.layui-form-radio{line-height:28px;margin:6px 10px 0 0;padding-right:10px;cursor:pointer;font-size:0}.layui-form-radio *{font-size:14px}.layui-form-radio>i{margin-right:8px;font-size:22px;color:#c2c2c2}.layui-form-radio>i:hover,.layui-form-radioed>i{color:#5FB878}.layui-radio-disbaled>i{color:#e2e2e2!important}.layui-form-pane .layui-form-label{width:110px;padding:8px 15px;height:38px;line-height:20px;border-width:1px;border-style:solid;border-radius:2px 0 0 2px;text-align:center;background-color:#FBFBFB;overflow:hidden;box-sizing:border-box}.layui-form-pane .layui-input-inline{margin-left:-1px}.layui-form-pane .layui-input-block{margin-left:110px;left:-1px}.layui-form-pane .layui-input{border-radius:0 2px 2px 0}.layui-form-pane .layui-form-text .layui-form-label{float:none;width:100%;border-radius:2px;box-sizing:border-box;text-align:left}.layui-form-pane .layui-form-text .layui-input-inline{display:block;margin:0;top:-1px;clear:both}.layui-form-pane .layui-form-text .layui-input-block{margin:0;left:0;top:-1px}.layui-form-pane .layui-form-text .layui-textarea{min-height:100px;border-radius:0 0 2px 2px}.layui-form-pane .layui-form-checkbox{margin:4px 0 4px 10px}.layui-form-pane .layui-form-radio,.layui-form-pane .layui-form-switch{margin-top:6px;margin-left:10px}.layui-form-pane .layui-form-item[pane]{position:relative;border-width:1px;border-style:solid}.layui-form-pane .layui-form-item[pane] .layui-form-label{position:absolute;left:0;top:0;height:100%;border-width:0 1px 0 0}.layui-form-pane .layui-form-item[pane] .layui-input-inline{margin-left:110px}@media screen and (max-width:450px){.layui-form-item .layui-form-label{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-form-item .layui-inline{display:block;margin-right:0;margin-bottom:20px;clear:both}.layui-form-item .layui-inline:after{content:'\20';clear:both;display:block;height:0}.layui-form-item .layui-input-inline{display:block;float:none;left:-3px;width:auto;margin:0 0 10px 112px}.layui-form-item .layui-input-inline+.layui-form-mid{margin-left:110px;top:-5px;padding:0}.layui-form-item .layui-form-checkbox{margin-right:5px;margin-bottom:5px}}.layui-layedit{border-width:1px;border-style:solid;border-radius:2px}.layui-layedit-tool{padding:3px 5px;border-bottom-width:1px;border-bottom-style:solid;font-size:0}.layedit-tool-fixed{position:fixed;top:0;border-top:1px solid #e2e2e2}.layui-layedit-tool .layedit-tool-mid,.layui-layedit-tool .layui-icon{display:inline-block;vertical-align:middle;text-align:center;font-size:14px}.layui-layedit-tool .layui-icon{position:relative;width:32px;height:30px;line-height:30px;margin:3px 5px;color:#777;cursor:pointer;border-radius:2px}.layui-layedit-tool .layui-icon:hover{color:#393D49}.layui-layedit-tool .layui-icon:active{color:#000}.layui-layedit-tool .layedit-tool-active{background-color:#e2e2e2;color:#000}.layui-layedit-tool .layui-disabled,.layui-layedit-tool .layui-disabled:hover{color:#d2d2d2;cursor:not-allowed}.layui-layedit-tool .layedit-tool-mid{width:1px;height:18px;margin:0 10px;background-color:#d2d2d2}.layedit-tool-html{width:50px!important;font-size:30px!important}.layedit-tool-b,.layedit-tool-code,.layedit-tool-help{font-size:16px!important}.layedit-tool-d,.layedit-tool-face,.layedit-tool-image,.layedit-tool-unlink{font-size:18px!important}.layedit-tool-image input{position:absolute;font-size:0;left:0;top:0;width:100%;height:100%;opacity:.01;filter:Alpha(opacity=1);cursor:pointer}.layui-layedit-iframe iframe{display:block;width:100%}#LAY_layedit_code{overflow:hidden}.layui-laypage{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;margin:10px 0;font-size:0}.layui-laypage>a:first-child,.layui-laypage>a:first-child em{border-radius:2px 0 0 2px}.layui-laypage>a:last-child,.layui-laypage>a:last-child em{border-radius:0 2px 2px 0}.layui-laypage>:first-child{margin-left:0!important}.layui-laypage>:last-child{margin-right:0!important}.layui-laypage a,.layui-laypage button,.layui-laypage input,.layui-laypage select,.layui-laypage span{border:1px solid #e2e2e2}.layui-laypage a,.layui-laypage span{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;padding:0 15px;height:28px;line-height:28px;margin:0 -1px 5px 0;background-color:#fff;color:#333;font-size:12px}.layui-flow-more a *,.layui-laypage input,.layui-table-view select[lay-ignore]{display:inline-block}.layui-laypage a:hover{color:#009688}.layui-laypage em{font-style:normal}.layui-laypage .layui-laypage-spr{color:#999;font-weight:700}.layui-laypage a{text-decoration:none}.layui-laypage .layui-laypage-curr{position:relative}.layui-laypage .layui-laypage-curr em{position:relative;color:#fff}.layui-laypage .layui-laypage-curr .layui-laypage-em{position:absolute;left:-1px;top:-1px;padding:1px;width:100%;height:100%;background-color:#009688}.layui-laypage-em{border-radius:2px}.layui-laypage-next em,.layui-laypage-prev em{font-family:Sim sun;font-size:16px}.layui-laypage .layui-laypage-count,.layui-laypage .layui-laypage-limits,.layui-laypage .layui-laypage-refresh,.layui-laypage .layui-laypage-skip{margin-left:10px;margin-right:10px;padding:0;border:none}.layui-laypage .layui-laypage-limits,.layui-laypage .layui-laypage-refresh{vertical-align:top}.layui-laypage .layui-laypage-refresh i{font-size:18px;cursor:pointer}.layui-laypage select{height:22px;padding:3px;border-radius:2px;cursor:pointer}.layui-laypage .layui-laypage-skip{height:30px;line-height:30px;color:#999}.layui-laypage button,.layui-laypage input{height:30px;line-height:30px;border-radius:2px;vertical-align:top;background-color:#fff;box-sizing:border-box}.layui-laypage input{width:40px;margin:0 10px;padding:0 3px;text-align:center}.layui-laypage input:focus,.layui-laypage select:focus{border-color:#009688!important}.layui-laypage button{margin-left:10px;padding:0 10px;cursor:pointer}.layui-table,.layui-table-view{margin:10px 0}.layui-flow-more{margin:10px 0;text-align:center;color:#999;font-size:14px}.layui-flow-more a{height:32px;line-height:32px}.layui-flow-more a *{vertical-align:top}.layui-flow-more a cite{padding:0 20px;border-radius:3px;background-color:#eee;color:#333;font-style:normal}.layui-flow-more a cite:hover{opacity:.8}.layui-flow-more a i{font-size:30px;color:#737383}.layui-table{width:100%;background-color:#fff;color:#666}.layui-table tr{transition:all .3s;-webkit-transition:all .3s}.layui-table th{text-align:left;font-weight:400}.layui-table tbody tr:hover,.layui-table thead tr,.layui-table-click,.layui-table-header,.layui-table-hover,.layui-table-mend,.layui-table-patch,.layui-table-tool,.layui-table-total,.layui-table-total tr,.layui-table[lay-even] tr:nth-child(even){background-color:#f2f2f2}.layui-table td,.layui-table th,.layui-table-col-set,.layui-table-fixed-r,.layui-table-grid-down,.layui-table-header,.layui-table-page,.layui-table-tips-main,.layui-table-tool,.layui-table-total,.layui-table-view,.layui-table[lay-skin=line],.layui-table[lay-skin=row]{border-width:1px;border-style:solid;border-color:#e6e6e6}.layui-table td,.layui-table th{position:relative;padding:9px 15px;min-height:20px;line-height:20px;font-size:14px}.layui-table[lay-skin=line] td,.layui-table[lay-skin=line] th{border-width:0 0 1px}.layui-table[lay-skin=row] td,.layui-table[lay-skin=row] th{border-width:0 1px 0 0}.layui-table[lay-skin=nob] td,.layui-table[lay-skin=nob] th{border:none}.layui-table img{max-width:100px}.layui-table[lay-size=lg] td,.layui-table[lay-size=lg] th{padding:15px 30px}.layui-table-view .layui-table[lay-size=lg] .layui-table-cell{height:40px;line-height:40px}.layui-table[lay-size=sm] td,.layui-table[lay-size=sm] th{font-size:12px;padding:5px 10px}.layui-table-view .layui-table[lay-size=sm] .layui-table-cell{height:20px;line-height:20px}.layui-table[lay-data]{display:none}.layui-table-box{position:relative;overflow:hidden}.layui-table-view .layui-table{position:relative;width:auto;margin:0}.layui-table-view .layui-table[lay-skin=line]{border-width:0 1px 0 0}.layui-table-view .layui-table[lay-skin=row]{border-width:0 0 1px}.layui-table-view .layui-table td,.layui-table-view .layui-table th{padding:5px 0;border-top:none;border-left:none}.layui-table-view .layui-table th.layui-unselect .layui-table-cell span{cursor:pointer}.layui-table-view .layui-table td{cursor:default}.layui-table-view .layui-form-checkbox[lay-skin=primary] i{width:18px;height:18px}.layui-table-view .layui-form-radio{line-height:0;padding:0}.layui-table-view .layui-form-radio>i{margin:0;font-size:20px}.layui-table-init{position:absolute;left:0;top:0;width:100%;height:100%;text-align:center;z-index:110}.layui-table-init .layui-icon{position:absolute;left:50%;top:50%;margin:-15px 0 0 -15px;font-size:30px;color:#c2c2c2}.layui-table-header{border-width:0 0 1px;overflow:hidden}.layui-table-header .layui-table{margin-bottom:-1px}.layui-table-tool .layui-inline[lay-event]{position:relative;width:26px;height:26px;padding:5px;line-height:16px;margin-right:10px;text-align:center;color:#333;border:1px solid #ccc;cursor:pointer;-webkit-transition:.5s all;transition:.5s all}.layui-table-tool .layui-inline[lay-event]:hover{border:1px solid #999}.layui-table-tool-temp{padding-right:120px}.layui-table-tool-self{position:absolute;right:17px;top:10px}.layui-table-tool .layui-table-tool-self .layui-inline[lay-event]{margin:0 0 0 10px}.layui-table-tool-panel{position:absolute;top:29px;left:-1px;padding:5px 0;min-width:150px;min-height:40px;border:1px solid #d2d2d2;text-align:left;overflow-y:auto;background-color:#fff;box-shadow:0 2px 4px rgba(0,0,0,.12)}.layui-table-cell,.layui-table-tool-panel li{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.layui-table-tool-panel li{padding:0 10px;line-height:30px;-webkit-transition:.5s all;transition:.5s all}.layui-table-tool-panel li .layui-form-checkbox[lay-skin=primary]{width:100%;padding-left:28px}.layui-table-tool-panel li:hover{background-color:#f2f2f2}.layui-table-tool-panel li .layui-form-checkbox[lay-skin=primary] i{position:absolute;left:0;top:0}.layui-table-tool-panel li .layui-form-checkbox[lay-skin=primary] span{padding:0}.layui-table-tool .layui-table-tool-self .layui-table-tool-panel{left:auto;right:-1px}.layui-table-col-set{position:absolute;right:0;top:0;width:20px;height:100%;border-width:0 0 0 1px;background-color:#fff}.layui-table-sort{width:10px;height:20px;margin-left:5px;cursor:pointer!important}.layui-table-sort .layui-edge{position:absolute;left:5px;border-width:5px}.layui-table-sort .layui-table-sort-asc{top:3px;border-top:none;border-bottom-style:solid;border-bottom-color:#b2b2b2}.layui-table-sort .layui-table-sort-asc:hover{border-bottom-color:#666}.layui-table-sort .layui-table-sort-desc{bottom:5px;border-bottom:none;border-top-style:solid;border-top-color:#b2b2b2}.layui-table-sort .layui-table-sort-desc:hover{border-top-color:#666}.layui-table-sort[lay-sort=asc] .layui-table-sort-asc{border-bottom-color:#000}.layui-table-sort[lay-sort=desc] .layui-table-sort-desc{border-top-color:#000}.layui-table-cell{height:28px;line-height:28px;padding:0 15px;position:relative;box-sizing:border-box}.layui-table-cell .layui-form-checkbox[lay-skin=primary]{top:-1px;padding:0}.layui-table-cell .layui-table-link{color:#01AAED}.laytable-cell-checkbox,.laytable-cell-numbers,.laytable-cell-radio,.laytable-cell-space{padding:0;text-align:center}.layui-table-body{position:relative;overflow:auto;margin-right:-1px;margin-bottom:-1px}.layui-table-body .layui-none{line-height:26px;padding:15px;text-align:center;color:#999}.layui-table-fixed{position:absolute;left:0;top:0;z-index:101}.layui-table-fixed .layui-table-body{overflow:hidden}.layui-table-fixed-l{box-shadow:0 -1px 8px rgba(0,0,0,.08)}.layui-table-fixed-r{left:auto;right:-1px;border-width:0 0 0 1px;box-shadow:-1px 0 8px rgba(0,0,0,.08)}.layui-table-fixed-r .layui-table-header{position:relative;overflow:visible}.layui-table-mend{position:absolute;right:-49px;top:0;height:100%;width:50px}.layui-table-tool{position:relative;z-index:890;width:100%;min-height:50px;line-height:30px;padding:10px 15px;border-width:0 0 1px}.layui-table-tool .layui-btn-container{margin-bottom:-10px}.layui-table-page,.layui-table-total{border-width:1px 0 0;margin-bottom:-1px;overflow:hidden}.layui-table-page{position:relative;width:100%;padding:7px 7px 0;height:41px;font-size:12px;white-space:nowrap}.layui-table-page>div{height:26px}.layui-table-page .layui-laypage{margin:0}.layui-table-page .layui-laypage a,.layui-table-page .layui-laypage span{height:26px;line-height:26px;margin-bottom:10px;border:none;background:0 0}.layui-table-page .layui-laypage a,.layui-table-page .layui-laypage span.layui-laypage-curr{padding:0 12px}.layui-table-page .layui-laypage span{margin-left:0;padding:0}.layui-table-page .layui-laypage .layui-laypage-prev{margin-left:-7px!important}.layui-table-page .layui-laypage .layui-laypage-curr .layui-laypage-em{left:0;top:0;padding:0}.layui-table-page .layui-laypage button,.layui-table-page .layui-laypage input{height:26px;line-height:26px}.layui-table-page .layui-laypage input{width:40px}.layui-table-page .layui-laypage button{padding:0 10px}.layui-table-page select{height:18px}.layui-table-patch .layui-table-cell{padding:0;width:30px}.layui-table-edit{position:absolute;left:0;top:0;width:100%;height:100%;padding:0 14px 1px;border-radius:0;box-shadow:1px 1px 20px rgba(0,0,0,.15)}.layui-table-edit:focus{border-color:#5FB878!important}select.layui-table-edit{padding:0 0 0 10px;border-color:#C9C9C9}.layui-table-view .layui-form-checkbox,.layui-table-view .layui-form-radio,.layui-table-view .layui-form-switch{top:0;margin:0;box-sizing:content-box}.layui-table-view .layui-form-checkbox{top:-1px;height:26px;line-height:26px}.layui-table-view .layui-form-checkbox i{height:26px}.layui-table-grid .layui-table-cell{overflow:visible}.layui-table-grid-down{position:absolute;top:0;right:0;width:26px;height:100%;padding:5px 0;border-width:0 0 0 1px;text-align:center;background-color:#fff;color:#999;cursor:pointer}.layui-table-grid-down .layui-icon{position:absolute;top:50%;left:50%;margin:-8px 0 0 -8px}.layui-table-grid-down:hover{background-color:#fbfbfb}body .layui-table-tips .layui-layer-content{background:0 0;padding:0;box-shadow:0 1px 6px rgba(0,0,0,.12)}.layui-table-tips-main{margin:-44px 0 0 -1px;max-height:150px;padding:8px 15px;font-size:14px;overflow-y:scroll;background-color:#fff;color:#666}.layui-table-tips-c{position:absolute;right:-3px;top:-13px;width:20px;height:20px;padding:3px;cursor:pointer;background-color:#666;border-radius:50%;color:#fff}.layui-table-tips-c:hover{background-color:#777}.layui-table-tips-c:before{position:relative;right:-2px}.layui-upload-file{display:none!important;opacity:.01;filter:Alpha(opacity=1)}.layui-upload-drag,.layui-upload-form,.layui-upload-wrap{display:inline-block}.layui-upload-list{margin:10px 0}.layui-upload-choose{padding:0 10px;color:#999}.layui-upload-drag{position:relative;padding:30px;border:1px dashed #e2e2e2;background-color:#fff;text-align:center;cursor:pointer;color:#999}.layui-upload-drag .layui-icon{font-size:50px;color:#009688}.layui-upload-drag[lay-over]{border-color:#009688}.layui-upload-iframe{position:absolute;width:0;height:0;border:0;visibility:hidden}.layui-upload-wrap{position:relative;vertical-align:middle}.layui-upload-wrap .layui-upload-file{display:block!important;position:absolute;left:0;top:0;z-index:10;font-size:100px;width:100%;height:100%;opacity:.01;filter:Alpha(opacity=1);cursor:pointer}.layui-tree{line-height:26px}.layui-tree li{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-tree li .layui-tree-spread,.layui-tree li a{display:inline-block;vertical-align:top;height:26px;*display:inline;*zoom:1;cursor:pointer}.layui-tree li a{font-size:0}.layui-tree li a i{font-size:16px}.layui-tree li a cite{padding:0 6px;font-size:14px;font-style:normal}.layui-tree li i{padding-left:6px;color:#333;-moz-user-select:none}.layui-tree li .layui-tree-check{font-size:13px}.layui-tree li .layui-tree-check:hover{color:#009E94}.layui-tree li ul{display:none;margin-left:20px}.layui-tree li .layui-tree-enter{line-height:24px;border:1px dotted #000}.layui-tree-drag{display:none;position:absolute;left:-666px;top:-666px;background-color:#f2f2f2;padding:5px 10px;border:1px dotted #000;white-space:nowrap}.layui-tree-drag i{padding-right:5px}.layui-nav{position:relative;padding:0 20px;background-color:#393D49;color:#fff;border-radius:2px;font-size:0;box-sizing:border-box}.layui-nav *{font-size:14px}.layui-nav .layui-nav-item{position:relative;display:inline-block;*display:inline;*zoom:1;vertical-align:middle;line-height:60px}.layui-nav .layui-nav-item a{display:block;padding:0 20px;color:#fff;color:rgba(255,255,255,.7);transition:all .3s;-webkit-transition:all .3s}.layui-nav .layui-this:after,.layui-nav-bar,.layui-nav-tree .layui-nav-itemed:after{position:absolute;left:0;top:0;width:0;height:5px;background-color:#5FB878;transition:all .2s;-webkit-transition:all .2s}.layui-nav-bar{z-index:1000}.layui-nav .layui-nav-item a:hover,.layui-nav .layui-this a{color:#fff}.layui-nav .layui-this:after{content:'';top:auto;bottom:0;width:100%}.layui-nav-img{width:30px;height:30px;margin-right:10px;border-radius:50%}.layui-nav .layui-nav-more{content:'';width:0;height:0;border-style:solid dashed dashed;border-color:#fff transparent transparent;overflow:hidden;cursor:pointer;transition:all .2s;-webkit-transition:all .2s;position:absolute;top:50%;right:3px;margin-top:-3px;border-width:6px;border-top-color:rgba(255,255,255,.7)}.layui-nav .layui-nav-mored,.layui-nav-itemed>a .layui-nav-more{margin-top:-9px;border-style:dashed dashed solid;border-color:transparent transparent #fff}.layui-nav-child{display:none;position:absolute;left:0;top:65px;min-width:100%;line-height:36px;padding:5px 0;box-shadow:0 2px 4px rgba(0,0,0,.12);border:1px solid #d2d2d2;background-color:#fff;z-index:100;border-radius:2px;white-space:nowrap}.layui-nav .layui-nav-child a{color:#333}.layui-nav .layui-nav-child a:hover{background-color:#f2f2f2;color:#000}.layui-nav-child dd{position:relative}.layui-nav .layui-nav-child dd.layui-this a,.layui-nav-child dd.layui-this{background-color:#5FB878;color:#fff}.layui-nav-child dd.layui-this:after{display:none}.layui-nav-tree{width:200px;padding:0}.layui-nav-tree .layui-nav-item{display:block;width:100%;line-height:45px}.layui-nav-tree .layui-nav-item a{position:relative;height:45px;line-height:45px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.layui-nav-tree .layui-nav-item a:hover{background-color:#4E5465}.layui-nav-tree .layui-nav-bar{width:5px;height:0;background-color:#009688}.layui-nav-tree .layui-nav-child dd.layui-this,.layui-nav-tree .layui-nav-child dd.layui-this a,.layui-nav-tree .layui-this,.layui-nav-tree .layui-this>a,.layui-nav-tree .layui-this>a:hover{background-color:#009688;color:#fff}.layui-nav-tree .layui-this:after{display:none}.layui-nav-itemed>a,.layui-nav-tree .layui-nav-title a,.layui-nav-tree .layui-nav-title a:hover{color:#fff!important}.layui-nav-tree .layui-nav-child{position:relative;z-index:0;top:0;border:none;box-shadow:none}.layui-nav-tree .layui-nav-child a{height:40px;line-height:40px;color:#fff;color:rgba(255,255,255,.7)}.layui-nav-tree .layui-nav-child,.layui-nav-tree .layui-nav-child a:hover{background:0 0;color:#fff}.layui-nav-tree .layui-nav-more{right:10px}.layui-nav-itemed>.layui-nav-child{display:block;padding:0;background-color:rgba(0,0,0,.3)!important}.layui-nav-itemed>.layui-nav-child>.layui-this>.layui-nav-child{display:block}.layui-nav-side{position:fixed;top:0;bottom:0;left:0;overflow-x:hidden;z-index:999}.layui-bg-blue .layui-nav-bar,.layui-bg-blue .layui-nav-itemed:after,.layui-bg-blue .layui-this:after{background-color:#93D1FF}.layui-bg-blue .layui-nav-child dd.layui-this{background-color:#1E9FFF}.layui-bg-blue .layui-nav-itemed>a,.layui-nav-tree.layui-bg-blue .layui-nav-title a,.layui-nav-tree.layui-bg-blue .layui-nav-title a:hover{background-color:#007DDB!important}.layui-breadcrumb{visibility:hidden;font-size:0}.layui-breadcrumb>*{font-size:14px}.layui-breadcrumb a{color:#999!important}.layui-breadcrumb a:hover{color:#5FB878!important}.layui-breadcrumb a cite{color:#666;font-style:normal}.layui-breadcrumb span[lay-separator]{margin:0 10px;color:#999}.layui-tab{margin:10px 0;text-align:left!important}.layui-tab[overflow]>.layui-tab-title{overflow:hidden}.layui-tab-title{position:relative;left:0;height:40px;white-space:nowrap;font-size:0;border-bottom-width:1px;border-bottom-style:solid;transition:all .2s;-webkit-transition:all .2s}.layui-tab-title li{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;font-size:14px;transition:all .2s;-webkit-transition:all .2s;position:relative;line-height:40px;min-width:65px;padding:0 15px;text-align:center;cursor:pointer}.layui-tab-title li a{display:block}.layui-tab-title .layui-this{color:#000}.layui-tab-title .layui-this:after{position:absolute;left:0;top:0;content:'';width:100%;height:41px;border-width:1px;border-style:solid;border-bottom-color:#fff;border-radius:2px 2px 0 0;box-sizing:border-box;pointer-events:none}.layui-tab-bar{position:absolute;right:0;top:0;z-index:10;width:30px;height:39px;line-height:39px;border-width:1px;border-style:solid;border-radius:2px;text-align:center;background-color:#fff;cursor:pointer}.layui-tab-bar .layui-icon{position:relative;display:inline-block;top:3px;transition:all .3s;-webkit-transition:all .3s}.layui-tab-item{display:none}.layui-tab-more{padding-right:30px;height:auto!important;white-space:normal!important}.layui-tab-more li.layui-this:after{border-bottom-color:#e2e2e2;border-radius:2px}.layui-tab-more .layui-tab-bar .layui-icon{top:-2px;top:3px\9;-webkit-transform:rotate(180deg);transform:rotate(180deg)}:root .layui-tab-more .layui-tab-bar .layui-icon{top:-2px\0/IE9}.layui-tab-content{padding:10px}.layui-tab-title li .layui-tab-close{position:relative;display:inline-block;width:18px;height:18px;line-height:20px;margin-left:8px;top:1px;text-align:center;font-size:14px;color:#c2c2c2;transition:all .2s;-webkit-transition:all .2s}.layui-tab-title li .layui-tab-close:hover{border-radius:2px;background-color:#FF5722;color:#fff}.layui-tab-brief>.layui-tab-title .layui-this{color:#009688}.layui-tab-brief>.layui-tab-more li.layui-this:after,.layui-tab-brief>.layui-tab-title .layui-this:after{border:none;border-radius:0;border-bottom:2px solid #5FB878}.layui-tab-brief[overflow]>.layui-tab-title .layui-this:after{top:-1px}.layui-tab-card{border-width:1px;border-style:solid;border-radius:2px;box-shadow:0 2px 5px 0 rgba(0,0,0,.1)}.layui-tab-card>.layui-tab-title{background-color:#f2f2f2}.layui-tab-card>.layui-tab-title li{margin-right:-1px;margin-left:-1px}.layui-tab-card>.layui-tab-title .layui-this{background-color:#fff}.layui-tab-card>.layui-tab-title .layui-this:after{border-top:none;border-width:1px;border-bottom-color:#fff}.layui-tab-card>.layui-tab-title .layui-tab-bar{height:40px;line-height:40px;border-radius:0;border-top:none;border-right:none}.layui-tab-card>.layui-tab-more .layui-this{background:0 0;color:#5FB878}.layui-tab-card>.layui-tab-more .layui-this:after{border:none}.layui-timeline{padding-left:5px}.layui-timeline-item{position:relative;padding-bottom:20px}.layui-timeline-axis{position:absolute;left:-5px;top:0;z-index:10;width:20px;height:20px;line-height:20px;background-color:#fff;color:#5FB878;border-radius:50%;text-align:center;cursor:pointer}.layui-timeline-axis:hover{color:#FF5722}.layui-timeline-item:before{content:'';position:absolute;left:5px;top:0;z-index:0;width:1px;height:100%}.layui-timeline-item:last-child:before{display:none}.layui-timeline-item:first-child:before{display:block}.layui-timeline-content{padding-left:25px}.layui-timeline-title{position:relative;margin-bottom:10px}.layui-badge,.layui-badge-dot,.layui-badge-rim{position:relative;display:inline-block;padding:0 6px;font-size:12px;text-align:center;background-color:#FF5722;color:#fff;border-radius:2px}.layui-badge{height:18px;line-height:18px}.layui-badge-dot{width:8px;height:8px;padding:0;border-radius:50%}.layui-badge-rim{height:18px;line-height:18px;border-width:1px;border-style:solid;background-color:#fff;color:#666}.layui-btn .layui-badge,.layui-btn .layui-badge-dot{margin-left:5px}.layui-nav .layui-badge,.layui-nav .layui-badge-dot{position:absolute;top:50%;margin:-8px 6px 0}.layui-tab-title .layui-badge,.layui-tab-title .layui-badge-dot{left:5px;top:-2px}.layui-carousel{position:relative;left:0;top:0;background-color:#f8f8f8}.layui-carousel>[carousel-item]{position:relative;width:100%;height:100%;overflow:hidden}.layui-carousel>[carousel-item]:before{position:absolute;content:'\e63d';left:50%;top:50%;width:100px;line-height:20px;margin:-10px 0 0 -50px;text-align:center;color:#c2c2c2;font-family:layui-icon!important;font-size:30px;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.layui-carousel>[carousel-item]>*{display:none;position:absolute;left:0;top:0;width:100%;height:100%;background-color:#f8f8f8;transition-duration:.3s;-webkit-transition-duration:.3s}.layui-carousel-updown>*{-webkit-transition:.3s ease-in-out up;transition:.3s ease-in-out up}.layui-carousel-arrow{display:none\9;opacity:0;position:absolute;left:10px;top:50%;margin-top:-18px;width:36px;height:36px;line-height:36px;text-align:center;font-size:20px;border:0;border-radius:50%;background-color:rgba(0,0,0,.2);color:#fff;-webkit-transition-duration:.3s;transition-duration:.3s;cursor:pointer}.layui-carousel-arrow[lay-type=add]{left:auto!important;right:10px}.layui-carousel:hover .layui-carousel-arrow[lay-type=add],.layui-carousel[lay-arrow=always] .layui-carousel-arrow[lay-type=add]{right:20px}.layui-carousel[lay-arrow=always] .layui-carousel-arrow{opacity:1;left:20px}.layui-carousel[lay-arrow=none] .layui-carousel-arrow{display:none}.layui-carousel-arrow:hover,.layui-carousel-ind ul:hover{background-color:rgba(0,0,0,.35)}.layui-carousel:hover .layui-carousel-arrow{display:block\9;opacity:1;left:20px}.layui-carousel-ind{position:relative;top:-35px;width:100%;line-height:0!important;text-align:center;font-size:0}.layui-carousel[lay-indicator=outside]{margin-bottom:30px}.layui-carousel[lay-indicator=outside] .layui-carousel-ind{top:10px}.layui-carousel[lay-indicator=outside] .layui-carousel-ind ul{background-color:rgba(0,0,0,.5)}.layui-carousel[lay-indicator=none] .layui-carousel-ind{display:none}.layui-carousel-ind ul{display:inline-block;padding:5px;background-color:rgba(0,0,0,.2);border-radius:10px;-webkit-transition-duration:.3s;transition-duration:.3s}.layui-carousel-ind li{display:inline-block;width:10px;height:10px;margin:0 3px;font-size:14px;background-color:#e2e2e2;background-color:rgba(255,255,255,.5);border-radius:50%;cursor:pointer;-webkit-transition-duration:.3s;transition-duration:.3s}.layui-carousel-ind li:hover{background-color:rgba(255,255,255,.7)}.layui-carousel-ind li.layui-this{background-color:#fff}.layui-carousel>[carousel-item]>.layui-carousel-next,.layui-carousel>[carousel-item]>.layui-carousel-prev,.layui-carousel>[carousel-item]>.layui-this{display:block}.layui-carousel>[carousel-item]>.layui-this{left:0}.layui-carousel>[carousel-item]>.layui-carousel-prev{left:-100%}.layui-carousel>[carousel-item]>.layui-carousel-next{left:100%}.layui-carousel>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel>[carousel-item]>.layui-carousel-prev.layui-carousel-right{left:0}.layui-carousel>[carousel-item]>.layui-this.layui-carousel-left{left:-100%}.layui-carousel>[carousel-item]>.layui-this.layui-carousel-right{left:100%}.layui-carousel[lay-anim=updown] .layui-carousel-arrow{left:50%!important;top:20px;margin:0 0 0 -18px}.layui-carousel[lay-anim=updown]>[carousel-item]>*,.layui-carousel[lay-anim=fade]>[carousel-item]>*{left:0!important}.layui-carousel[lay-anim=updown] .layui-carousel-arrow[lay-type=add]{top:auto!important;bottom:20px}.layui-carousel[lay-anim=updown] .layui-carousel-ind{position:absolute;top:50%;right:20px;width:auto;height:auto}.layui-carousel[lay-anim=updown] .layui-carousel-ind ul{padding:3px 5px}.layui-carousel[lay-anim=updown] .layui-carousel-ind li{display:block;margin:6px 0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this{top:0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-prev{top:-100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-next{top:100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-carousel-prev.layui-carousel-right{top:0}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this.layui-carousel-left{top:-100%}.layui-carousel[lay-anim=updown]>[carousel-item]>.layui-this.layui-carousel-right{top:100%}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-next,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-prev{opacity:0}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-next.layui-carousel-left,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-carousel-prev.layui-carousel-right{opacity:1}.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-this.layui-carousel-left,.layui-carousel[lay-anim=fade]>[carousel-item]>.layui-this.layui-carousel-right{opacity:0}.layui-fixbar{position:fixed;right:15px;bottom:15px;z-index:999999}.layui-fixbar li{width:50px;height:50px;line-height:50px;margin-bottom:1px;text-align:center;cursor:pointer;font-size:30px;background-color:#9F9F9F;color:#fff;border-radius:2px;opacity:.95}.layui-fixbar li:hover{opacity:.85}.layui-fixbar li:active{opacity:1}.layui-fixbar .layui-fixbar-top{display:none;font-size:40px}body .layui-util-face{border:none;background:0 0}body .layui-util-face .layui-layer-content{padding:0;background-color:#fff;color:#666;box-shadow:none}.layui-util-face .layui-layer-TipsG{display:none}.layui-util-face ul{position:relative;width:372px;padding:10px;border:1px solid #D9D9D9;background-color:#fff;box-shadow:0 0 20px rgba(0,0,0,.2)}.layui-util-face ul li{cursor:pointer;float:left;border:1px solid #e8e8e8;height:22px;width:26px;overflow:hidden;margin:-1px 0 0 -1px;padding:4px 2px;text-align:center}.layui-util-face ul li:hover{position:relative;z-index:2;border:1px solid #eb7350;background:#fff9ec}.layui-code{position:relative;margin:10px 0;padding:15px;line-height:20px;border:1px solid #ddd;border-left-width:6px;background-color:#F2F2F2;color:#333;font-family:Courier New;font-size:12px}.layui-rate,.layui-rate *{display:inline-block;vertical-align:middle}.layui-rate{padding:10px 5px 10px 0;font-size:0}.layui-rate li i.layui-icon{font-size:20px;color:#FFB800;margin-right:5px;transition:all .3s;-webkit-transition:all .3s}.layui-rate li i:hover{cursor:pointer;transform:scale(1.12);-webkit-transform:scale(1.12)}.layui-rate[readonly] li i:hover{cursor:default;transform:scale(1)}.layui-colorpicker{width:26px;height:26px;border:1px solid #e6e6e6;padding:5px;border-radius:2px;line-height:24px;display:inline-block;cursor:pointer;transition:all .3s;-webkit-transition:all .3s}.layui-colorpicker:hover{border-color:#d2d2d2}.layui-colorpicker.layui-colorpicker-lg{width:34px;height:34px;line-height:32px}.layui-colorpicker.layui-colorpicker-sm{width:24px;height:24px;line-height:22px}.layui-colorpicker.layui-colorpicker-xs{width:22px;height:22px;line-height:20px}.layui-colorpicker-trigger-bgcolor{display:block;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);border-radius:2px}.layui-colorpicker-trigger-span{display:block;height:100%;box-sizing:border-box;border:1px solid rgba(0,0,0,.15);border-radius:2px;text-align:center}.layui-colorpicker-trigger-i{display:inline-block;color:#FFF;font-size:12px}.layui-colorpicker-trigger-i.layui-icon-close{color:#999}.layui-colorpicker-main{position:absolute;z-index:66666666;width:280px;padding:7px;background:#FFF;border:1px solid #d2d2d2;border-radius:2px;box-shadow:0 2px 4px rgba(0,0,0,.12)}.layui-colorpicker-main-wrapper{height:180px;position:relative}.layui-colorpicker-basis{width:260px;height:100%;position:relative}.layui-colorpicker-basis-white{width:100%;height:100%;position:absolute;top:0;left:0;background:linear-gradient(90deg,#FFF,hsla(0,0%,100%,0))}.layui-colorpicker-basis-black{width:100%;height:100%;position:absolute;top:0;left:0;background:linear-gradient(0deg,#000,transparent)}.layui-colorpicker-basis-cursor{width:10px;height:10px;border:1px solid #FFF;border-radius:50%;position:absolute;top:-3px;right:-3px;cursor:pointer}.layui-colorpicker-side{position:absolute;top:0;right:0;width:12px;height:100%;background:linear-gradient(red,#FF0,#0F0,#0FF,#00F,#F0F,red)}.layui-colorpicker-side-slider{width:100%;height:5px;box-shadow:0 0 1px #888;box-sizing:border-box;background:#FFF;border-radius:1px;border:1px solid #f0f0f0;cursor:pointer;position:absolute;left:0}.layui-colorpicker-main-alpha{display:none;height:12px;margin-top:7px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.layui-colorpicker-alpha-bgcolor{height:100%;position:relative}.layui-colorpicker-alpha-slider{width:5px;height:100%;box-shadow:0 0 1px #888;box-sizing:border-box;background:#FFF;border-radius:1px;border:1px solid #f0f0f0;cursor:pointer;position:absolute;top:0}.layui-colorpicker-main-pre{padding-top:7px;font-size:0}.layui-colorpicker-pre{width:20px;height:20px;border-radius:2px;display:inline-block;margin-left:6px;margin-bottom:7px;cursor:pointer}.layui-colorpicker-pre:nth-child(11n+1){margin-left:0}.layui-colorpicker-pre-isalpha{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.layui-colorpicker-pre.layui-this{box-shadow:0 0 3px 2px rgba(0,0,0,.15)}.layui-colorpicker-pre>div{height:100%;border-radius:2px}.layui-colorpicker-main-input{text-align:right;padding-top:7px}.layui-colorpicker-main-input .layui-btn-container .layui-btn{margin:0 0 0 10px}.layui-colorpicker-main-input div.layui-inline{float:left;margin-right:10px;font-size:14px}.layui-colorpicker-main-input input.layui-input{width:150px;height:30px;color:#666}.layui-slider{height:4px;background:#e2e2e2;border-radius:3px;position:relative;cursor:pointer}.layui-slider-bar{border-radius:3px;position:absolute;height:100%}.layui-slider-step{position:absolute;top:0;width:4px;height:4px;border-radius:50%;background:#FFF;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.layui-slider-wrap{width:36px;height:36px;position:absolute;top:-16px;-webkit-transform:translateX(-50%);transform:translateX(-50%);z-index:10;text-align:center}.layui-slider-wrap-btn{width:12px;height:12px;border-radius:50%;background:#FFF;display:inline-block;vertical-align:middle;cursor:pointer;transition:.3s}.layui-slider-wrap:after{content:"";height:100%;display:inline-block;vertical-align:middle}.layui-slider-wrap-btn.layui-slider-hover,.layui-slider-wrap-btn:hover{transform:scale(1.2)}.layui-slider-wrap-btn.layui-disabled:hover{transform:scale(1)!important}.layui-slider-tips{position:absolute;top:-42px;z-index:66666666;white-space:nowrap;display:none;-webkit-transform:translateX(-50%);transform:translateX(-50%);color:#FFF;background:#000;border-radius:3px;height:25px;line-height:25px;padding:0 10px}.layui-slider-tips:after{content:'';position:absolute;bottom:-12px;left:50%;margin-left:-6px;width:0;height:0;border-width:6px;border-style:solid;border-color:#000 transparent transparent}.layui-slider-input{width:70px;height:32px;border:1px solid #e6e6e6;border-radius:3px;font-size:16px;line-height:32px;position:absolute;right:0;top:-15px}.layui-slider-input-btn{display:none;position:absolute;top:0;right:0;width:20px;height:100%;border-left:1px solid #d2d2d2}.layui-slider-input-btn i{cursor:pointer;position:absolute;right:0;bottom:0;width:20px;height:50%;font-size:12px;line-height:16px;text-align:center;color:#999}.layui-slider-input-btn i:first-child{top:0;border-bottom:1px solid #d2d2d2}.layui-slider-input-txt{height:100%;font-size:14px}.layui-slider-input-txt input{height:100%;border:none}.layui-slider-input-btn i:hover{color:#009688}.layui-slider-vertical{width:4px;margin-left:34px}.layui-slider-vertical .layui-slider-bar{width:4px}.layui-slider-vertical .layui-slider-step{top:auto;left:0;-webkit-transform:translateY(50%);transform:translateY(50%)}.layui-slider-vertical .layui-slider-wrap{top:auto;left:-16px;-webkit-transform:translateY(50%);transform:translateY(50%)}.layui-slider-vertical .layui-slider-tips{top:auto;left:2px}@media \0screen{.layui-slider-wrap-btn{margin-left:-20px}.layui-slider-vertical .layui-slider-wrap-btn{margin-left:0;margin-bottom:-20px}.layui-slider-vertical .layui-slider-tips{margin-left:-8px}.layui-slider>span{margin-left:8px}}.layui-anim{-webkit-animation-duration:.3s;animation-duration:.3s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.layui-anim.layui-icon{display:inline-block}.layui-anim-loop{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.layui-trans,.layui-trans a{transition:all .3s;-webkit-transition:all .3s}@-webkit-keyframes layui-rotate{from{-webkit-transform:rotate(0)}to{-webkit-transform:rotate(360deg)}}@keyframes layui-rotate{from{transform:rotate(0)}to{transform:rotate(360deg)}}.layui-anim-rotate{-webkit-animation-name:layui-rotate;animation-name:layui-rotate;-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-timing-function:linear;animation-timing-function:linear}@-webkit-keyframes layui-up{from{-webkit-transform:translate3d(0,100%,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes layui-up{from{transform:translate3d(0,100%,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-anim-up{-webkit-animation-name:layui-up;animation-name:layui-up}@-webkit-keyframes layui-upbit{from{-webkit-transform:translate3d(0,30px,0);opacity:.3}to{-webkit-transform:translate3d(0,0,0);opacity:1}}@keyframes layui-upbit{from{transform:translate3d(0,30px,0);opacity:.3}to{transform:translate3d(0,0,0);opacity:1}}.layui-anim-upbit{-webkit-animation-name:layui-upbit;animation-name:layui-upbit}@-webkit-keyframes layui-scale{0%{opacity:.3;-webkit-transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes layui-scale{0%{opacity:.3;-ms-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-ms-transform:scale(1);transform:scale(1)}}.layui-anim-scale{-webkit-animation-name:layui-scale;animation-name:layui-scale}@-webkit-keyframes layui-scale-spring{0%{opacity:.5;-webkit-transform:scale(.5)}80%{opacity:.8;-webkit-transform:scale(1.1)}100%{opacity:1;-webkit-transform:scale(1)}}@keyframes layui-scale-spring{0%{opacity:.5;transform:scale(.5)}80%{opacity:.8;transform:scale(1.1)}100%{opacity:1;transform:scale(1)}}.layui-anim-scaleSpring{-webkit-animation-name:layui-scale-spring;animation-name:layui-scale-spring}@-webkit-keyframes layui-fadein{0%{opacity:0}100%{opacity:1}}@keyframes layui-fadein{0%{opacity:0}100%{opacity:1}}.layui-anim-fadein{-webkit-animation-name:layui-fadein;animation-name:layui-fadein}@-webkit-keyframes layui-fadeout{0%{opacity:1}100%{opacity:0}}@keyframes layui-fadeout{0%{opacity:1}100%{opacity:0}}.layui-anim-fadeout{-webkit-animation-name:layui-fadeout;animation-name:layui-fadeout} \ No newline at end of file diff --git a/admin-core/src/main/resources/static/plugins/sideshow/css/component.css b/admin-core/src/main/resources/static/plugins/sideshow/css/component.css new file mode 100644 index 0000000000000000000000000000000000000000..3c510dbb3a3aff7a750f66319cec31033f114af3 --- /dev/null +++ b/admin-core/src/main/resources/static/plugins/sideshow/css/component.css @@ -0,0 +1,102 @@ +/* Header */ +.large-header { + position: relative; + width: 100%; + background: #333; + overflow: hidden; + background-size: cover; + background-position: center center; + z-index: 1; +} + +.demo-1 .large-header { + background-image: url('../img/demo-1-bg.jpg'); +} + +.demo-2 .large-header { + background-image: url('../img/demo-2-bg.jpg'); + background-position: center bottom; +} + +.demo-3 .large-header { + background: #7f8c8d; +} + +.demo-4 .large-header { + background: #f9f1e9; +} + +.main-title { + position: absolute; + margin: 0; + padding: 0; + color: #f9f1e9; + text-align: center; + top: 50%; + left: 50%; + -webkit-transform: translate3d(-50%,-50%,0); + transform: translate3d(-50%,-50%,0); +} + +.demo-1 .main-title, +.demo-3 .main-title { + text-transform: uppercase; + font-size: 4.2em; + letter-spacing: 0.1em; +} + +.demo-2 .main-title { + font-family: 'Clicker Script', cursive; + font-weight: normal; + font-size: 8em; + padding-left: 10px; + text-shadow: 2px 2px 4px rgba(0,0,0,0.4); +} + +.demo-2 .main-title::before { + content: ''; + width: 20vw; + height: 20vw; + min-width: 3.5em; + min-height: 3.5em; + background: url(../img/deco.svg) no-repeat center center; + background-size: cover; + position: absolute; + top: 50%; + left: 50%; + border-radius: 50%; + z-index: -1; + -webkit-transform: translate3d(-50%,-50%,0); + transform: translate3d(-50%,-50%,0); +} + +.demo-3 .main-title { + padding: 10px 40px; + border: 10px double #f9f1e9; + text-transform: uppercase; + font-family: Londrina Outline, sans-serif; +} + +.demo-4 .main-title { + font-size: 6em; + font-weight: 300; + padding: 10px 30px; + text-transform: uppercase; + color: #222; +} + +.main-title .thin { + font-weight: 200; +} + +@media only screen and (max-width : 768px) { + .demo-1 .main-title, + .demo-3 .main-title, + .demo-4 .main-title { + font-size: 3em; + } + + .demo-2 .main-title { + font-size: 4em; + } +} \ No newline at end of file diff --git a/admin-core/src/main/resources/static/plugins/sideshow/css/demo.css b/admin-core/src/main/resources/static/plugins/sideshow/css/demo.css new file mode 100644 index 0000000000000000000000000000000000000000..39f203f23f0a4697d06162323bbdbb730d3373ca --- /dev/null +++ b/admin-core/src/main/resources/static/plugins/sideshow/css/demo.css @@ -0,0 +1,196 @@ +@font-face { + font-weight: normal; + font-style: normal; + font-family: 'codropsicons'; + src:url('../fonts/codropsicons/codropsicons.eot'); + src:url('../fonts/codropsicons/codropsicons.eot?#iefix') format('embedded-opentype'), + url('../fonts/codropsicons/codropsicons.woff') format('woff'), + url('../fonts/codropsicons/codropsicons.ttf') format('truetype'), + url('../fonts/codropsicons/codropsicons.svg#codropsicons') format('svg'); +} + +*, *:after, *:before { -webkit-box-sizing: border-box; box-sizing: border-box; } +.clearfix:before, .clearfix:after { content: ''; display: table; } +.clearfix:after { clear: both; } + +body { + background: #fff; + color: #383a3c; + font-weight: 400; + font-size: 1em; + line-height: 1.25; + font-family: 'Raleway', Calibri, Arial, sans-serif; +} + +a, button { + outline: none; +} + +a { + color: #566473; + text-decoration: none; +} + +a:hover, a:focus { + color: #34495e; +} + +section { + padding: 1em; + text-align: center; +} + +p.ref { + text-align: center; + padding: 2em 1em; +} + +/* Header */ +.codrops-header { + margin: 0 auto; + padding: 2em; + text-align: center; + max-width: 900px; +} + +.codrops-header h1 { + margin: 0; + font-size: 4.5em; + line-height: 1; + font-weight: 200; +} + +.codrops-header h1 span { + display: block; + padding: 1em 0 1.5em; + font-size: 36%; + color: #95a5a6; + line-height: 1.4; +} + +/* To Navigation Style */ +.codrops-top { + width: 100%; + text-transform: uppercase; + font-weight: 700; + font-size: 0.69em; + text-align: center; + padding: 3em 0; +} + +.codrops-top a { + display: inline-block; + padding: 1.5em; + text-decoration: none; + letter-spacing: 1px; +} + +.codrops-icon:before { + margin: 0 4px; + text-transform: none; + font-weight: normal; + font-style: normal; + font-variant: normal; + font-family: 'codropsicons'; + line-height: 1; + speak: none; + -webkit-font-smoothing: antialiased; +} + +.codrops-icon-drop:before { + content: "\e001"; +} + +.codrops-icon-prev:before { + content: "\e004"; +} + +/* Demo Buttons Style */ +.codrops-demos { + padding-top: 1em; + font-size: 0.8em; + text-align:center; +} + +.codrops-demos a { + display: inline-block; + margin: 0.35em 0.1em; + padding: 0.5em 1.2em; + outline: none; + text-decoration: none; + text-transform: uppercase; + letter-spacing: 1px; + font-weight: 700; + border-radius: 2px; + font-size: 110%; + border: 2px solid transparent; +} + +.codrops-demos a:hover, +.codrops-demos a.current-demo { + border-color: #383a3c; +} + +.codrops-demos h3 { + margin: 0; + padding: 1em 0 0.5em 0; + font-size: 0.9em; + float: left; + min-width: 90px; + clear: left; +} + +.codrops-demos div:not(:first-child) h3 { + padding-top: 2em; +} + +.codrops-demos a:hover, +.codrops-demos a.current-demo { + color: inherit; + border-color: initial; +} + +/* Related demos */ +.related { + padding: 10em 0; +} + +.related p { + font-size: 1.5em; +} + +.related > a { + display: inline-block; + text-align: center; + margin: 20px 10px; + padding: 25px; + vertical-align: middle; +} + +.related a img { + max-width: 100%; + opacity: 0.8; + border-radius: 10px; +} + +.related a:hover img, +.related a:active img { + opacity: 1; +} + +.related a h3 { + margin: 0; + min-height: 63px; + padding: 0.5em 0 0.3em; + max-width: 300px; + text-align: center; + font-weight: 400; + font-size: 1em; +} + +@media screen and (max-width: 40em) { + + .codrops-header h1 { + font-size: 2.5em; + } +} \ No newline at end of file diff --git a/admin-core/src/main/resources/static/plugins/sideshow/css/login.css b/admin-core/src/main/resources/static/plugins/sideshow/css/login.css new file mode 100644 index 0000000000000000000000000000000000000000..ba2ac9fc1bb087a287187ea348edcdac080665b5 --- /dev/null +++ b/admin-core/src/main/resources/static/plugins/sideshow/css/login.css @@ -0,0 +1,105 @@ +.kit-login-bg { + /*background: url(../Images/login-bg-1.jpg) no-repeat center center fixed;*/ + background-color: #393D49; +} + +.kit-login-box { + width: 390px; + /*height: 330px;*/ + margin: 10% auto; + background-color: #666; + background-color: rgba(46, 46, 46, 0.61); + border-radius: 10px; + color: aliceblue; + box-shadow: 0px 0px 20px 0px #009688; +} + + .kit-login-box header { + height: 39px; + padding: 10px; + border-bottom: 1px solid rgba(0, 150, 136, 0.5); + } + +.kit-login-box header h1 { + text-align: center; + font-size: 25px; + line-height: 40px; +} + + .kit-login-box .kit-login-main { + /*height: 185px;*/ + padding: 30px 50px 0; + } + .kit-login-box .kit-login-main .layui-input:focus { + border-color: #009688 !important; + } + +.kit-login-main .layui-form-item { + position: relative; +} + +.kit-login-main .layui-form-item .kit-login-icon { + position: absolute; + color: #cccccc; + top: 10px; + left: 10px; +} + +.kit-login-main .layui-form-item input { + padding-left: 34px; +} + +.kit-login-box footer { + height: 85px; + /*padding: 10px 10px 0 10px;*/ +} + +.kit-login-box footer p { + line-height: 35px; + text-align: center; +} + +.kit-pull-left { + float: left !important; +} + +.kit-pull-right { + float: right !important; +} + +.kit-clear { + clear: both; +} + +.kit-login-remember { + line-height: 38px; +} + .kit-login-remember .layui-form-checkbox[lay-skin=primary] span { + color: white; + } + + .kit-login-remember .layui-form-checked[lay-skin=primary] i { + border-color: #009688; + background-color: #009688; + } + +.kit-login-remember .layui-form-switch { + margin-top: 0px; +} + +.kit-login-code-box { + position: relative; + padding: 10px; +} + +.kit-login-code-box input { + position: absolute; + width: 100px; +} + +.kit-login-code-box img { + cursor: pointer; + position: absolute; + left: 115px; + height: 38px; +} diff --git a/admin-core/src/main/resources/static/plugins/sideshow/css/normalize.css b/admin-core/src/main/resources/static/plugins/sideshow/css/normalize.css new file mode 100644 index 0000000000000000000000000000000000000000..77feb205bc286d2d0cb63da1c1d49101c1cec116 --- /dev/null +++ b/admin-core/src/main/resources/static/plugins/sideshow/css/normalize.css @@ -0,0 +1 @@ +article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block;}audio,canvas,video{display:inline-block;}audio:not([controls]){display:none;height:0;}[hidden]{display:none;}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;}body{margin:0;}a:focus{outline:thin dotted;}a:active,a:hover{outline:0;}h1{font-size:2em;margin:0.67em 0;}abbr[title]{border-bottom:1px dotted;}b,strong{font-weight:bold;}dfn{font-style:italic;}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0;}mark{background:#ff0;color:#000;}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em;}pre{white-space:pre-wrap;}q{quotes:"\201C" "\201D" "\2018" "\2019";}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:0;}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em;}legend{border:0;padding:0;}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0;}button,input{line-height:normal;}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;}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}textarea{overflow:auto;vertical-align:top;}table{border-collapse:collapse;border-spacing:0;} \ No newline at end of file diff --git a/admin-core/src/main/resources/static/plugins/sideshow/fonts/codropsicons/codropsicons.eot b/admin-core/src/main/resources/static/plugins/sideshow/fonts/codropsicons/codropsicons.eot new file mode 100644 index 0000000000000000000000000000000000000000..f46c7f4844855ac4e6ae8d283280440004f2f8be Binary files /dev/null and b/admin-core/src/main/resources/static/plugins/sideshow/fonts/codropsicons/codropsicons.eot differ diff --git a/admin-core/src/main/resources/static/plugins/sideshow/fonts/codropsicons/codropsicons.svg b/admin-core/src/main/resources/static/plugins/sideshow/fonts/codropsicons/codropsicons.svg new file mode 100644 index 0000000000000000000000000000000000000000..d202d2121052874a64f74f908f89f00c0dcf234e --- /dev/null +++ b/admin-core/src/main/resources/static/plugins/sideshow/fonts/codropsicons/codropsicons.svg @@ -0,0 +1,24 @@ + + + + +This is a custom SVG font generated by IcoMoon. + + + + + + + + + + + + + + \ No newline at end of file diff --git a/admin-core/src/main/resources/static/plugins/sideshow/fonts/codropsicons/codropsicons.ttf b/admin-core/src/main/resources/static/plugins/sideshow/fonts/codropsicons/codropsicons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..72bed1fc166049e8b1a6865d60876c7b66c9c33f Binary files /dev/null and b/admin-core/src/main/resources/static/plugins/sideshow/fonts/codropsicons/codropsicons.ttf differ diff --git a/admin-core/src/main/resources/static/plugins/sideshow/fonts/codropsicons/codropsicons.woff b/admin-core/src/main/resources/static/plugins/sideshow/fonts/codropsicons/codropsicons.woff new file mode 100644 index 0000000000000000000000000000000000000000..1003218f04a098dcf26cf9260f28f9e58ea77b5f Binary files /dev/null and b/admin-core/src/main/resources/static/plugins/sideshow/fonts/codropsicons/codropsicons.woff differ diff --git a/admin-core/src/main/resources/static/plugins/sideshow/fonts/codropsicons/license.txt b/admin-core/src/main/resources/static/plugins/sideshow/fonts/codropsicons/license.txt new file mode 100644 index 0000000000000000000000000000000000000000..88a5cbc9ad9bace070e1e12ebbf798fe7d43c71b --- /dev/null +++ b/admin-core/src/main/resources/static/plugins/sideshow/fonts/codropsicons/license.txt @@ -0,0 +1,6 @@ +Icon Set: Font Awesome -- http://fortawesome.github.com/Font-Awesome/ +License: SIL -- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL + + +Icon Set: Eco Ico -- http://dribbble.com/shots/665585-Eco-Ico +License: CC0 -- http://creativecommons.org/publicdomain/zero/1.0/ \ No newline at end of file diff --git a/admin-core/src/main/resources/static/plugins/sideshow/img/demo-1-bg.jpg b/admin-core/src/main/resources/static/plugins/sideshow/img/demo-1-bg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a6018b7e5a41f1af7a4a38ffe464c5da9512ebe6 Binary files /dev/null and b/admin-core/src/main/resources/static/plugins/sideshow/img/demo-1-bg.jpg differ diff --git a/admin-core/src/main/resources/static/plugins/sideshow/img/demo-2-bg.jpg b/admin-core/src/main/resources/static/plugins/sideshow/img/demo-2-bg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b34f9c644e341c6d0a41106e8b678342c59eca87 Binary files /dev/null and b/admin-core/src/main/resources/static/plugins/sideshow/img/demo-2-bg.jpg differ diff --git a/admin-core/src/main/resources/static/plugins/sideshow/js/EasePack.min.js b/admin-core/src/main/resources/static/plugins/sideshow/js/EasePack.min.js new file mode 100644 index 0000000000000000000000000000000000000000..d94e23b9ea9235794cfc15e66680e200c951f9ab --- /dev/null +++ b/admin-core/src/main/resources/static/plugins/sideshow/js/EasePack.min.js @@ -0,0 +1,12 @@ +/*! + * VERSION: beta 1.9.4 + * DATE: 2014-07-17 + * UPDATES AND DOCS AT: http://www.greensock.com + * + * @license Copyright (c) 2008-2014, GreenSock. All rights reserved. + * This work is subject to the terms at http://www.greensock.com/terms_of_use.html or for + * Club GreenSock members, the software agreement that was issued with your membership. + * + * @author: Jack Doyle, jack@greensock.com + **/ +var _gsScope="undefined"!=typeof module&&module.exports&&"undefined"!=typeof global?global:this||window;(_gsScope._gsQueue||(_gsScope._gsQueue=[])).push(function(){"use strict";_gsScope._gsDefine("easing.Back",["easing.Ease"],function(t){var e,i,s,r=_gsScope.GreenSockGlobals||_gsScope,n=r.com.greensock,a=2*Math.PI,o=Math.PI/2,h=n._class,l=function(e,i){var s=h("easing."+e,function(){},!0),r=s.prototype=new t;return r.constructor=s,r.getRatio=i,s},_=t.register||function(){},u=function(t,e,i,s){var r=h("easing."+t,{easeOut:new e,easeIn:new i,easeInOut:new s},!0);return _(r,t),r},c=function(t,e,i){this.t=t,this.v=e,i&&(this.next=i,i.prev=this,this.c=i.v-e,this.gap=i.t-t)},p=function(e,i){var s=h("easing."+e,function(t){this._p1=t||0===t?t:1.70158,this._p2=1.525*this._p1},!0),r=s.prototype=new t;return r.constructor=s,r.getRatio=i,r.config=function(t){return new s(t)},s},f=u("Back",p("BackOut",function(t){return(t-=1)*t*((this._p1+1)*t+this._p1)+1}),p("BackIn",function(t){return t*t*((this._p1+1)*t-this._p1)}),p("BackInOut",function(t){return 1>(t*=2)?.5*t*t*((this._p2+1)*t-this._p2):.5*((t-=2)*t*((this._p2+1)*t+this._p2)+2)})),m=h("easing.SlowMo",function(t,e,i){e=e||0===e?e:.7,null==t?t=.7:t>1&&(t=1),this._p=1!==t?e:0,this._p1=(1-t)/2,this._p2=t,this._p3=this._p1+this._p2,this._calcEnd=i===!0},!0),d=m.prototype=new t;return d.constructor=m,d.getRatio=function(t){var e=t+(.5-t)*this._p;return this._p1>t?this._calcEnd?1-(t=1-t/this._p1)*t:e-(t=1-t/this._p1)*t*t*t*e:t>this._p3?this._calcEnd?1-(t=(t-this._p3)/this._p1)*t:e+(t-e)*(t=(t-this._p3)/this._p1)*t*t*t:this._calcEnd?1:e},m.ease=new m(.7,.7),d.config=m.config=function(t,e,i){return new m(t,e,i)},e=h("easing.SteppedEase",function(t){t=t||1,this._p1=1/t,this._p2=t+1},!0),d=e.prototype=new t,d.constructor=e,d.getRatio=function(t){return 0>t?t=0:t>=1&&(t=.999999999),(this._p2*t>>0)*this._p1},d.config=e.config=function(t){return new e(t)},i=h("easing.RoughEase",function(e){e=e||{};for(var i,s,r,n,a,o,h=e.taper||"none",l=[],_=0,u=0|(e.points||20),p=u,f=e.randomize!==!1,m=e.clamp===!0,d=e.template instanceof t?e.template:null,g="number"==typeof e.strength?.4*e.strength:.4;--p>-1;)i=f?Math.random():1/u*p,s=d?d.getRatio(i):i,"none"===h?r=g:"out"===h?(n=1-i,r=n*n*g):"in"===h?r=i*i*g:.5>i?(n=2*i,r=.5*n*n*g):(n=2*(1-i),r=.5*n*n*g),f?s+=Math.random()*r-.5*r:p%2?s+=.5*r:s-=.5*r,m&&(s>1?s=1:0>s&&(s=0)),l[_++]={x:i,y:s};for(l.sort(function(t,e){return t.x-e.x}),o=new c(1,1,null),p=u;--p>-1;)a=l[p],o=new c(a.x,a.y,o);this._prev=new c(0,0,0!==o.t?o:o.next)},!0),d=i.prototype=new t,d.constructor=i,d.getRatio=function(t){var e=this._prev;if(t>e.t){for(;e.next&&t>=e.t;)e=e.next;e=e.prev}else for(;e.prev&&e.t>=t;)e=e.prev;return this._prev=e,e.v+(t-e.t)/e.gap*e.c},d.config=function(t){return new i(t)},i.ease=new i,u("Bounce",l("BounceOut",function(t){return 1/2.75>t?7.5625*t*t:2/2.75>t?7.5625*(t-=1.5/2.75)*t+.75:2.5/2.75>t?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375}),l("BounceIn",function(t){return 1/2.75>(t=1-t)?1-7.5625*t*t:2/2.75>t?1-(7.5625*(t-=1.5/2.75)*t+.75):2.5/2.75>t?1-(7.5625*(t-=2.25/2.75)*t+.9375):1-(7.5625*(t-=2.625/2.75)*t+.984375)}),l("BounceInOut",function(t){var e=.5>t;return t=e?1-2*t:2*t-1,t=1/2.75>t?7.5625*t*t:2/2.75>t?7.5625*(t-=1.5/2.75)*t+.75:2.5/2.75>t?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375,e?.5*(1-t):.5*t+.5})),u("Circ",l("CircOut",function(t){return Math.sqrt(1-(t-=1)*t)}),l("CircIn",function(t){return-(Math.sqrt(1-t*t)-1)}),l("CircInOut",function(t){return 1>(t*=2)?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)})),s=function(e,i,s){var r=h("easing."+e,function(t,e){this._p1=t||1,this._p2=e||s,this._p3=this._p2/a*(Math.asin(1/this._p1)||0)},!0),n=r.prototype=new t;return n.constructor=r,n.getRatio=i,n.config=function(t,e){return new r(t,e)},r},u("Elastic",s("ElasticOut",function(t){return this._p1*Math.pow(2,-10*t)*Math.sin((t-this._p3)*a/this._p2)+1},.3),s("ElasticIn",function(t){return-(this._p1*Math.pow(2,10*(t-=1))*Math.sin((t-this._p3)*a/this._p2))},.3),s("ElasticInOut",function(t){return 1>(t*=2)?-.5*this._p1*Math.pow(2,10*(t-=1))*Math.sin((t-this._p3)*a/this._p2):.5*this._p1*Math.pow(2,-10*(t-=1))*Math.sin((t-this._p3)*a/this._p2)+1},.45)),u("Expo",l("ExpoOut",function(t){return 1-Math.pow(2,-10*t)}),l("ExpoIn",function(t){return Math.pow(2,10*(t-1))-.001}),l("ExpoInOut",function(t){return 1>(t*=2)?.5*Math.pow(2,10*(t-1)):.5*(2-Math.pow(2,-10*(t-1)))})),u("Sine",l("SineOut",function(t){return Math.sin(t*o)}),l("SineIn",function(t){return-Math.cos(t*o)+1}),l("SineInOut",function(t){return-.5*(Math.cos(Math.PI*t)-1)})),h("easing.EaseLookup",{find:function(e){return t.map[e]}},!0),_(r.SlowMo,"SlowMo","ease,"),_(i,"RoughEase","ease,"),_(e,"SteppedEase","ease,"),f},!0)}),_gsScope._gsDefine&&_gsScope._gsQueue.pop()(); \ No newline at end of file diff --git a/admin-core/src/main/resources/static/plugins/sideshow/js/TweenLite.min.js b/admin-core/src/main/resources/static/plugins/sideshow/js/TweenLite.min.js new file mode 100644 index 0000000000000000000000000000000000000000..1d40adeb57d51763bbd486b9b0a763c014d51d5f --- /dev/null +++ b/admin-core/src/main/resources/static/plugins/sideshow/js/TweenLite.min.js @@ -0,0 +1,12 @@ +/*! + * VERSION: 1.13.1 + * DATE: 2014-07-22 + * UPDATES AND DOCS AT: http://www.greensock.com + * + * @license Copyright (c) 2008-2014, GreenSock. All rights reserved. + * This work is subject to the terms at http://www.greensock.com/terms_of_use.html or for + * Club GreenSock members, the software agreement that was issued with your membership. + * + * @author: Jack Doyle, jack@greensock.com + */ +(function(t,e){"use strict";var i=t.GreenSockGlobals=t.GreenSockGlobals||t;if(!i.TweenLite){var s,n,r,a,o,l=function(t){var e,s=t.split("."),n=i;for(e=0;s.length>e;e++)n[s[e]]=n=n[s[e]]||{};return n},h=l("com.greensock"),_=1e-10,u=function(t){var e,i=[],s=t.length;for(e=0;e!==s;i.push(t[e++]));return i},f=function(){},m=function(){var t=Object.prototype.toString,e=t.call([]);return function(i){return null!=i&&(i instanceof Array||"object"==typeof i&&!!i.push&&t.call(i)===e)}}(),p={},c=function(s,n,r,a){this.sc=p[s]?p[s].sc:[],p[s]=this,this.gsClass=null,this.func=r;var o=[];this.check=function(h){for(var _,u,f,m,d=n.length,v=d;--d>-1;)(_=p[n[d]]||new c(n[d],[])).gsClass?(o[d]=_.gsClass,v--):h&&_.sc.push(this);if(0===v&&r)for(u=("com.greensock."+s).split("."),f=u.pop(),m=l(u.join("."))[f]=this.gsClass=r.apply(r,o),a&&(i[f]=m,"function"==typeof define&&define.amd?define((t.GreenSockAMDPath?t.GreenSockAMDPath+"/":"")+s.split(".").pop(),[],function(){return m}):s===e&&"undefined"!=typeof module&&module.exports&&(module.exports=m)),d=0;this.sc.length>d;d++)this.sc[d].check()},this.check(!0)},d=t._gsDefine=function(t,e,i,s){return new c(t,e,i,s)},v=h._class=function(t,e,i){return e=e||function(){},d(t,[],function(){return e},i),e};d.globals=i;var g=[0,0,1,1],T=[],y=v("easing.Ease",function(t,e,i,s){this._func=t,this._type=i||0,this._power=s||0,this._params=e?g.concat(e):g},!0),w=y.map={},P=y.register=function(t,e,i,s){for(var n,r,a,o,l=e.split(","),_=l.length,u=(i||"easeIn,easeOut,easeInOut").split(",");--_>-1;)for(r=l[_],n=s?v("easing."+r,null,!0):h.easing[r]||{},a=u.length;--a>-1;)o=u[a],w[r+"."+o]=w[o+r]=n[o]=t.getRatio?t:t[o]||new t};for(r=y.prototype,r._calcEnd=!1,r.getRatio=function(t){if(this._func)return this._params[0]=t,this._func.apply(null,this._params);var e=this._type,i=this._power,s=1===e?1-t:2===e?t:.5>t?2*t:2*(1-t);return 1===i?s*=s:2===i?s*=s*s:3===i?s*=s*s*s:4===i&&(s*=s*s*s*s),1===e?1-s:2===e?s:.5>t?s/2:1-s/2},s=["Linear","Quad","Cubic","Quart","Quint,Strong"],n=s.length;--n>-1;)r=s[n]+",Power"+n,P(new y(null,null,1,n),r,"easeOut",!0),P(new y(null,null,2,n),r,"easeIn"+(0===n?",easeNone":"")),P(new y(null,null,3,n),r,"easeInOut");w.linear=h.easing.Linear.easeIn,w.swing=h.easing.Quad.easeInOut;var b=v("events.EventDispatcher",function(t){this._listeners={},this._eventTarget=t||this});r=b.prototype,r.addEventListener=function(t,e,i,s,n){n=n||0;var r,l,h=this._listeners[t],_=0;for(null==h&&(this._listeners[t]=h=[]),l=h.length;--l>-1;)r=h[l],r.c===e&&r.s===i?h.splice(l,1):0===_&&n>r.pr&&(_=l+1);h.splice(_,0,{c:e,s:i,up:s,pr:n}),this!==a||o||a.wake()},r.removeEventListener=function(t,e){var i,s=this._listeners[t];if(s)for(i=s.length;--i>-1;)if(s[i].c===e)return s.splice(i,1),void 0},r.dispatchEvent=function(t){var e,i,s,n=this._listeners[t];if(n)for(e=n.length,i=this._eventTarget;--e>-1;)s=n[e],s.up?s.c.call(s.s||i,{type:t,target:i}):s.c.call(s.s||i)};var k=t.requestAnimationFrame,A=t.cancelAnimationFrame,S=Date.now||function(){return(new Date).getTime()},x=S();for(s=["ms","moz","webkit","o"],n=s.length;--n>-1&&!k;)k=t[s[n]+"RequestAnimationFrame"],A=t[s[n]+"CancelAnimationFrame"]||t[s[n]+"CancelRequestAnimationFrame"];v("Ticker",function(t,e){var i,s,n,r,l,h=this,u=S(),m=e!==!1&&k,p=500,c=33,d=function(t){var e,a,o=S()-x;o>p&&(u+=o-c),x+=o,h.time=(x-u)/1e3,e=h.time-l,(!i||e>0||t===!0)&&(h.frame++,l+=e+(e>=r?.004:r-e),a=!0),t!==!0&&(n=s(d)),a&&h.dispatchEvent("tick")};b.call(h),h.time=h.frame=0,h.tick=function(){d(!0)},h.lagSmoothing=function(t,e){p=t||1/_,c=Math.min(e,p,0)},h.sleep=function(){null!=n&&(m&&A?A(n):clearTimeout(n),s=f,n=null,h===a&&(o=!1))},h.wake=function(){null!==n?h.sleep():h.frame>10&&(x=S()-p+5),s=0===i?f:m&&k?k:function(t){return setTimeout(t,0|1e3*(l-h.time)+1)},h===a&&(o=!0),d(2)},h.fps=function(t){return arguments.length?(i=t,r=1/(i||60),l=this.time+r,h.wake(),void 0):i},h.useRAF=function(t){return arguments.length?(h.sleep(),m=t,h.fps(i),void 0):m},h.fps(t),setTimeout(function(){m&&(!n||5>h.frame)&&h.useRAF(!1)},1500)}),r=h.Ticker.prototype=new h.events.EventDispatcher,r.constructor=h.Ticker;var C=v("core.Animation",function(t,e){if(this.vars=e=e||{},this._duration=this._totalDuration=t||0,this._delay=Number(e.delay)||0,this._timeScale=1,this._active=e.immediateRender===!0,this.data=e.data,this._reversed=e.reversed===!0,B){o||a.wake();var i=this.vars.useFrames?q:B;i.add(this,i._time),this.vars.paused&&this.paused(!0)}});a=C.ticker=new h.Ticker,r=C.prototype,r._dirty=r._gc=r._initted=r._paused=!1,r._totalTime=r._time=0,r._rawPrevTime=-1,r._next=r._last=r._onUpdate=r._timeline=r.timeline=null,r._paused=!1;var R=function(){o&&S()-x>2e3&&a.wake(),setTimeout(R,2e3)};R(),r.play=function(t,e){return null!=t&&this.seek(t,e),this.reversed(!1).paused(!1)},r.pause=function(t,e){return null!=t&&this.seek(t,e),this.paused(!0)},r.resume=function(t,e){return null!=t&&this.seek(t,e),this.paused(!1)},r.seek=function(t,e){return this.totalTime(Number(t),e!==!1)},r.restart=function(t,e){return this.reversed(!1).paused(!1).totalTime(t?-this._delay:0,e!==!1,!0)},r.reverse=function(t,e){return null!=t&&this.seek(t||this.totalDuration(),e),this.reversed(!0).paused(!1)},r.render=function(){},r.invalidate=function(){return this},r.isActive=function(){var t,e=this._timeline,i=this._startTime;return!e||!this._gc&&!this._paused&&e.isActive()&&(t=e.rawTime())>=i&&i+this.totalDuration()/this._timeScale>t},r._enabled=function(t,e){return o||a.wake(),this._gc=!t,this._active=this.isActive(),e!==!0&&(t&&!this.timeline?this._timeline.add(this,this._startTime-this._delay):!t&&this.timeline&&this._timeline._remove(this,!0)),!1},r._kill=function(){return this._enabled(!1,!1)},r.kill=function(t,e){return this._kill(t,e),this},r._uncache=function(t){for(var e=t?this:this.timeline;e;)e._dirty=!0,e=e.timeline;return this},r._swapSelfInParams=function(t){for(var e=t.length,i=t.concat();--e>-1;)"{self}"===t[e]&&(i[e]=this);return i},r.eventCallback=function(t,e,i,s){if("on"===(t||"").substr(0,2)){var n=this.vars;if(1===arguments.length)return n[t];null==e?delete n[t]:(n[t]=e,n[t+"Params"]=m(i)&&-1!==i.join("").indexOf("{self}")?this._swapSelfInParams(i):i,n[t+"Scope"]=s),"onUpdate"===t&&(this._onUpdate=e)}return this},r.delay=function(t){return arguments.length?(this._timeline.smoothChildTiming&&this.startTime(this._startTime+t-this._delay),this._delay=t,this):this._delay},r.duration=function(t){return arguments.length?(this._duration=this._totalDuration=t,this._uncache(!0),this._timeline.smoothChildTiming&&this._time>0&&this._timethis._duration?this._duration:t,e)):this._time},r.totalTime=function(t,e,i){if(o||a.wake(),!arguments.length)return this._totalTime;if(this._timeline){if(0>t&&!i&&(t+=this.totalDuration()),this._timeline.smoothChildTiming){this._dirty&&this.totalDuration();var s=this._totalDuration,n=this._timeline;if(t>s&&!i&&(t=s),this._startTime=(this._paused?this._pauseTime:n._time)-(this._reversed?s-t:t)/this._timeScale,n._dirty||this._uncache(!1),n._timeline)for(;n._timeline;)n._timeline._time!==(n._startTime+n._totalTime)/n._timeScale&&n.totalTime(n._totalTime,!0),n=n._timeline}this._gc&&this._enabled(!0,!1),(this._totalTime!==t||0===this._duration)&&(this.render(t,e,!1),O.length&&M())}return this},r.progress=r.totalProgress=function(t,e){return arguments.length?this.totalTime(this.duration()*t,e):this._time/this.duration()},r.startTime=function(t){return arguments.length?(t!==this._startTime&&(this._startTime=t,this.timeline&&this.timeline._sortChildren&&this.timeline.add(this,t-this._delay)),this):this._startTime},r.timeScale=function(t){if(!arguments.length)return this._timeScale;if(t=t||_,this._timeline&&this._timeline.smoothChildTiming){var e=this._pauseTime,i=e||0===e?e:this._timeline.totalTime();this._startTime=i-(i-this._startTime)*this._timeScale/t}return this._timeScale=t,this._uncache(!1)},r.reversed=function(t){return arguments.length?(t!=this._reversed&&(this._reversed=t,this.totalTime(this._timeline&&!this._timeline.smoothChildTiming?this.totalDuration()-this._totalTime:this._totalTime,!0)),this):this._reversed},r.paused=function(t){if(!arguments.length)return this._paused;if(t!=this._paused&&this._timeline){o||t||a.wake();var e=this._timeline,i=e.rawTime(),s=i-this._pauseTime;!t&&e.smoothChildTiming&&(this._startTime+=s,this._uncache(!1)),this._pauseTime=t?i:null,this._paused=t,this._active=this.isActive(),!t&&0!==s&&this._initted&&this.duration()&&this.render(e.smoothChildTiming?this._totalTime:(i-this._startTime)/this._timeScale,!0,!0)}return this._gc&&!t&&this._enabled(!0,!1),this};var D=v("core.SimpleTimeline",function(t){C.call(this,0,t),this.autoRemoveChildren=this.smoothChildTiming=!0});r=D.prototype=new C,r.constructor=D,r.kill()._gc=!1,r._first=r._last=null,r._sortChildren=!1,r.add=r.insert=function(t,e){var i,s;if(t._startTime=Number(e||0)+t._delay,t._paused&&this!==t._timeline&&(t._pauseTime=t._startTime+(this.rawTime()-t._startTime)/t._timeScale),t.timeline&&t.timeline._remove(t,!0),t.timeline=t._timeline=this,t._gc&&t._enabled(!0,!0),i=this._last,this._sortChildren)for(s=t._startTime;i&&i._startTime>s;)i=i._prev;return i?(t._next=i._next,i._next=t):(t._next=this._first,this._first=t),t._next?t._next._prev=t:this._last=t,t._prev=i,this._timeline&&this._uncache(!0),this},r._remove=function(t,e){return t.timeline===this&&(e||t._enabled(!1,!0),t._prev?t._prev._next=t._next:this._first===t&&(this._first=t._next),t._next?t._next._prev=t._prev:this._last===t&&(this._last=t._prev),t._next=t._prev=t.timeline=null,this._timeline&&this._uncache(!0)),this},r.render=function(t,e,i){var s,n=this._first;for(this._totalTime=this._time=this._rawPrevTime=t;n;)s=n._next,(n._active||t>=n._startTime&&!n._paused)&&(n._reversed?n.render((n._dirty?n.totalDuration():n._totalDuration)-(t-n._startTime)*n._timeScale,e,i):n.render((t-n._startTime)*n._timeScale,e,i)),n=s},r.rawTime=function(){return o||a.wake(),this._totalTime};var I=v("TweenLite",function(e,i,s){if(C.call(this,i,s),this.render=I.prototype.render,null==e)throw"Cannot tween a null target.";this.target=e="string"!=typeof e?e:I.selector(e)||e;var n,r,a,o=e.jquery||e.length&&e!==t&&e[0]&&(e[0]===t||e[0].nodeType&&e[0].style&&!e.nodeType),l=this.vars.overwrite;if(this._overwrite=l=null==l?Q[I.defaultOverwrite]:"number"==typeof l?l>>0:Q[l],(o||e instanceof Array||e.push&&m(e))&&"number"!=typeof e[0])for(this._targets=a=u(e),this._propLookup=[],this._siblings=[],n=0;a.length>n;n++)r=a[n],r?"string"!=typeof r?r.length&&r!==t&&r[0]&&(r[0]===t||r[0].nodeType&&r[0].style&&!r.nodeType)?(a.splice(n--,1),this._targets=a=a.concat(u(r))):(this._siblings[n]=$(r,this,!1),1===l&&this._siblings[n].length>1&&K(r,this,null,1,this._siblings[n])):(r=a[n--]=I.selector(r),"string"==typeof r&&a.splice(n+1,1)):a.splice(n--,1);else this._propLookup={},this._siblings=$(e,this,!1),1===l&&this._siblings.length>1&&K(e,this,null,1,this._siblings);(this.vars.immediateRender||0===i&&0===this._delay&&this.vars.immediateRender!==!1)&&(this._time=-_,this.render(-this._delay))},!0),E=function(e){return e.length&&e!==t&&e[0]&&(e[0]===t||e[0].nodeType&&e[0].style&&!e.nodeType)},z=function(t,e){var i,s={};for(i in t)G[i]||i in e&&"transform"!==i&&"x"!==i&&"y"!==i&&"width"!==i&&"height"!==i&&"className"!==i&&"border"!==i||!(!U[i]||U[i]&&U[i]._autoCSS)||(s[i]=t[i],delete t[i]);t.css=s};r=I.prototype=new C,r.constructor=I,r.kill()._gc=!1,r.ratio=0,r._firstPT=r._targets=r._overwrittenProps=r._startAt=null,r._notifyPluginsOfEnabled=r._lazy=!1,I.version="1.13.1",I.defaultEase=r._ease=new y(null,null,1,1),I.defaultOverwrite="auto",I.ticker=a,I.autoSleep=!0,I.lagSmoothing=function(t,e){a.lagSmoothing(t,e)},I.selector=t.$||t.jQuery||function(e){var i=t.$||t.jQuery;return i?(I.selector=i,i(e)):"undefined"==typeof document?e:document.querySelectorAll?document.querySelectorAll(e):document.getElementById("#"===e.charAt(0)?e.substr(1):e)};var O=[],L={},N=I._internals={isArray:m,isSelector:E,lazyTweens:O},U=I._plugins={},F=N.tweenLookup={},j=0,G=N.reservedProps={ease:1,delay:1,overwrite:1,onComplete:1,onCompleteParams:1,onCompleteScope:1,useFrames:1,runBackwards:1,startAt:1,onUpdate:1,onUpdateParams:1,onUpdateScope:1,onStart:1,onStartParams:1,onStartScope:1,onReverseComplete:1,onReverseCompleteParams:1,onReverseCompleteScope:1,onRepeat:1,onRepeatParams:1,onRepeatScope:1,easeParams:1,yoyo:1,immediateRender:1,repeat:1,repeatDelay:1,data:1,paused:1,reversed:1,autoCSS:1,lazy:1},Q={none:0,all:1,auto:2,concurrent:3,allOnStart:4,preexisting:5,"true":1,"false":0},q=C._rootFramesTimeline=new D,B=C._rootTimeline=new D,M=N.lazyRender=function(){var t=O.length;for(L={};--t>-1;)s=O[t],s&&s._lazy!==!1&&(s.render(s._lazy,!1,!0),s._lazy=!1);O.length=0};B._startTime=a.time,q._startTime=a.frame,B._active=q._active=!0,setTimeout(M,1),C._updateRoot=I.render=function(){var t,e,i;if(O.length&&M(),B.render((a.time-B._startTime)*B._timeScale,!1,!1),q.render((a.frame-q._startTime)*q._timeScale,!1,!1),O.length&&M(),!(a.frame%120)){for(i in F){for(e=F[i].tweens,t=e.length;--t>-1;)e[t]._gc&&e.splice(t,1);0===e.length&&delete F[i]}if(i=B._first,(!i||i._paused)&&I.autoSleep&&!q._first&&1===a._listeners.tick.length){for(;i&&i._paused;)i=i._next;i||a.sleep()}}},a.addEventListener("tick",C._updateRoot);var $=function(t,e,i){var s,n,r=t._gsTweenID;if(F[r||(t._gsTweenID=r="t"+j++)]||(F[r]={target:t,tweens:[]}),e&&(s=F[r].tweens,s[n=s.length]=e,i))for(;--n>-1;)s[n]===e&&s.splice(n,1);return F[r].tweens},K=function(t,e,i,s,n){var r,a,o,l;if(1===s||s>=4){for(l=n.length,r=0;l>r;r++)if((o=n[r])!==e)o._gc||o._enabled(!1,!1)&&(a=!0);else if(5===s)break;return a}var h,u=e._startTime+_,f=[],m=0,p=0===e._duration;for(r=n.length;--r>-1;)(o=n[r])===e||o._gc||o._paused||(o._timeline!==e._timeline?(h=h||H(e,0,p),0===H(o,h,p)&&(f[m++]=o)):u>=o._startTime&&o._startTime+o.totalDuration()/o._timeScale>u&&((p||!o._initted)&&2e-10>=u-o._startTime||(f[m++]=o)));for(r=m;--r>-1;)o=f[r],2===s&&o._kill(i,t)&&(a=!0),(2!==s||!o._firstPT&&o._initted)&&o._enabled(!1,!1)&&(a=!0);return a},H=function(t,e,i){for(var s=t._timeline,n=s._timeScale,r=t._startTime;s._timeline;){if(r+=s._startTime,n*=s._timeScale,s._paused)return-100;s=s._timeline}return r/=n,r>e?r-e:i&&r===e||!t._initted&&2*_>r-e?_:(r+=t.totalDuration()/t._timeScale/n)>e+_?0:r-e-_};r._init=function(){var t,e,i,s,n,r=this.vars,a=this._overwrittenProps,o=this._duration,l=!!r.immediateRender,h=r.ease;if(r.startAt){this._startAt&&(this._startAt.render(-1,!0),this._startAt.kill()),n={};for(s in r.startAt)n[s]=r.startAt[s];if(n.overwrite=!1,n.immediateRender=!0,n.lazy=l&&r.lazy!==!1,n.startAt=n.delay=null,this._startAt=I.to(this.target,0,n),l)if(this._time>0)this._startAt=null;else if(0!==o)return}else if(r.runBackwards&&0!==o)if(this._startAt)this._startAt.render(-1,!0),this._startAt.kill(),this._startAt=null;else{i={};for(s in r)G[s]&&"autoCSS"!==s||(i[s]=r[s]);if(i.overwrite=0,i.data="isFromStart",i.lazy=l&&r.lazy!==!1,i.immediateRender=l,this._startAt=I.to(this.target,0,i),l){if(0===this._time)return}else this._startAt._init(),this._startAt._enabled(!1)}if(this._ease=h=h?h instanceof y?h:"function"==typeof h?new y(h,r.easeParams):w[h]||I.defaultEase:I.defaultEase,r.easeParams instanceof Array&&h.config&&(this._ease=h.config.apply(h,r.easeParams)),this._easeType=this._ease._type,this._easePower=this._ease._power,this._firstPT=null,this._targets)for(t=this._targets.length;--t>-1;)this._initProps(this._targets[t],this._propLookup[t]={},this._siblings[t],a?a[t]:null)&&(e=!0);else e=this._initProps(this.target,this._propLookup,this._siblings,a);if(e&&I._onPluginEvent("_onInitAllProps",this),a&&(this._firstPT||"function"!=typeof this.target&&this._enabled(!1,!1)),r.runBackwards)for(i=this._firstPT;i;)i.s+=i.c,i.c=-i.c,i=i._next;this._onUpdate=r.onUpdate,this._initted=!0},r._initProps=function(e,i,s,n){var r,a,o,l,h,_;if(null==e)return!1;L[e._gsTweenID]&&M(),this.vars.css||e.style&&e!==t&&e.nodeType&&U.css&&this.vars.autoCSS!==!1&&z(this.vars,e);for(r in this.vars){if(_=this.vars[r],G[r])_&&(_ instanceof Array||_.push&&m(_))&&-1!==_.join("").indexOf("{self}")&&(this.vars[r]=_=this._swapSelfInParams(_,this));else if(U[r]&&(l=new U[r])._onInitTween(e,this.vars[r],this)){for(this._firstPT=h={_next:this._firstPT,t:l,p:"setRatio",s:0,c:1,f:!0,n:r,pg:!0,pr:l._priority},a=l._overwriteProps.length;--a>-1;)i[l._overwriteProps[a]]=this._firstPT;(l._priority||l._onInitAllProps)&&(o=!0),(l._onDisable||l._onEnable)&&(this._notifyPluginsOfEnabled=!0)}else this._firstPT=i[r]=h={_next:this._firstPT,t:e,p:r,f:"function"==typeof e[r],n:r,pg:!1,pr:0},h.s=h.f?e[r.indexOf("set")||"function"!=typeof e["get"+r.substr(3)]?r:"get"+r.substr(3)]():parseFloat(e[r]),h.c="string"==typeof _&&"="===_.charAt(1)?parseInt(_.charAt(0)+"1",10)*Number(_.substr(2)):Number(_)-h.s||0;h&&h._next&&(h._next._prev=h)}return n&&this._kill(n,e)?this._initProps(e,i,s,n):this._overwrite>1&&this._firstPT&&s.length>1&&K(e,this,i,this._overwrite,s)?(this._kill(i,e),this._initProps(e,i,s,n)):(this._firstPT&&(this.vars.lazy!==!1&&this._duration||this.vars.lazy&&!this._duration)&&(L[e._gsTweenID]=!0),o)},r.render=function(t,e,i){var s,n,r,a,o=this._time,l=this._duration,h=this._rawPrevTime;if(t>=l)this._totalTime=this._time=l,this.ratio=this._ease._calcEnd?this._ease.getRatio(1):1,this._reversed||(s=!0,n="onComplete"),0===l&&(this._initted||!this.vars.lazy||i)&&(this._startTime===this._timeline._duration&&(t=0),(0===t||0>h||h===_)&&h!==t&&(i=!0,h>_&&(n="onReverseComplete")),this._rawPrevTime=a=!e||t||h===t?t:_);else if(1e-7>t)this._totalTime=this._time=0,this.ratio=this._ease._calcEnd?this._ease.getRatio(0):0,(0!==o||0===l&&h>0&&h!==_)&&(n="onReverseComplete",s=this._reversed),0>t?(this._active=!1,0===l&&(this._initted||!this.vars.lazy||i)&&(h>=0&&(i=!0),this._rawPrevTime=a=!e||t||h===t?t:_)):this._initted||(i=!0);else if(this._totalTime=this._time=t,this._easeType){var u=t/l,f=this._easeType,m=this._easePower;(1===f||3===f&&u>=.5)&&(u=1-u),3===f&&(u*=2),1===m?u*=u:2===m?u*=u*u:3===m?u*=u*u*u:4===m&&(u*=u*u*u*u),this.ratio=1===f?1-u:2===f?u:.5>t/l?u/2:1-u/2}else this.ratio=this._ease.getRatio(t/l);if(this._time!==o||i){if(!this._initted){if(this._init(),!this._initted||this._gc)return;if(!i&&this._firstPT&&(this.vars.lazy!==!1&&this._duration||this.vars.lazy&&!this._duration))return this._time=this._totalTime=o,this._rawPrevTime=h,O.push(this),this._lazy=t,void 0;this._time&&!s?this.ratio=this._ease.getRatio(this._time/l):s&&this._ease._calcEnd&&(this.ratio=this._ease.getRatio(0===this._time?0:1))}for(this._lazy!==!1&&(this._lazy=!1),this._active||!this._paused&&this._time!==o&&t>=0&&(this._active=!0),0===o&&(this._startAt&&(t>=0?this._startAt.render(t,e,i):n||(n="_dummyGS")),this.vars.onStart&&(0!==this._time||0===l)&&(e||this.vars.onStart.apply(this.vars.onStartScope||this,this.vars.onStartParams||T))),r=this._firstPT;r;)r.f?r.t[r.p](r.c*this.ratio+r.s):r.t[r.p]=r.c*this.ratio+r.s,r=r._next;this._onUpdate&&(0>t&&this._startAt&&this._startTime&&this._startAt.render(t,e,i),e||(this._time!==o||s)&&this._onUpdate.apply(this.vars.onUpdateScope||this,this.vars.onUpdateParams||T)),n&&(!this._gc||i)&&(0>t&&this._startAt&&!this._onUpdate&&this._startTime&&this._startAt.render(t,e,i),s&&(this._timeline.autoRemoveChildren&&this._enabled(!1,!1),this._active=!1),!e&&this.vars[n]&&this.vars[n].apply(this.vars[n+"Scope"]||this,this.vars[n+"Params"]||T),0===l&&this._rawPrevTime===_&&a!==_&&(this._rawPrevTime=0))}},r._kill=function(t,e){if("all"===t&&(t=null),null==t&&(null==e||e===this.target))return this._lazy=!1,this._enabled(!1,!1);e="string"!=typeof e?e||this._targets||this.target:I.selector(e)||e;var i,s,n,r,a,o,l,h;if((m(e)||E(e))&&"number"!=typeof e[0])for(i=e.length;--i>-1;)this._kill(t,e[i])&&(o=!0);else{if(this._targets){for(i=this._targets.length;--i>-1;)if(e===this._targets[i]){a=this._propLookup[i]||{},this._overwrittenProps=this._overwrittenProps||[],s=this._overwrittenProps[i]=t?this._overwrittenProps[i]||{}:"all";break}}else{if(e!==this.target)return!1;a=this._propLookup,s=this._overwrittenProps=t?this._overwrittenProps||{}:"all"}if(a){l=t||a,h=t!==s&&"all"!==s&&t!==a&&("object"!=typeof t||!t._tempKill);for(n in l)(r=a[n])&&(r.pg&&r.t._kill(l)&&(o=!0),r.pg&&0!==r.t._overwriteProps.length||(r._prev?r._prev._next=r._next:r===this._firstPT&&(this._firstPT=r._next),r._next&&(r._next._prev=r._prev),r._next=r._prev=null),delete a[n]),h&&(s[n]=1);!this._firstPT&&this._initted&&this._enabled(!1,!1)}}return o},r.invalidate=function(){return this._notifyPluginsOfEnabled&&I._onPluginEvent("_onDisable",this),this._firstPT=null,this._overwrittenProps=null,this._onUpdate=null,this._startAt=null,this._initted=this._active=this._notifyPluginsOfEnabled=this._lazy=!1,this._propLookup=this._targets?{}:[],this},r._enabled=function(t,e){if(o||a.wake(),t&&this._gc){var i,s=this._targets;if(s)for(i=s.length;--i>-1;)this._siblings[i]=$(s[i],this,!0);else this._siblings=$(this.target,this,!0)}return C.prototype._enabled.call(this,t,e),this._notifyPluginsOfEnabled&&this._firstPT?I._onPluginEvent(t?"_onEnable":"_onDisable",this):!1},I.to=function(t,e,i){return new I(t,e,i)},I.from=function(t,e,i){return i.runBackwards=!0,i.immediateRender=0!=i.immediateRender,new I(t,e,i)},I.fromTo=function(t,e,i,s){return s.startAt=i,s.immediateRender=0!=s.immediateRender&&0!=i.immediateRender,new I(t,e,s)},I.delayedCall=function(t,e,i,s,n){return new I(e,0,{delay:t,onComplete:e,onCompleteParams:i,onCompleteScope:s,onReverseComplete:e,onReverseCompleteParams:i,onReverseCompleteScope:s,immediateRender:!1,useFrames:n,overwrite:0})},I.set=function(t,e){return new I(t,0,e)},I.getTweensOf=function(t,e){if(null==t)return[];t="string"!=typeof t?t:I.selector(t)||t;var i,s,n,r;if((m(t)||E(t))&&"number"!=typeof t[0]){for(i=t.length,s=[];--i>-1;)s=s.concat(I.getTweensOf(t[i],e));for(i=s.length;--i>-1;)for(r=s[i],n=i;--n>-1;)r===s[n]&&s.splice(i,1)}else for(s=$(t).concat(),i=s.length;--i>-1;)(s[i]._gc||e&&!s[i].isActive())&&s.splice(i,1);return s},I.killTweensOf=I.killDelayedCallsTo=function(t,e,i){"object"==typeof e&&(i=e,e=!1);for(var s=I.getTweensOf(t,e),n=s.length;--n>-1;)s[n]._kill(i,t)};var J=v("plugins.TweenPlugin",function(t,e){this._overwriteProps=(t||"").split(","),this._propName=this._overwriteProps[0],this._priority=e||0,this._super=J.prototype},!0);if(r=J.prototype,J.version="1.10.1",J.API=2,r._firstPT=null,r._addTween=function(t,e,i,s,n,r){var a,o;return null!=s&&(a="number"==typeof s||"="!==s.charAt(1)?Number(s)-i:parseInt(s.charAt(0)+"1",10)*Number(s.substr(2)))?(this._firstPT=o={_next:this._firstPT,t:t,p:e,s:i,c:a,f:"function"==typeof t[e],n:n||e,r:r},o._next&&(o._next._prev=o),o):void 0},r.setRatio=function(t){for(var e,i=this._firstPT,s=1e-6;i;)e=i.c*t+i.s,i.r?e=Math.round(e):s>e&&e>-s&&(e=0),i.f?i.t[i.p](e):i.t[i.p]=e,i=i._next},r._kill=function(t){var e,i=this._overwriteProps,s=this._firstPT;if(null!=t[this._propName])this._overwriteProps=[];else for(e=i.length;--e>-1;)null!=t[i[e]]&&i.splice(e,1);for(;s;)null!=t[s.n]&&(s._next&&(s._next._prev=s._prev),s._prev?(s._prev._next=s._next,s._prev=null):this._firstPT===s&&(this._firstPT=s._next)),s=s._next;return!1},r._roundProps=function(t,e){for(var i=this._firstPT;i;)(t[this._propName]||null!=i.n&&t[i.n.split(this._propName+"_").join("")])&&(i.r=e),i=i._next},I._onPluginEvent=function(t,e){var i,s,n,r,a,o=e._firstPT;if("_onInitAllProps"===t){for(;o;){for(a=o._next,s=n;s&&s.pr>o.pr;)s=s._next;(o._prev=s?s._prev:r)?o._prev._next=o:n=o,(o._next=s)?s._prev=o:r=o,o=a}o=e._firstPT=n}for(;o;)o.pg&&"function"==typeof o.t[t]&&o.t[t]()&&(i=!0),o=o._next;return i},J.activate=function(t){for(var e=t.length;--e>-1;)t[e].API===J.API&&(U[(new t[e])._propName]=t[e]);return!0},d.plugin=function(t){if(!(t&&t.propName&&t.init&&t.API))throw"illegal plugin definition.";var e,i=t.propName,s=t.priority||0,n=t.overwriteProps,r={init:"_onInitTween",set:"setRatio",kill:"_kill",round:"_roundProps",initAll:"_onInitAllProps"},a=v("plugins."+i.charAt(0).toUpperCase()+i.substr(1)+"Plugin",function(){J.call(this,i,s),this._overwriteProps=n||[]},t.global===!0),o=a.prototype=new J(i);o.constructor=a,a.API=t.API;for(e in r)"function"==typeof t[e]&&(o[r[e]]=t[e]);return a.version=t.version,J.activate([a]),a},s=t._gsQueue){for(n=0;s.length>n;n++)s[n]();for(r in p)p[r].func||t.console.log("GSAP encountered missing dependency: com.greensock."+r)}o=!1}})("undefined"!=typeof module&&module.exports&&"undefined"!=typeof global?global:this||window,"TweenLite"); \ No newline at end of file diff --git a/admin-core/src/main/resources/static/plugins/sideshow/js/demo-1.js b/admin-core/src/main/resources/static/plugins/sideshow/js/demo-1.js new file mode 100644 index 0000000000000000000000000000000000000000..57ed6d7cd40e764f206940c1247003fd399736d2 --- /dev/null +++ b/admin-core/src/main/resources/static/plugins/sideshow/js/demo-1.js @@ -0,0 +1,185 @@ +(function() { + + var width, height, largeHeader, canvas, ctx, points, target, animateHeader = true; + + // Main + initHeader(); + initAnimation(); + addListeners(); + + function initHeader() { + width = window.innerWidth; + height = window.innerHeight; + target = {x: width/2, y: height/2}; + + largeHeader = document.getElementById('large-header'); + largeHeader.style.height = height+'px'; + + canvas = document.getElementById('demo-canvas'); + canvas.width = width; + canvas.height = height; + ctx = canvas.getContext('2d'); + + // create points + points = []; + for(var x = 0; x < width; x = x + width/20) { + for(var y = 0; y < height; y = y + height/20) { + var px = x + Math.random()*width/20; + var py = y + Math.random()*height/20; + var p = {x: px, originX: px, y: py, originY: py }; + points.push(p); + } + } + + // for each point find the 5 closest points + for(var i = 0; i < points.length; i++) { + var closest = []; + var p1 = points[i]; + for(var j = 0; j < points.length; j++) { + var p2 = points[j] + if(!(p1 == p2)) { + var placed = false; + for(var k = 0; k < 5; k++) { + if(!placed) { + if(closest[k] == undefined) { + closest[k] = p2; + placed = true; + } + } + } + + for(var k = 0; k < 5; k++) { + if(!placed) { + if(getDistance(p1, p2) < getDistance(p1, closest[k])) { + closest[k] = p2; + placed = true; + } + } + } + } + } + p1.closest = closest; + } + + // assign a circle to each point + for(var i in points) { + var c = new Circle(points[i], 2+Math.random()*2, 'rgba(255,255,255,0.3)'); + points[i].circle = c; + } + } + + // Event handling + function addListeners() { + if(!('ontouchstart' in window)) { + window.addEventListener('mousemove', mouseMove); + } + window.addEventListener('scroll', scrollCheck); + window.addEventListener('resize', resize); + } + + function mouseMove(e) { + var posx = posy = 0; + if (e.pageX || e.pageY) { + posx = e.pageX; + posy = e.pageY; + } + else if (e.clientX || e.clientY) { + posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; + posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; + } + target.x = posx; + target.y = posy; + } + + function scrollCheck() { + if(document.body.scrollTop > height) animateHeader = false; + else animateHeader = true; + } + + function resize() { + width = window.innerWidth; + height = window.innerHeight; + largeHeader.style.height = height+'px'; + canvas.width = width; + canvas.height = height; + } + + // animation + function initAnimation() { + animate(); + for(var i in points) { + shiftPoint(points[i]); + } + } + + function animate() { + if(animateHeader) { + ctx.clearRect(0,0,width,height); + for(var i in points) { + // detect points in range + if(Math.abs(getDistance(target, points[i])) < 4000) { + points[i].active = 0.3; + points[i].circle.active = 0.6; + } else if(Math.abs(getDistance(target, points[i])) < 20000) { + points[i].active = 0.1; + points[i].circle.active = 0.3; + } else if(Math.abs(getDistance(target, points[i])) < 40000) { + points[i].active = 0.02; + points[i].circle.active = 0.1; + } else { + points[i].active = 0; + points[i].circle.active = 0; + } + + drawLines(points[i]); + points[i].circle.draw(); + } + } + requestAnimationFrame(animate); + } + + function shiftPoint(p) { + TweenLite.to(p, 1+1*Math.random(), {x:p.originX-50+Math.random()*100, + y: p.originY-50+Math.random()*100, ease:Circ.easeInOut, + onComplete: function() { + shiftPoint(p); + }}); + } + + // Canvas manipulation + function drawLines(p) { + if(!p.active) return; + for(var i in p.closest) { + ctx.beginPath(); + ctx.moveTo(p.x, p.y); + ctx.lineTo(p.closest[i].x, p.closest[i].y); + ctx.strokeStyle = 'rgba(156,217,249,'+ p.active+')'; + ctx.stroke(); + } + } + + function Circle(pos,rad,color) { + var _this = this; + + // constructor + (function() { + _this.pos = pos || null; + _this.radius = rad || null; + _this.color = color || null; + })(); + + this.draw = function() { + if(!_this.active) return; + ctx.beginPath(); + ctx.arc(_this.pos.x, _this.pos.y, _this.radius, 0, 2 * Math.PI, false); + ctx.fillStyle = 'rgba(156,217,249,'+ _this.active+')'; + ctx.fill(); + }; + } + + // Util + function getDistance(p1, p2) { + return Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2); + } + +})(); \ No newline at end of file diff --git a/admin-core/src/main/resources/static/plugins/sideshow/js/rAF.js b/admin-core/src/main/resources/static/plugins/sideshow/js/rAF.js new file mode 100644 index 0000000000000000000000000000000000000000..e1f1999239bb3d4d4f54da0aa3b5ea726171d9c9 --- /dev/null +++ b/admin-core/src/main/resources/static/plugins/sideshow/js/rAF.js @@ -0,0 +1,31 @@ +// http://paulirish.com/2011/requestanimationframe-for-smart-animating/ +// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating + +// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel + +// MIT license + +(function() { + var lastTime = 0; + var vendors = ['ms', 'moz', 'webkit', 'o']; + for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { + window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; + window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] + || window[vendors[x]+'CancelRequestAnimationFrame']; + } + + if (!window.requestAnimationFrame) + window.requestAnimationFrame = function(callback, element) { + var currTime = new Date().getTime(); + var timeToCall = Math.max(0, 16 - (currTime - lastTime)); + var id = window.setTimeout(function() { callback(currTime + timeToCall); }, + timeToCall); + lastTime = currTime + timeToCall; + return id; + }; + + if (!window.cancelAnimationFrame) + window.cancelAnimationFrame = function(id) { + clearTimeout(id); + }; +}()); \ No newline at end of file diff --git a/admin-core/src/main/resources/static/plugins/wangEditor3/fonts/w-e-icon.woff b/admin-core/src/main/resources/static/plugins/wangEditor3/fonts/w-e-icon.woff new file mode 100644 index 0000000000000000000000000000000000000000..6dc5b5a33ab856629748dba686540870da73e89f Binary files /dev/null and b/admin-core/src/main/resources/static/plugins/wangEditor3/fonts/w-e-icon.woff differ diff --git a/admin-core/src/main/resources/static/plugins/wangEditor3/wangEditor.css b/admin-core/src/main/resources/static/plugins/wangEditor3/wangEditor.css new file mode 100644 index 0000000000000000000000000000000000000000..5502c553ff701ec0837ea4b0d521a90315d39e19 --- /dev/null +++ b/admin-core/src/main/resources/static/plugins/wangEditor3/wangEditor.css @@ -0,0 +1,411 @@ +.w-e-toolbar, +.w-e-text-container, +.w-e-menu-panel { + padding: 0; + margin: 0; + box-sizing: border-box; +} +.w-e-toolbar *, +.w-e-text-container *, +.w-e-menu-panel * { + padding: 0; + margin: 0; + box-sizing: border-box; +} +.w-e-clear-fix:after { + content: ""; + display: table; + clear: both; +} + +.w-e-toolbar .w-e-droplist { + position: absolute; + left: 0; + top: 0; + background-color: #fff; + border: 1px solid #f1f1f1; + border-right-color: #ccc; + border-bottom-color: #ccc; +} +.w-e-toolbar .w-e-droplist .w-e-dp-title { + text-align: center; + color: #999; + line-height: 2; + border-bottom: 1px solid #f1f1f1; + font-size: 13px; +} +.w-e-toolbar .w-e-droplist ul.w-e-list { + list-style: none; + line-height: 1; +} +.w-e-toolbar .w-e-droplist ul.w-e-list li.w-e-item { + color: #333; + padding: 5px 0; +} +.w-e-toolbar .w-e-droplist ul.w-e-list li.w-e-item:hover { + background-color: #f1f1f1; +} +.w-e-toolbar .w-e-droplist ul.w-e-block { + list-style: none; + text-align: left; + padding: 5px; +} +.w-e-toolbar .w-e-droplist ul.w-e-block li.w-e-item { + display: inline-block; + *display: inline; + *zoom: 1; + padding: 3px 5px; +} +.w-e-toolbar .w-e-droplist ul.w-e-block li.w-e-item:hover { + background-color: #f1f1f1; +} + +@font-face { + font-family: 'w-e-icon'; + src: url(data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAABhQAAsAAAAAGAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAABCAAAAGAAAABgDxIPBGNtYXAAAAFoAAABBAAAAQQrSf4BZ2FzcAAAAmwAAAAIAAAACAAAABBnbHlmAAACdAAAEvAAABLwfpUWUWhlYWQAABVkAAAANgAAADYQp00kaGhlYQAAFZwAAAAkAAAAJAfEA+FobXR4AAAVwAAAAIQAAACEeAcD7GxvY2EAABZEAAAARAAAAERBSEX+bWF4cAAAFogAAAAgAAAAIAAsALZuYW1lAAAWqAAAAYYAAAGGmUoJ+3Bvc3QAABgwAAAAIAAAACAAAwAAAAMD3gGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAA8fwDwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEAOgAAAA2ACAABAAWAAEAIOkG6Q3pEulH6Wbpd+m56bvpxunL6d/qDepc6l/qZepo6nHqefAN8BTxIPHc8fz//f//AAAAAAAg6QbpDekS6UfpZel36bnpu+nG6cvp3+oN6lzqX+pi6mjqcep38A3wFPEg8dzx/P/9//8AAf/jFv4W+Bb0FsAWoxaTFlIWURZHFkMWMBYDFbUVsxWxFa8VpxWiEA8QCQ7+DkMOJAADAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAB//8ADwABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAACAAD/wAQAA8AABAATAAABNwEnAQMuAScTNwEjAQMlATUBBwGAgAHAQP5Anxc7MmOAAYDA/oDAAoABgP6ATgFAQAHAQP5A/p0yOxcBEU4BgP6A/YDAAYDA/oCAAAQAAAAABAADgAAQACEALQA0AAABOAExETgBMSE4ATEROAExITUhIgYVERQWMyEyNjURNCYjBxQGIyImNTQ2MzIWEyE1EwEzNwPA/IADgPyAGiYmGgOAGiYmGoA4KCg4OCgoOED9AOABAEDgA0D9AAMAQCYa/QAaJiYaAwAaJuAoODgoKDg4/biAAYD+wMAAAAIAAABABAADQAA4ADwAAAEmJy4BJyYjIgcOAQcGBwYHDgEHBhUUFx4BFxYXFhceARcWMzI3PgE3Njc2Nz4BNzY1NCcuAScmJwERDQED1TY4OXY8PT8/PTx2OTg2CwcICwMDAwMLCAcLNjg5djw9Pz89PHY5ODYLBwgLAwMDAwsIBwv9qwFA/sADIAgGBggCAgICCAYGCCkqKlktLi8vLi1ZKiopCAYGCAICAgIIBgYIKSoqWS0uLy8uLVkqKin94AGAwMAAAAAAAgDA/8ADQAPAABsAJwAAASIHDgEHBhUUFx4BFxYxMDc+ATc2NTQnLgEnJgMiJjU0NjMyFhUUBgIAQjs6VxkZMjJ4MjIyMngyMhkZVzo7QlBwcFBQcHADwBkZVzo7Qnh9fcxBQUFBzH19eEI7OlcZGf4AcFBQcHBQUHAAAAEAAAAABAADgAArAAABIgcOAQcGBycRISc+ATMyFx4BFxYVFAcOAQcGBxc2Nz4BNzY1NCcuAScmIwIANTIyXCkpI5YBgJA1i1BQRUZpHh4JCSIYGB5VKCAgLQwMKCiLXl1qA4AKCycbHCOW/oCQNDweHmlGRVArKClJICEaYCMrK2I2NjlqXV6LKCgAAQAAAAAEAAOAACoAABMUFx4BFxYXNyYnLgEnJjU0Nz4BNzYzMhYXByERByYnLgEnJiMiBw4BBwYADAwtICAoVR4YGCIJCR4eaUZFUFCLNZABgJYjKSlcMjI1al1eiygoAYA5NjZiKysjYBohIEkpKCtQRUZpHh48NJABgJYjHBsnCwooKIteXQAAAAACAAAAQAQBAwAAJgBNAAATMhceARcWFRQHDgEHBiMiJy4BJyY1JzQ3PgE3NjMVIgYHDgEHPgEhMhceARcWFRQHDgEHBiMiJy4BJyY1JzQ3PgE3NjMVIgYHDgEHPgHhLikpPRESEhE9KSkuLikpPRESASMjelJRXUB1LQkQBwgSAkkuKSk9ERISET0pKS4uKSk9ERIBIyN6UlFdQHUtCRAHCBICABIRPSkpLi4pKT0REhIRPSkpLiBdUVJ6IyOAMC4IEwoCARIRPSkpLi4pKT0REhIRPSkpLiBdUVJ6IyOAMC4IEwoCAQAABgBA/8AEAAPAAAMABwALABEAHQApAAAlIRUhESEVIREhFSEnESM1IzUTFTMVIzU3NSM1MxUVESM1MzUjNTM1IzUBgAKA/YACgP2AAoD9gMBAQECAwICAwMCAgICAgIACAIACAIDA/wDAQP3yMkCSPDJAku7+wEBAQEBAAAYAAP/ABAADwAADAAcACwAXACMALwAAASEVIREhFSERIRUhATQ2MzIWFRQGIyImETQ2MzIWFRQGIyImETQ2MzIWFRQGIyImAYACgP2AAoD9gAKA/YD+gEs1NUtLNTVLSzU1S0s1NUtLNTVLSzU1SwOAgP8AgP8AgANANUtLNTVLS/61NUtLNTVLS/61NUtLNTVLSwADAAAAAAQAA6AAAwANABQAADchFSElFSE1EyEVITUhJQkBIxEjEQAEAPwABAD8AIABAAEAAQD9YAEgASDggEBAwEBAAQCAgMABIP7g/wABAAAAAAACAB7/zAPiA7QAMwBkAAABIiYnJicmNDc2PwE+ATMyFhcWFxYUBwYPAQYiJyY0PwE2NCcuASMiBg8BBhQXFhQHDgEjAyImJyYnJjQ3Nj8BNjIXFhQPAQYUFx4BMzI2PwE2NCcmNDc2MhcWFxYUBwYPAQ4BIwG4ChMIIxISEhIjwCNZMTFZIyMSEhISI1gPLA8PD1gpKRQzHBwzFMApKQ8PCBMKuDFZIyMSEhISI1gPLA8PD1gpKRQzHBwzFMApKQ8PDysQIxISEhIjwCNZMQFECAckLS1eLS0kwCIlJSIkLS1eLS0kVxAQDysPWCl0KRQVFRTAKXQpDysQBwj+iCUiJC0tXi0tJFcQEA8rD1gpdCkUFRUUwCl0KQ8rEA8PJC0tXi0tJMAiJQAAAAAFAAD/wAQAA8AAGwA3AFMAXwBrAAAFMjc+ATc2NTQnLgEnJiMiBw4BBwYVFBceARcWEzIXHgEXFhUUBw4BBwYjIicuAScmNTQ3PgE3NhMyNz4BNzY3BgcOAQcGIyInLgEnJicWFx4BFxYnNDYzMhYVFAYjIiYlNDYzMhYVFAYjIiYCAGpdXosoKCgoi15dampdXosoKCgoi15dalZMTHEgISEgcUxMVlZMTHEgISEgcUxMVisrKlEmJiMFHBtWODc/Pzc4VhscBSMmJlEqK9UlGxslJRsbJQGAJRsbJSUbGyVAKCiLXl1qal1eiygoKCiLXl1qal1eiygoA6AhIHFMTFZWTExxICEhIHFMTFZWTExxICH+CQYGFRAQFEM6OlYYGRkYVjo6QxQQEBUGBvcoODgoKDg4KCg4OCgoODgAAAMAAP/ABAADwAAbADcAQwAAASIHDgEHBhUUFx4BFxYzMjc+ATc2NTQnLgEnJgMiJy4BJyY1NDc+ATc2MzIXHgEXFhUUBw4BBwYTBycHFwcXNxc3JzcCAGpdXosoKCgoi15dampdXosoKCgoi15dalZMTHEgISEgcUxMVlZMTHEgISEgcUxMSqCgYKCgYKCgYKCgA8AoKIteXWpqXV6LKCgoKIteXWpqXV6LKCj8YCEgcUxMVlZMTHEgISEgcUxMVlZMTHEgIQKgoKBgoKBgoKBgoKAAAQBl/8ADmwPAACkAAAEiJiMiBw4BBwYVFBYzLgE1NDY3MAcGAgcGBxUhEzM3IzceATMyNjcOAQMgRGhGcVNUbRobSUgGDWVKEBBLPDxZAT1sxizXNC1VJi5QGB09A7AQHh1hPj9BTTsLJjeZbwN9fv7Fj5AjGQIAgPYJDzdrCQcAAAAAAgAAAAAEAAOAAAkAFwAAJTMHJzMRIzcXIyURJyMRMxUhNTMRIwcRA4CAoKCAgKCggP8AQMCA/oCAwEDAwMACAMDAwP8AgP1AQEACwIABAAADAMAAAANAA4AAFgAfACgAAAE+ATU0Jy4BJyYjIREhMjc+ATc2NTQmATMyFhUUBisBEyMRMzIWFRQGAsQcIBQURi4vNf7AAYA1Ly5GFBRE/oRlKjw8KWafn58sPj4B2yJULzUvLkYUFPyAFBRGLi81RnQBRks1NUv+gAEASzU1SwAAAAACAMAAAANAA4AAHwAjAAABMxEUBw4BBwYjIicuAScmNREzERQWFx4BMzI2Nz4BNQEhFSECwIAZGVc6O0JCOzpXGRmAGxgcSSgoSRwYG/4AAoD9gAOA/mA8NDVOFhcXFk41NDwBoP5gHjgXGBsbGBc4Hv6ggAAAAAABAIAAAAOAA4AACwAAARUjATMVITUzASM1A4CA/sCA/kCAAUCAA4BA/QBAQAMAQAABAAAAAAQAA4AAPQAAARUjHgEVFAYHDgEjIiYnLgE1MxQWMzI2NTQmIyE1IS4BJy4BNTQ2Nz4BMzIWFx4BFSM0JiMiBhUUFjMyFhcEAOsVFjUwLHE+PnEsMDWAck5OcnJO/gABLAIEATA1NTAscT4+cSwwNYByTk5yck47bisBwEAdQSI1YiQhJCQhJGI1NExMNDRMQAEDASRiNTViJCEkJCEkYjU0TEw0NEwhHwAAAAcAAP/ABAADwAADAAcACwAPABMAGwAjAAATMxUjNzMVIyUzFSM3MxUjJTMVIwMTIRMzEyETAQMhAyMDIQMAgIDAwMABAICAwMDAAQCAgBAQ/QAQIBACgBD9QBADABAgEP2AEAHAQEBAQEBAQEBAAkD+QAHA/oABgPwAAYD+gAFA/sAAAAoAAAAABAADgAADAAcACwAPABMAFwAbAB8AIwAnAAATESERATUhFR0BITUBFSE1IxUhNREhFSElIRUhETUhFQEhFSEhNSEVAAQA/YABAP8AAQD/AED/AAEA/wACgAEA/wABAPyAAQD/AAKAAQADgPyAA4D9wMDAQMDAAgDAwMDA/wDAwMABAMDA/sDAwMAAAAUAAAAABAADgAADAAcACwAPABMAABMhFSEVIRUhESEVIREhFSERIRUhAAQA/AACgP2AAoD9gAQA/AAEAPwAA4CAQID/AIABQID/AIAAAAAABQAAAAAEAAOAAAMABwALAA8AEwAAEyEVIRchFSERIRUhAyEVIREhFSEABAD8AMACgP2AAoD9gMAEAPwABAD8AAOAgECA/wCAAUCA/wCAAAAFAAAAAAQAA4AAAwAHAAsADwATAAATIRUhBSEVIREhFSEBIRUhESEVIQAEAPwAAYACgP2AAoD9gP6ABAD8AAQA/AADgIBAgP8AgAFAgP8AgAAAAAABAD8APwLmAuYALAAAJRQPAQYjIi8BBwYjIi8BJjU0PwEnJjU0PwE2MzIfATc2MzIfARYVFA8BFxYVAuYQThAXFxCoqBAXFhBOEBCoqBAQThAWFxCoqBAXFxBOEBCoqBDDFhBOEBCoqBAQThAWFxCoqBAXFxBOEBCoqBAQThAXFxCoqBAXAAAABgAAAAADJQNuABQAKAA8AE0AVQCCAAABERQHBisBIicmNRE0NzY7ATIXFhUzERQHBisBIicmNRE0NzY7ATIXFhcRFAcGKwEiJyY1ETQ3NjsBMhcWExEhERQXFhcWMyEyNzY3NjUBIScmJyMGBwUVFAcGKwERFAcGIyEiJyY1ESMiJyY9ATQ3NjsBNzY3NjsBMhcWHwEzMhcWFQElBgUIJAgFBgYFCCQIBQaSBQUIJQgFBQUFCCUIBQWSBQUIJQgFBQUFCCUIBQVJ/gAEBAUEAgHbAgQEBAT+gAEAGwQGtQYEAfcGBQg3Ghsm/iUmGxs3CAUFBQUIsSgIFxYXtxcWFgkosAgFBgIS/rcIBQUFBQgBSQgFBgYFCP63CAUFBQUIAUkIBQYGBQj+twgFBQUFCAFJCAUGBgX+WwId/eMNCwoFBQUFCgsNAmZDBQICBVUkCAYF/eMwIiMhIi8CIAUGCCQIBQVgFQ8PDw8VYAUFCAACAAcASQO3Aq8AGgAuAAAJAQYjIi8BJjU0PwEnJjU0PwE2MzIXARYVFAcBFRQHBiMhIicmPQE0NzYzITIXFgFO/vYGBwgFHQYG4eEGBh0FCAcGAQoGBgJpBQUI/dsIBQUFBQgCJQgFBQGF/vYGBhwGCAcG4OEGBwcGHQUF/vUFCAcG/vslCAUFBQUIJQgFBQUFAAAAAQAjAAAD3QNuALMAACUiJyYjIgcGIyInJjU0NzY3Njc2NzY9ATQnJiMhIgcGHQEUFxYXFjMWFxYVFAcGIyInJiMiBwYjIicmNTQ3Njc2NzY3Nj0BETQ1NDU0JzQnJicmJyYnJicmIyInJjU0NzYzMhcWMzI3NjMyFxYVFAcGIwYHBgcGHQEUFxYzITI3Nj0BNCcmJyYnJjU0NzYzMhcWMzI3NjMyFxYVFAcGByIHBgcGFREUFxYXFhcyFxYVFAcGIwPBGTMyGhkyMxkNCAcJCg0MERAKEgEHFf5+FgcBFQkSEw4ODAsHBw4bNTUaGDExGA0HBwkJCwwQDwkSAQIBAgMEBAUIEhENDQoLBwcOGjU1GhgwMRgOBwcJCgwNEBAIFAEHDwGQDgcBFAoXFw8OBwcOGTMyGRkxMRkOBwcKCg0NEBEIFBQJEREODQoLBwcOAAICAgIMCw8RCQkBAQMDBQxE4AwFAwMFDNRRDQYBAgEICBIPDA0CAgICDAwOEQgJAQIDAwUNRSEB0AINDQgIDg4KCgsLBwcDBgEBCAgSDwwNAgICAg0MDxEICAECAQYMULYMBwEBBwy2UAwGAQEGBxYPDA0CAgICDQwPEQgIAQECBg1P/eZEDAYCAgEJCBEPDA0AAAIAAP+3A/8DtwATADkAAAEyFxYVFAcCBwYjIicmNTQ3ATYzARYXFh8BFgcGIyInJicmJyY1FhcWFxYXFjMyNzY3Njc2NzY3NjcDmygeHhq+TDdFSDQ0NQFtISn9+BcmJy8BAkxMe0c2NiEhEBEEExQQEBIRCRcIDxITFRUdHR4eKQO3GxooJDP+mUY0NTRJSTABSx/9sSsfHw0oek1MGhsuLzo6RAMPDgsLCgoWJRsaEREKCwQEAgABAAAAAAAA9evv618PPPUACwQAAAAAANbEBFgAAAAA1sQEWAAA/7cEAQPAAAAACAACAAAAAAAAAAEAAAPA/8AAAAQAAAD//wQBAAEAAAAAAAAAAAAAAAAAAAAhBAAAAAAAAAAAAAAAAgAAAAQAAAAEAAAABAAAAAQAAMAEAAAABAAAAAQAAAAEAABABAAAAAQAAAAEAAAeBAAAAAQAAAAEAABlBAAAAAQAAMAEAADABAAAgAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAMlAD8DJQAAA74ABwQAACMD/wAAAAAAAAAKABQAHgBMAJQA+AE2AXwBwgI2AnQCvgLoA34EHgSIBMoE8gU0BXAFiAXgBiIGagaSBroG5AcoB+AIKgkcCXgAAQAAACEAtAAKAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAA4ArgABAAAAAAABAAcAAAABAAAAAAACAAcAYAABAAAAAAADAAcANgABAAAAAAAEAAcAdQABAAAAAAAFAAsAFQABAAAAAAAGAAcASwABAAAAAAAKABoAigADAAEECQABAA4ABwADAAEECQACAA4AZwADAAEECQADAA4APQADAAEECQAEAA4AfAADAAEECQAFABYAIAADAAEECQAGAA4AUgADAAEECQAKADQApGljb21vb24AaQBjAG8AbQBvAG8AblZlcnNpb24gMS4wAFYAZQByAHMAaQBvAG4AIAAxAC4AMGljb21vb24AaQBjAG8AbQBvAG8Abmljb21vb24AaQBjAG8AbQBvAG8AblJlZ3VsYXIAUgBlAGcAdQBsAGEAcmljb21vb24AaQBjAG8AbQBvAG8AbkZvbnQgZ2VuZXJhdGVkIGJ5IEljb01vb24uAEYAbwBuAHQAIABnAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAEkAYwBvAE0AbwBvAG4ALgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=) format('truetype'); + font-weight: normal; + font-style: normal; +} +[class^="w-e-icon-"], +[class*=" w-e-icon-"] { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: 'w-e-icon' !important; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.w-e-icon-close:before { + content: "\f00d"; +} +.w-e-icon-upload2:before { + content: "\e9c6"; +} +.w-e-icon-trash-o:before { + content: "\f014"; +} +.w-e-icon-header:before { + content: "\f1dc"; +} +.w-e-icon-pencil2:before { + content: "\e906"; +} +.w-e-icon-paint-brush:before { + content: "\f1fc"; +} +.w-e-icon-image:before { + content: "\e90d"; +} +.w-e-icon-play:before { + content: "\e912"; +} +.w-e-icon-location:before { + content: "\e947"; +} +.w-e-icon-undo:before { + content: "\e965"; +} +.w-e-icon-redo:before { + content: "\e966"; +} +.w-e-icon-quotes-left:before { + content: "\e977"; +} +.w-e-icon-list-numbered:before { + content: "\e9b9"; +} +.w-e-icon-list2:before { + content: "\e9bb"; +} +.w-e-icon-link:before { + content: "\e9cb"; +} +.w-e-icon-happy:before { + content: "\e9df"; +} +.w-e-icon-bold:before { + content: "\ea62"; +} +.w-e-icon-underline:before { + content: "\ea63"; +} +.w-e-icon-italic:before { + content: "\ea64"; +} +.w-e-icon-strikethrough:before { + content: "\ea65"; +} +.w-e-icon-table2:before { + content: "\ea71"; +} +.w-e-icon-paragraph-left:before { + content: "\ea77"; +} +.w-e-icon-paragraph-center:before { + content: "\ea78"; +} +.w-e-icon-paragraph-right:before { + content: "\ea79"; +} +.w-e-icon-terminal:before { + content: "\f120"; +} +.w-e-icon-page-break:before { + content: "\ea68"; +} +.w-e-icon-cancel-circle:before { + content: "\ea0d"; +} +.w-e-icon-font:before { + content: "\ea5c"; +} +.w-e-icon-text-heigh:before { + content: "\ea5f"; +} + +.w-e-toolbar { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + padding: 0 5px; + /* flex-wrap: wrap; */ + /* 单个菜单 */ +} +.w-e-toolbar .w-e-menu { + position: relative; + text-align: center; + padding: 5px 10px; + cursor: pointer; +} +.w-e-toolbar .w-e-menu i { + color: #999; +} +.w-e-toolbar .w-e-menu:hover i { + color: #333; +} +.w-e-toolbar .w-e-active i { + color: #1e88e5; +} +.w-e-toolbar .w-e-active:hover i { + color: #1e88e5; +} + +.w-e-text-container .w-e-panel-container { + position: absolute; + top: 0; + left: 50%; + border: 1px solid #ccc; + border-top: 0; + box-shadow: 1px 1px 2px #ccc; + color: #333; + background-color: #fff; + /* 为 emotion panel 定制的样式 */ + /* 上传图片的 panel 定制样式 */ +} +.w-e-text-container .w-e-panel-container .w-e-panel-close { + position: absolute; + right: 0; + top: 0; + padding: 5px; + margin: 2px 5px 0 0; + cursor: pointer; + color: #999; +} +.w-e-text-container .w-e-panel-container .w-e-panel-close:hover { + color: #333; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-title { + list-style: none; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + font-size: 14px; + margin: 2px 10px 0 10px; + border-bottom: 1px solid #f1f1f1; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-title .w-e-item { + padding: 3px 5px; + color: #999; + cursor: pointer; + margin: 0 3px; + position: relative; + top: 1px; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-title .w-e-active { + color: #333; + border-bottom: 1px solid #333; + cursor: default; + font-weight: 700; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content { + padding: 10px 15px 10px 15px; + font-size: 16px; + /* 输入框的样式 */ + /* 按钮的样式 */ +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input:focus, +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content textarea:focus, +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content button:focus { + outline: none; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content textarea { + width: 100%; + border: 1px solid #ccc; + padding: 5px; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content textarea:focus { + border-color: #1e88e5; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input[type=text] { + border: none; + border-bottom: 1px solid #ccc; + font-size: 14px; + height: 20px; + color: #333; + text-align: left; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input[type=text].small { + width: 30px; + text-align: center; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input[type=text].block { + display: block; + width: 100%; + margin: 10px 0; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input[type=text]:focus { + border-bottom: 2px solid #1e88e5; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button { + font-size: 14px; + color: #1e88e5; + border: none; + padding: 5px 10px; + background-color: #fff; + cursor: pointer; + border-radius: 3px; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button.left { + float: left; + margin-right: 10px; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button.right { + float: right; + margin-left: 10px; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button.gray { + color: #999; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button.red { + color: #c24f4a; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button:hover { + background-color: #f1f1f1; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container:after { + content: ""; + display: table; + clear: both; +} +.w-e-text-container .w-e-panel-container .w-e-emoticon-container .w-e-item { + cursor: pointer; + font-size: 18px; + padding: 0 3px; + display: inline-block; + *display: inline; + *zoom: 1; +} +.w-e-text-container .w-e-panel-container .w-e-up-img-container { + text-align: center; +} +.w-e-text-container .w-e-panel-container .w-e-up-img-container .w-e-up-btn { + display: inline-block; + *display: inline; + *zoom: 1; + color: #999; + cursor: pointer; + font-size: 60px; + line-height: 1; +} +.w-e-text-container .w-e-panel-container .w-e-up-img-container .w-e-up-btn:hover { + color: #333; +} + +.w-e-text-container { + position: relative; +} +.w-e-text-container .w-e-progress { + position: absolute; + background-color: #1e88e5; + bottom: 0; + left: 0; + height: 1px; +} +.w-e-text { + padding: 0 10px; + overflow-y: scroll; +} +.w-e-text p, +.w-e-text h1, +.w-e-text h2, +.w-e-text h3, +.w-e-text h4, +.w-e-text h5, +.w-e-text table, +.w-e-text pre { + margin: 10px 0; + line-height: 1.5; +} +.w-e-text ul, +.w-e-text ol { + margin: 10px 0 10px 20px; +} +.w-e-text blockquote { + display: block; + border-left: 8px solid #d0e5f2; + padding: 5px 10px; + margin: 10px 0; + line-height: 1.4; + font-size: 100%; + background-color: #f1f1f1; +} +.w-e-text code { + display: inline-block; + *display: inline; + *zoom: 1; + background-color: #f1f1f1; + border-radius: 3px; + padding: 3px 5px; + margin: 0 3px; +} +.w-e-text pre code { + display: block; +} +.w-e-text table { + border-top: 1px solid #ccc; + border-left: 1px solid #ccc; +} +.w-e-text table td, +.w-e-text table th { + border-bottom: 1px solid #ccc; + border-right: 1px solid #ccc; + padding: 3px 5px; +} +.w-e-text table th { + border-bottom: 2px solid #ccc; + text-align: center; +} +.w-e-text:focus { + outline: none; +} +.w-e-text img { + cursor: pointer; +} +.w-e-text img:hover { + box-shadow: 0 0 5px #333; +} diff --git a/admin-core/src/main/resources/static/plugins/wangEditor3/wangEditor.js b/admin-core/src/main/resources/static/plugins/wangEditor3/wangEditor.js new file mode 100644 index 0000000000000000000000000000000000000000..36bcf815749541445ee5bea7ef56a2a59ef3fe4e --- /dev/null +++ b/admin-core/src/main/resources/static/plugins/wangEditor3/wangEditor.js @@ -0,0 +1,4674 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.wangEditor = factory()); +}(this, (function () { 'use strict'; + +/* + poly-fill +*/ + +var polyfill = function () { + + // Object.assign + if (typeof Object.assign != 'function') { + Object.assign = function (target, varArgs) { + // .length of function is 2 + if (target == null) { + // TypeError if undefined or null + throw new TypeError('Cannot convert undefined or null to object'); + } + + var to = Object(target); + + for (var index = 1; index < arguments.length; index++) { + var nextSource = arguments[index]; + + if (nextSource != null) { + // Skip over if undefined or null + for (var nextKey in nextSource) { + // Avoid bugs when hasOwnProperty is shadowed + if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { + to[nextKey] = nextSource[nextKey]; + } + } + } + } + return to; + }; + } + + // IE 中兼容 Element.prototype.matches + if (!Element.prototype.matches) { + Element.prototype.matches = Element.prototype.matchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector || Element.prototype.webkitMatchesSelector || function (s) { + var matches = (this.document || this.ownerDocument).querySelectorAll(s), + i = matches.length; + while (--i >= 0 && matches.item(i) !== this) {} + return i > -1; + }; + } +}; + +/* + DOM 操作 API +*/ + +// 根据 html 代码片段创建 dom 对象 +function createElemByHTML(html) { + var div = void 0; + div = document.createElement('div'); + div.innerHTML = html; + return div.children; +} + +// 是否是 DOM List +function isDOMList(selector) { + if (!selector) { + return false; + } + if (selector instanceof HTMLCollection || selector instanceof NodeList) { + return true; + } + return false; +} + +// 封装 document.querySelectorAll +function querySelectorAll(selector) { + var result = document.querySelectorAll(selector); + if (isDOMList(result)) { + return result; + } else { + return [result]; + } +} + +// 记录所有的事件绑定 +var eventList = []; + +// 创建构造函数 +function DomElement(selector) { + if (!selector) { + return; + } + + // selector 本来就是 DomElement 对象,直接返回 + if (selector instanceof DomElement) { + return selector; + } + + this.selector = selector; + var nodeType = selector.nodeType; + + // 根据 selector 得出的结果(如 DOM,DOM List) + var selectorResult = []; + if (nodeType === 9) { + // document 节点 + selectorResult = [selector]; + } else if (nodeType === 1) { + // 单个 DOM 节点 + selectorResult = [selector]; + } else if (isDOMList(selector) || selector instanceof Array) { + // DOM List 或者数组 + selectorResult = selector; + } else if (typeof selector === 'string') { + // 字符串 + selector = selector.replace('/\n/mg', '').trim(); + if (selector.indexOf('<') === 0) { + // 如
+ selectorResult = createElemByHTML(selector); + } else { + // 如 #id .class + selectorResult = querySelectorAll(selector); + } + } + + var length = selectorResult.length; + if (!length) { + // 空数组 + return this; + } + + // 加入 DOM 节点 + var i = void 0; + for (i = 0; i < length; i++) { + this[i] = selectorResult[i]; + } + this.length = length; +} + +// 修改原型 +DomElement.prototype = { + constructor: DomElement, + + // 类数组,forEach + forEach: function forEach(fn) { + var i = void 0; + for (i = 0; i < this.length; i++) { + var elem = this[i]; + var result = fn.call(elem, elem, i); + if (result === false) { + break; + } + } + return this; + }, + + // clone + clone: function clone(deep) { + var cloneList = []; + this.forEach(function (elem) { + cloneList.push(elem.cloneNode(!!deep)); + }); + return $(cloneList); + }, + + // 获取第几个元素 + get: function get(index) { + var length = this.length; + if (index >= length) { + index = index % length; + } + return $(this[index]); + }, + + // 第一个 + first: function first() { + return this.get(0); + }, + + // 最后一个 + last: function last() { + var length = this.length; + return this.get(length - 1); + }, + + // 绑定事件 + on: function on(type, selector, fn) { + // selector 不为空,证明绑定事件要加代理 + if (!fn) { + fn = selector; + selector = null; + } + + // type 是否有多个 + var types = []; + types = type.split(/\s+/); + + return this.forEach(function (elem) { + types.forEach(function (type) { + if (!type) { + return; + } + + // 记录下,方便后面解绑 + eventList.push({ + elem: elem, + type: type, + fn: fn + }); + + if (!selector) { + // 无代理 + elem.addEventListener(type, fn); + return; + } + + // 有代理 + elem.addEventListener(type, function (e) { + var target = e.target; + if (target.matches(selector)) { + fn.call(target, e); + } + }); + }); + }); + }, + + // 取消事件绑定 + off: function off(type, fn) { + return this.forEach(function (elem) { + elem.removeEventListener(type, fn); + }); + }, + + // 获取/设置 属性 + attr: function attr(key, val) { + if (val == null) { + // 获取值 + return this[0].getAttribute(key); + } else { + // 设置值 + return this.forEach(function (elem) { + elem.setAttribute(key, val); + }); + } + }, + + // 添加 class + addClass: function addClass(className) { + if (!className) { + return this; + } + return this.forEach(function (elem) { + var arr = void 0; + if (elem.className) { + // 解析当前 className 转换为数组 + arr = elem.className.split(/\s/); + arr = arr.filter(function (item) { + return !!item.trim(); + }); + // 添加 class + if (arr.indexOf(className) < 0) { + arr.push(className); + } + // 修改 elem.class + elem.className = arr.join(' '); + } else { + elem.className = className; + } + }); + }, + + // 删除 class + removeClass: function removeClass(className) { + if (!className) { + return this; + } + return this.forEach(function (elem) { + var arr = void 0; + if (elem.className) { + // 解析当前 className 转换为数组 + arr = elem.className.split(/\s/); + arr = arr.filter(function (item) { + item = item.trim(); + // 删除 class + if (!item || item === className) { + return false; + } + return true; + }); + // 修改 elem.class + elem.className = arr.join(' '); + } + }); + }, + + // 修改 css + css: function css(key, val) { + var currentStyle = key + ':' + val + ';'; + return this.forEach(function (elem) { + var style = (elem.getAttribute('style') || '').trim(); + var styleArr = void 0, + resultArr = []; + if (style) { + // 将 style 按照 ; 拆分为数组 + styleArr = style.split(';'); + styleArr.forEach(function (item) { + // 对每项样式,按照 : 拆分为 key 和 value + var arr = item.split(':').map(function (i) { + return i.trim(); + }); + if (arr.length === 2) { + resultArr.push(arr[0] + ':' + arr[1]); + } + }); + // 替换或者新增 + resultArr = resultArr.map(function (item) { + if (item.indexOf(key) === 0) { + return currentStyle; + } else { + return item; + } + }); + if (resultArr.indexOf(currentStyle) < 0) { + resultArr.push(currentStyle); + } + // 结果 + elem.setAttribute('style', resultArr.join('; ')); + } else { + // style 无值 + elem.setAttribute('style', currentStyle); + } + }); + }, + + // 显示 + show: function show() { + return this.css('display', 'block'); + }, + + // 隐藏 + hide: function hide() { + return this.css('display', 'none'); + }, + + // 获取子节点 + children: function children() { + var elem = this[0]; + if (!elem) { + return null; + } + + return $(elem.children); + }, + + // 获取子节点(包括文本节点) + childNodes: function childNodes() { + var elem = this[0]; + if (!elem) { + return null; + } + + return $(elem.childNodes); + }, + + // 增加子节点 + append: function append($children) { + return this.forEach(function (elem) { + $children.forEach(function (child) { + elem.appendChild(child); + }); + }); + }, + + // 移除当前节点 + remove: function remove() { + return this.forEach(function (elem) { + if (elem.remove) { + elem.remove(); + } else { + var parent = elem.parentElement; + parent && parent.removeChild(elem); + } + }); + }, + + // 是否包含某个子节点 + isContain: function isContain($child) { + var elem = this[0]; + var child = $child[0]; + return elem.contains(child); + }, + + // 尺寸数据 + getSizeData: function getSizeData() { + var elem = this[0]; + return elem.getBoundingClientRect(); // 可得到 bottom height left right top width 的数据 + }, + + // 封装 nodeName + getNodeName: function getNodeName() { + var elem = this[0]; + return elem.nodeName; + }, + + // 从当前元素查找 + find: function find(selector) { + var elem = this[0]; + return $(elem.querySelectorAll(selector)); + }, + + // 获取当前元素的 text + text: function text(val) { + if (!val) { + // 获取 text + var elem = this[0]; + return elem.innerHTML.replace(/<.*?>/g, function () { + return ''; + }); + } else { + // 设置 text + return this.forEach(function (elem) { + elem.innerHTML = val; + }); + } + }, + + // 获取 html + html: function html(value) { + var elem = this[0]; + if (value == null) { + return elem.innerHTML; + } else { + elem.innerHTML = value; + return this; + } + }, + + // 获取 value + val: function val() { + var elem = this[0]; + return elem.value.trim(); + }, + + // focus + focus: function focus() { + return this.forEach(function (elem) { + elem.focus(); + }); + }, + + // parent + parent: function parent() { + var elem = this[0]; + return $(elem.parentElement); + }, + + // parentUntil 找到符合 selector 的父节点 + parentUntil: function parentUntil(selector, _currentElem) { + var results = document.querySelectorAll(selector); + var length = results.length; + if (!length) { + // 传入的 selector 无效 + return null; + } + + var elem = _currentElem || this[0]; + if (elem.nodeName === 'BODY') { + return null; + } + + var parent = elem.parentElement; + var i = void 0; + for (i = 0; i < length; i++) { + if (parent === results[i]) { + // 找到,并返回 + return $(parent); + } + } + + // 继续查找 + return this.parentUntil(selector, parent); + }, + + // 判断两个 elem 是否相等 + equal: function equal($elem) { + if ($elem.nodeType === 1) { + return this[0] === $elem; + } else { + return this[0] === $elem[0]; + } + }, + + // 将该元素插入到某个元素前面 + insertBefore: function insertBefore(selector) { + var $referenceNode = $(selector); + var referenceNode = $referenceNode[0]; + if (!referenceNode) { + return this; + } + return this.forEach(function (elem) { + var parent = referenceNode.parentNode; + parent.insertBefore(elem, referenceNode); + }); + }, + + // 将该元素插入到某个元素后面 + insertAfter: function insertAfter(selector) { + var $referenceNode = $(selector); + var referenceNode = $referenceNode[0]; + if (!referenceNode) { + return this; + } + return this.forEach(function (elem) { + var parent = referenceNode.parentNode; + if (parent.lastChild === referenceNode) { + // 最后一个元素 + parent.appendChild(elem); + } else { + // 不是最后一个元素 + parent.insertBefore(elem, referenceNode.nextSibling); + } + }); + } +}; + +// new 一个对象 +function $(selector) { + return new DomElement(selector); +} + +// 解绑所有事件,用于销毁编辑器 +$.offAll = function () { + eventList.forEach(function (item) { + var elem = item.elem; + var type = item.type; + var fn = item.fn; + // 解绑 + elem.removeEventListener(type, fn); + }); +}; + +/* + 配置信息 +*/ + +var config = { + + // 默认菜单配置 + menus: ['head', 'bold', 'fontSize', 'fontName', 'italic', 'underline', 'strikeThrough', 'foreColor', 'backColor', 'link', 'list', 'justify', 'quote', 'emoticon', 'image', 'table', 'video', 'code', 'undo', 'redo'], + + fontNames: ['宋体', '微软雅黑', 'Arial', 'Tahoma', 'Verdana'], + + colors: ['#000000', '#eeece0', '#1c487f', '#4d80bf', '#c24f4a', '#8baa4a', '#7b5ba1', '#46acc8', '#f9963b', '#ffffff'], + + // // 语言配置 + // lang: { + // '设置标题': 'title', + // '正文': 'p', + // '链接文字': 'link text', + // '链接': 'link', + // '插入': 'insert', + // '创建': 'init' + // }, + + // 表情 + emotions: [{ + // tab 的标题 + title: '默认', + // type -> 'emoji' / 'image' + type: 'image', + // content -> 数组 + content: [{ + alt: '[坏笑]', + src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/50/pcmoren_huaixiao_org.png' + }, { + alt: '[舔屏]', + src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/40/pcmoren_tian_org.png' + }, { + alt: '[污]', + src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/3c/pcmoren_wu_org.png' + }] + }, { + // tab 的标题 + title: '新浪', + // type -> 'emoji' / 'image' + type: 'image', + // content -> 数组 + content: [{ + src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/7a/shenshou_thumb.gif', + alt: '[草泥马]' + }, { + src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/60/horse2_thumb.gif', + alt: '[神马]' + }, { + src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/bc/fuyun_thumb.gif', + alt: '[浮云]' + }] + }, { + // tab 的标题 + title: 'emoji', + // type -> 'emoji' / 'image' + type: 'emoji', + // content -> 数组 + content: '😀 😃 😄 😁 😆 😅 😂 😊 😇 🙂 🙃 😉 😓 😪 😴 🙄 🤔 😬 🤐'.split(/\s/) + }], + + // 编辑区域的 z-index + zIndex: 10000, + + // 是否开启 debug 模式(debug 模式下错误会 throw error 形式抛出) + debug: false, + + // 插入链接时候的格式校验 + linkCheck: function linkCheck(text, link) { + // text 是插入的文字 + // link 是插入的链接 + return true; // 返回 true 即表示成功 + // return '校验失败' // 返回字符串即表示失败的提示信息 + }, + + // 插入网络图片的校验 + linkImgCheck: function linkImgCheck(src) { + // src 即图片的地址 + return true; // 返回 true 即表示成功 + // return '校验失败' // 返回字符串即表示失败的提示信息 + }, + + // 粘贴过滤样式,默认开启 + pasteFilterStyle: true, + + // 粘贴内容时,忽略图片。默认关闭 + pasteIgnoreImg: false, + + // 对粘贴的文字进行自定义处理,返回处理后的结果。编辑器会将处理后的结果粘贴到编辑区域中。 + // IE 暂时不支持 + pasteTextHandle: function pasteTextHandle(content) { + // content 即粘贴过来的内容(html 或 纯文本),可进行自定义处理然后返回 + return content; + }, + + // onchange 事件 + // onchange: function (html) { + // // html 即变化之后的内容 + // console.log(html) + // }, + + // 是否显示添加网络图片的 tab + showLinkImg: true, + + // 插入网络图片的回调 + linkImgCallback: function linkImgCallback(url) { + // console.log(url) // url 即插入图片的地址 + }, + + // 默认上传图片 max size: 5M + uploadImgMaxSize: 5 * 1024 * 1024, + + // 配置一次最多上传几个图片 + // uploadImgMaxLength: 5, + + // 上传图片,是否显示 base64 格式 + uploadImgShowBase64: false, + + // 上传图片,server 地址(如果有值,则 base64 格式的配置则失效) + // uploadImgServer: '/upload', + + // 自定义配置 filename + uploadFileName: '', + + // 上传图片的自定义参数 + uploadImgParams: { + // token: 'abcdef12345' + }, + + // 上传图片的自定义header + uploadImgHeaders: { + // 'Accept': 'text/x-json' + }, + + // 配置 XHR withCredentials + withCredentials: false, + + // 自定义上传图片超时时间 ms + uploadImgTimeout: 10000, + + // 上传图片 hook + uploadImgHooks: { + // customInsert: function (insertLinkImg, result, editor) { + // console.log('customInsert') + // // 图片上传并返回结果,自定义插入图片的事件,而不是编辑器自动插入图片 + // const data = result.data1 || [] + // data.forEach(link => { + // insertLinkImg(link) + // }) + // }, + before: function before(xhr, editor, files) { + // 图片上传之前触发 + + // 如果返回的结果是 {prevent: true, msg: 'xxxx'} 则表示用户放弃上传 + // return { + // prevent: true, + // msg: '放弃上传' + // } + }, + success: function success(xhr, editor, result) { + // 图片上传并返回结果,图片插入成功之后触发 + }, + fail: function fail(xhr, editor, result) { + // 图片上传并返回结果,但图片插入错误时触发 + }, + error: function error(xhr, editor) { + // 图片上传出错时触发 + }, + timeout: function timeout(xhr, editor) { + // 图片上传超时时触发 + } + }, + + // 是否上传七牛云,默认为 false + qiniu: false + +}; + +/* + 工具 +*/ + +// 和 UA 相关的属性 +var UA = { + _ua: navigator.userAgent, + + // 是否 webkit + isWebkit: function isWebkit() { + var reg = /webkit/i; + return reg.test(this._ua); + }, + + // 是否 IE + isIE: function isIE() { + return 'ActiveXObject' in window; + } +}; + +// 遍历对象 +function objForEach(obj, fn) { + var key = void 0, + result = void 0; + for (key in obj) { + if (obj.hasOwnProperty(key)) { + result = fn.call(obj, key, obj[key]); + if (result === false) { + break; + } + } + } +} + +// 遍历类数组 +function arrForEach(fakeArr, fn) { + var i = void 0, + item = void 0, + result = void 0; + var length = fakeArr.length || 0; + for (i = 0; i < length; i++) { + item = fakeArr[i]; + result = fn.call(fakeArr, item, i); + if (result === false) { + break; + } + } +} + +// 获取随机数 +function getRandom(prefix) { + return prefix + Math.random().toString().slice(2); +} + +// 替换 html 特殊字符 +function replaceHtmlSymbol(html) { + if (html == null) { + return ''; + } + return html.replace(//gm, '>').replace(/"/gm, '"').replace(/(\r\n|\r|\n)/g, '
'); +} + +// 返回百分比的格式 + + +// 判断是不是 function +function isFunction(fn) { + return typeof fn === 'function'; +} + +/* + bold-menu +*/ +// 构造函数 +function Bold(editor) { + this.editor = editor; + this.$elem = $('
\n \n
'); + this.type = 'click'; + + // 当前是否 active 状态 + this._active = false; +} + +// 原型 +Bold.prototype = { + constructor: Bold, + + // 点击事件 + onClick: function onClick(e) { + // 点击菜单将触发这里 + + var editor = this.editor; + var isSeleEmpty = editor.selection.isSelectionEmpty(); + + if (isSeleEmpty) { + // 选区是空的,插入并选中一个“空白” + editor.selection.createEmptyRange(); + } + + // 执行 bold 命令 + editor.cmd.do('bold'); + + if (isSeleEmpty) { + // 需要将选取折叠起来 + editor.selection.collapseRange(); + editor.selection.restoreSelection(); + } + }, + + // 试图改变 active 状态 + tryChangeActive: function tryChangeActive(e) { + var editor = this.editor; + var $elem = this.$elem; + if (editor.cmd.queryCommandState('bold')) { + this._active = true; + $elem.addClass('w-e-active'); + } else { + this._active = false; + $elem.removeClass('w-e-active'); + } + } +}; + +/* + 替换多语言 + */ + +var replaceLang = function (editor, str) { + var langArgs = editor.config.langArgs || []; + var result = str; + + langArgs.forEach(function (item) { + var reg = item.reg; + var val = item.val; + + if (reg.test(result)) { + result = result.replace(reg, function () { + return val; + }); + } + }); + + return result; +}; + +/* + droplist +*/ +var _emptyFn = function _emptyFn() {}; + +// 构造函数 +function DropList(menu, opt) { + var _this = this; + + // droplist 所依附的菜单 + var editor = menu.editor; + this.menu = menu; + this.opt = opt; + // 容器 + var $container = $('
'); + + // 标题 + var $title = opt.$title; + var titleHtml = void 0; + if ($title) { + // 替换多语言 + titleHtml = $title.html(); + titleHtml = replaceLang(editor, titleHtml); + $title.html(titleHtml); + + $title.addClass('w-e-dp-title'); + $container.append($title); + } + + var list = opt.list || []; + var type = opt.type || 'list'; // 'list' 列表形式(如“标题”菜单) / 'inline-block' 块状形式(如“颜色”菜单) + var onClick = opt.onClick || _emptyFn; + + // 加入 DOM 并绑定事件 + var $list = $('
    '); + $container.append($list); + list.forEach(function (item) { + var $elem = item.$elem; + + // 替换多语言 + var elemHtml = $elem.html(); + elemHtml = replaceLang(editor, elemHtml); + $elem.html(elemHtml); + + var value = item.value; + var $li = $('
  • '); + if ($elem) { + $li.append($elem); + $list.append($li); + $li.on('click', function (e) { + onClick(value); + + // 隐藏 + _this.hideTimeoutId = setTimeout(function () { + _this.hide(); + }, 0); + }); + } + }); + + // 绑定隐藏事件 + $container.on('mouseleave', function (e) { + _this.hideTimeoutId = setTimeout(function () { + _this.hide(); + }, 0); + }); + + // 记录属性 + this.$container = $container; + + // 基本属性 + this._rendered = false; + this._show = false; +} + +// 原型 +DropList.prototype = { + constructor: DropList, + + // 显示(插入DOM) + show: function show() { + if (this.hideTimeoutId) { + // 清除之前的定时隐藏 + clearTimeout(this.hideTimeoutId); + } + + var menu = this.menu; + var $menuELem = menu.$elem; + var $container = this.$container; + if (this._show) { + return; + } + if (this._rendered) { + // 显示 + $container.show(); + } else { + // 加入 DOM 之前先定位位置 + var menuHeight = $menuELem.getSizeData().height || 0; + var width = this.opt.width || 100; // 默认为 100 + $container.css('margin-top', menuHeight + 'px').css('width', width + 'px'); + + // 加入到 DOM + $menuELem.append($container); + this._rendered = true; + } + + // 修改属性 + this._show = true; + }, + + // 隐藏(移除DOM) + hide: function hide() { + if (this.showTimeoutId) { + // 清除之前的定时显示 + clearTimeout(this.showTimeoutId); + } + + var $container = this.$container; + if (!this._show) { + return; + } + // 隐藏并需改属性 + $container.hide(); + this._show = false; + } +}; + +/* + menu - header +*/ +// 构造函数 +function Head(editor) { + var _this = this; + + this.editor = editor; + this.$elem = $('
    '); + this.type = 'droplist'; + + // 当前是否 active 状态 + this._active = false; + + // 初始化 droplist + this.droplist = new DropList(this, { + width: 100, + $title: $('

    设置标题

    '), + type: 'list', // droplist 以列表形式展示 + list: [{ $elem: $('

    H1

    '), value: '

    ' }, { $elem: $('

    H2

    '), value: '

    ' }, { $elem: $('

    H3

    '), value: '

    ' }, { $elem: $('

    H4

    '), value: '

    ' }, { $elem: $('

    H5
    '), value: '
    ' }, { $elem: $('

    正文

    '), value: '

    ' }], + onClick: function onClick(value) { + // 注意 this 是指向当前的 Head 对象 + _this._command(value); + } + }); +} + +// 原型 +Head.prototype = { + constructor: Head, + + // 执行命令 + _command: function _command(value) { + var editor = this.editor; + + var $selectionElem = editor.selection.getSelectionContainerElem(); + if (editor.$textElem.equal($selectionElem)) { + // 不能选中多行来设置标题,否则会出现问题 + // 例如选中的是

    xxx

    yyy

    来设置标题,设置之后会成为

    xxx
    yyy

    不符合预期 + return; + } + + editor.cmd.do('formatBlock', value); + }, + + // 试图改变 active 状态 + tryChangeActive: function tryChangeActive(e) { + var editor = this.editor; + var $elem = this.$elem; + var reg = /^h/i; + var cmdValue = editor.cmd.queryCommandValue('formatBlock'); + if (reg.test(cmdValue)) { + this._active = true; + $elem.addClass('w-e-active'); + } else { + this._active = false; + $elem.removeClass('w-e-active'); + } + } +}; + +/* + menu - fontSize +*/ + +// 构造函数 +function FontSize(editor) { + var _this = this; + + this.editor = editor; + this.$elem = $('
    '); + this.type = 'droplist'; + + // 当前是否 active 状态 + this._active = false; + + // 初始化 droplist + this.droplist = new DropList(this, { + width: 160, + $title: $('

    字号

    '), + type: 'list', // droplist 以列表形式展示 + list: [{ $elem: $('x-small'), value: '1' }, { $elem: $('small'), value: '2' }, { $elem: $('normal'), value: '3' }, { $elem: $('large'), value: '4' }, { $elem: $('x-large'), value: '5' }, { $elem: $('xx-large'), value: '6' }], + onClick: function onClick(value) { + // 注意 this 是指向当前的 FontSize 对象 + _this._command(value); + } + }); +} + +// 原型 +FontSize.prototype = { + constructor: FontSize, + + // 执行命令 + _command: function _command(value) { + var editor = this.editor; + editor.cmd.do('fontSize', value); + } +}; + +/* + menu - fontName +*/ + +// 构造函数 +function FontName(editor) { + var _this = this; + + this.editor = editor; + this.$elem = $('
    '); + this.type = 'droplist'; + + // 当前是否 active 状态 + this._active = false; + + // 获取配置的字体 + var config = editor.config; + var fontNames = config.fontNames || []; + + // 初始化 droplist + this.droplist = new DropList(this, { + width: 100, + $title: $('

    字体

    '), + type: 'list', // droplist 以列表形式展示 + list: fontNames.map(function (fontName) { + return { $elem: $('' + fontName + ''), value: fontName }; + }), + onClick: function onClick(value) { + // 注意 this 是指向当前的 FontName 对象 + _this._command(value); + } + }); +} + +// 原型 +FontName.prototype = { + constructor: FontName, + + _command: function _command(value) { + var editor = this.editor; + editor.cmd.do('fontName', value); + } +}; + +/* + panel +*/ + +var emptyFn = function emptyFn() {}; + +// 记录已经显示 panel 的菜单 +var _isCreatedPanelMenus = []; + +// 构造函数 +function Panel(menu, opt) { + this.menu = menu; + this.opt = opt; +} + +// 原型 +Panel.prototype = { + constructor: Panel, + + // 显示(插入DOM) + show: function show() { + var _this = this; + + var menu = this.menu; + if (_isCreatedPanelMenus.indexOf(menu) >= 0) { + // 该菜单已经创建了 panel 不能再创建 + return; + } + + var editor = menu.editor; + var $body = $('body'); + var $textContainerElem = editor.$textContainerElem; + var opt = this.opt; + + // panel 的容器 + var $container = $('
    '); + var width = opt.width || 300; // 默认 300px + $container.css('width', width + 'px').css('margin-left', (0 - width) / 2 + 'px'); + + // 添加关闭按钮 + var $closeBtn = $(''); + $container.append($closeBtn); + $closeBtn.on('click', function () { + _this.hide(); + }); + + // 准备 tabs 容器 + var $tabTitleContainer = $('
      '); + var $tabContentContainer = $('
      '); + $container.append($tabTitleContainer).append($tabContentContainer); + + // 设置高度 + var height = opt.height; + if (height) { + $tabContentContainer.css('height', height + 'px').css('overflow-y', 'auto'); + } + + // tabs + var tabs = opt.tabs || []; + var tabTitleArr = []; + var tabContentArr = []; + tabs.forEach(function (tab, tabIndex) { + if (!tab) { + return; + } + var title = tab.title || ''; + var tpl = tab.tpl || ''; + + // 替换多语言 + title = replaceLang(editor, title); + tpl = replaceLang(editor, tpl); + + // 添加到 DOM + var $title = $('
    • ' + title + '
    • '); + $tabTitleContainer.append($title); + var $content = $(tpl); + $tabContentContainer.append($content); + + // 记录到内存 + $title._index = tabIndex; + tabTitleArr.push($title); + tabContentArr.push($content); + + // 设置 active 项 + if (tabIndex === 0) { + $title._active = true; + $title.addClass('w-e-active'); + } else { + $content.hide(); + } + + // 绑定 tab 的事件 + $title.on('click', function (e) { + if ($title._active) { + return; + } + // 隐藏所有的 tab + tabTitleArr.forEach(function ($title) { + $title._active = false; + $title.removeClass('w-e-active'); + }); + tabContentArr.forEach(function ($content) { + $content.hide(); + }); + + // 显示当前的 tab + $title._active = true; + $title.addClass('w-e-active'); + $content.show(); + }); + }); + + // 绑定关闭事件 + $container.on('click', function (e) { + // 点击时阻止冒泡 + e.stopPropagation(); + }); + $body.on('click', function (e) { + _this.hide(); + }); + + // 添加到 DOM + $textContainerElem.append($container); + + // 绑定 opt 的事件,只有添加到 DOM 之后才能绑定成功 + tabs.forEach(function (tab, index) { + if (!tab) { + return; + } + var events = tab.events || []; + events.forEach(function (event) { + var selector = event.selector; + var type = event.type; + var fn = event.fn || emptyFn; + var $content = tabContentArr[index]; + $content.find(selector).on(type, function (e) { + e.stopPropagation(); + var needToHide = fn(e); + // 执行完事件之后,是否要关闭 panel + if (needToHide) { + _this.hide(); + } + }); + }); + }); + + // focus 第一个 elem + var $inputs = $container.find('input[type=text],textarea'); + if ($inputs.length) { + $inputs.get(0).focus(); + } + + // 添加到属性 + this.$container = $container; + + // 隐藏其他 panel + this._hideOtherPanels(); + // 记录该 menu 已经创建了 panel + _isCreatedPanelMenus.push(menu); + }, + + // 隐藏(移除DOM) + hide: function hide() { + var menu = this.menu; + var $container = this.$container; + if ($container) { + $container.remove(); + } + + // 将该 menu 记录中移除 + _isCreatedPanelMenus = _isCreatedPanelMenus.filter(function (item) { + if (item === menu) { + return false; + } else { + return true; + } + }); + }, + + // 一个 panel 展示时,隐藏其他 panel + _hideOtherPanels: function _hideOtherPanels() { + if (!_isCreatedPanelMenus.length) { + return; + } + _isCreatedPanelMenus.forEach(function (menu) { + var panel = menu.panel || {}; + if (panel.hide) { + panel.hide(); + } + }); + } +}; + +/* + menu - link +*/ +// 构造函数 +function Link(editor) { + this.editor = editor; + this.$elem = $('
      '); + this.type = 'panel'; + + // 当前是否 active 状态 + this._active = false; +} + +// 原型 +Link.prototype = { + constructor: Link, + + // 点击事件 + onClick: function onClick(e) { + var editor = this.editor; + var $linkelem = void 0; + + if (this._active) { + // 当前选区在链接里面 + $linkelem = editor.selection.getSelectionContainerElem(); + if (!$linkelem) { + return; + } + // 将该元素都包含在选取之内,以便后面整体替换 + editor.selection.createRangeByElem($linkelem); + editor.selection.restoreSelection(); + // 显示 panel + this._createPanel($linkelem.text(), $linkelem.attr('href')); + } else { + // 当前选区不在链接里面 + if (editor.selection.isSelectionEmpty()) { + // 选区是空的,未选中内容 + this._createPanel('', ''); + } else { + // 选中内容了 + this._createPanel(editor.selection.getSelectionText(), ''); + } + } + }, + + // 创建 panel + _createPanel: function _createPanel(text, link) { + var _this = this; + + // panel 中需要用到的id + var inputLinkId = getRandom('input-link'); + var inputTextId = getRandom('input-text'); + var btnOkId = getRandom('btn-ok'); + var btnDelId = getRandom('btn-del'); + + // 是否显示“删除链接” + var delBtnDisplay = this._active ? 'inline-block' : 'none'; + + // 初始化并显示 panel + var panel = new Panel(this, { + width: 300, + // panel 中可包含多个 tab + tabs: [{ + // tab 的标题 + title: '链接', + // 模板 + tpl: '
      \n \n \n
      \n \n \n
      \n
      ', + // 事件绑定 + events: [ + // 插入链接 + { + selector: '#' + btnOkId, + type: 'click', + fn: function fn() { + // 执行插入链接 + var $link = $('#' + inputLinkId); + var $text = $('#' + inputTextId); + var link = $link.val(); + var text = $text.val(); + _this._insertLink(text, link); + + // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 + return true; + } + }, + // 删除链接 + { + selector: '#' + btnDelId, + type: 'click', + fn: function fn() { + // 执行删除链接 + _this._delLink(); + + // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 + return true; + } + }] + } // tab end + ] // tabs end + }); + + // 显示 panel + panel.show(); + + // 记录属性 + this.panel = panel; + }, + + // 删除当前链接 + _delLink: function _delLink() { + if (!this._active) { + return; + } + var editor = this.editor; + var $selectionELem = editor.selection.getSelectionContainerElem(); + if (!$selectionELem) { + return; + } + var selectionText = editor.selection.getSelectionText(); + editor.cmd.do('insertHTML', '' + selectionText + ''); + }, + + // 插入链接 + _insertLink: function _insertLink(text, link) { + var editor = this.editor; + var config = editor.config; + var linkCheck = config.linkCheck; + var checkResult = true; // 默认为 true + if (linkCheck && typeof linkCheck === 'function') { + checkResult = linkCheck(text, link); + } + if (checkResult === true) { + editor.cmd.do('insertHTML', '' + text + ''); + } else { + alert(checkResult); + } + }, + + // 试图改变 active 状态 + tryChangeActive: function tryChangeActive(e) { + var editor = this.editor; + var $elem = this.$elem; + var $selectionELem = editor.selection.getSelectionContainerElem(); + if (!$selectionELem) { + return; + } + if ($selectionELem.getNodeName() === 'A') { + this._active = true; + $elem.addClass('w-e-active'); + } else { + this._active = false; + $elem.removeClass('w-e-active'); + } + } +}; + +/* + italic-menu +*/ +// 构造函数 +function Italic(editor) { + this.editor = editor; + this.$elem = $('
      \n \n
      '); + this.type = 'click'; + + // 当前是否 active 状态 + this._active = false; +} + +// 原型 +Italic.prototype = { + constructor: Italic, + + // 点击事件 + onClick: function onClick(e) { + // 点击菜单将触发这里 + + var editor = this.editor; + var isSeleEmpty = editor.selection.isSelectionEmpty(); + + if (isSeleEmpty) { + // 选区是空的,插入并选中一个“空白” + editor.selection.createEmptyRange(); + } + + // 执行 italic 命令 + editor.cmd.do('italic'); + + if (isSeleEmpty) { + // 需要将选取折叠起来 + editor.selection.collapseRange(); + editor.selection.restoreSelection(); + } + }, + + // 试图改变 active 状态 + tryChangeActive: function tryChangeActive(e) { + var editor = this.editor; + var $elem = this.$elem; + if (editor.cmd.queryCommandState('italic')) { + this._active = true; + $elem.addClass('w-e-active'); + } else { + this._active = false; + $elem.removeClass('w-e-active'); + } + } +}; + +/* + redo-menu +*/ +// 构造函数 +function Redo(editor) { + this.editor = editor; + this.$elem = $('
      \n \n
      '); + this.type = 'click'; + + // 当前是否 active 状态 + this._active = false; +} + +// 原型 +Redo.prototype = { + constructor: Redo, + + // 点击事件 + onClick: function onClick(e) { + // 点击菜单将触发这里 + + var editor = this.editor; + + // 执行 redo 命令 + editor.cmd.do('redo'); + } +}; + +/* + strikeThrough-menu +*/ +// 构造函数 +function StrikeThrough(editor) { + this.editor = editor; + this.$elem = $('
      \n \n
      '); + this.type = 'click'; + + // 当前是否 active 状态 + this._active = false; +} + +// 原型 +StrikeThrough.prototype = { + constructor: StrikeThrough, + + // 点击事件 + onClick: function onClick(e) { + // 点击菜单将触发这里 + + var editor = this.editor; + var isSeleEmpty = editor.selection.isSelectionEmpty(); + + if (isSeleEmpty) { + // 选区是空的,插入并选中一个“空白” + editor.selection.createEmptyRange(); + } + + // 执行 strikeThrough 命令 + editor.cmd.do('strikeThrough'); + + if (isSeleEmpty) { + // 需要将选取折叠起来 + editor.selection.collapseRange(); + editor.selection.restoreSelection(); + } + }, + + // 试图改变 active 状态 + tryChangeActive: function tryChangeActive(e) { + var editor = this.editor; + var $elem = this.$elem; + if (editor.cmd.queryCommandState('strikeThrough')) { + this._active = true; + $elem.addClass('w-e-active'); + } else { + this._active = false; + $elem.removeClass('w-e-active'); + } + } +}; + +/* + underline-menu +*/ +// 构造函数 +function Underline(editor) { + this.editor = editor; + this.$elem = $('
      \n \n
      '); + this.type = 'click'; + + // 当前是否 active 状态 + this._active = false; +} + +// 原型 +Underline.prototype = { + constructor: Underline, + + // 点击事件 + onClick: function onClick(e) { + // 点击菜单将触发这里 + + var editor = this.editor; + var isSeleEmpty = editor.selection.isSelectionEmpty(); + + if (isSeleEmpty) { + // 选区是空的,插入并选中一个“空白” + editor.selection.createEmptyRange(); + } + + // 执行 underline 命令 + editor.cmd.do('underline'); + + if (isSeleEmpty) { + // 需要将选取折叠起来 + editor.selection.collapseRange(); + editor.selection.restoreSelection(); + } + }, + + // 试图改变 active 状态 + tryChangeActive: function tryChangeActive(e) { + var editor = this.editor; + var $elem = this.$elem; + if (editor.cmd.queryCommandState('underline')) { + this._active = true; + $elem.addClass('w-e-active'); + } else { + this._active = false; + $elem.removeClass('w-e-active'); + } + } +}; + +/* + undo-menu +*/ +// 构造函数 +function Undo(editor) { + this.editor = editor; + this.$elem = $('
      \n \n
      '); + this.type = 'click'; + + // 当前是否 active 状态 + this._active = false; +} + +// 原型 +Undo.prototype = { + constructor: Undo, + + // 点击事件 + onClick: function onClick(e) { + // 点击菜单将触发这里 + + var editor = this.editor; + + // 执行 undo 命令 + editor.cmd.do('undo'); + } +}; + +/* + menu - list +*/ +// 构造函数 +function List(editor) { + var _this = this; + + this.editor = editor; + this.$elem = $('
      '); + this.type = 'droplist'; + + // 当前是否 active 状态 + this._active = false; + + // 初始化 droplist + this.droplist = new DropList(this, { + width: 120, + $title: $('

      设置列表

      '), + type: 'list', // droplist 以列表形式展示 + list: [{ $elem: $(' 有序列表'), value: 'insertOrderedList' }, { $elem: $(' 无序列表'), value: 'insertUnorderedList' }], + onClick: function onClick(value) { + // 注意 this 是指向当前的 List 对象 + _this._command(value); + } + }); +} + +// 原型 +List.prototype = { + constructor: List, + + // 执行命令 + _command: function _command(value) { + var editor = this.editor; + var $textElem = editor.$textElem; + editor.selection.restoreSelection(); + if (editor.cmd.queryCommandState(value)) { + return; + } + editor.cmd.do(value); + + // 验证列表是否被包裹在

      之内 + var $selectionElem = editor.selection.getSelectionContainerElem(); + if ($selectionElem.getNodeName() === 'LI') { + $selectionElem = $selectionElem.parent(); + } + if (/^ol|ul$/i.test($selectionElem.getNodeName()) === false) { + return; + } + if ($selectionElem.equal($textElem)) { + // 证明是顶级标签,没有被

      包裹 + return; + } + var $parent = $selectionElem.parent(); + if ($parent.equal($textElem)) { + // $parent 是顶级标签,不能删除 + return; + } + + $selectionElem.insertAfter($parent); + $parent.remove(); + }, + + // 试图改变 active 状态 + tryChangeActive: function tryChangeActive(e) { + var editor = this.editor; + var $elem = this.$elem; + if (editor.cmd.queryCommandState('insertUnOrderedList') || editor.cmd.queryCommandState('insertOrderedList')) { + this._active = true; + $elem.addClass('w-e-active'); + } else { + this._active = false; + $elem.removeClass('w-e-active'); + } + } +}; + +/* + menu - justify +*/ +// 构造函数 +function Justify(editor) { + var _this = this; + + this.editor = editor; + this.$elem = $('

      '); + this.type = 'droplist'; + + // 当前是否 active 状态 + this._active = false; + + // 初始化 droplist + this.droplist = new DropList(this, { + width: 100, + $title: $('

      对齐方式

      '), + type: 'list', // droplist 以列表形式展示 + list: [{ $elem: $(' 靠左'), value: 'justifyLeft' }, { $elem: $(' 居中'), value: 'justifyCenter' }, { $elem: $(' 靠右'), value: 'justifyRight' }], + onClick: function onClick(value) { + // 注意 this 是指向当前的 List 对象 + _this._command(value); + } + }); +} + +// 原型 +Justify.prototype = { + constructor: Justify, + + // 执行命令 + _command: function _command(value) { + var editor = this.editor; + editor.cmd.do(value); + } +}; + +/* + menu - Forecolor +*/ +// 构造函数 +function ForeColor(editor) { + var _this = this; + + this.editor = editor; + this.$elem = $('
      '); + this.type = 'droplist'; + + // 获取配置的颜色 + var config = editor.config; + var colors = config.colors || []; + + // 当前是否 active 状态 + this._active = false; + + // 初始化 droplist + this.droplist = new DropList(this, { + width: 120, + $title: $('

      文字颜色

      '), + type: 'inline-block', // droplist 内容以 block 形式展示 + list: colors.map(function (color) { + return { $elem: $(''), value: color }; + }), + onClick: function onClick(value) { + // 注意 this 是指向当前的 ForeColor 对象 + _this._command(value); + } + }); +} + +// 原型 +ForeColor.prototype = { + constructor: ForeColor, + + // 执行命令 + _command: function _command(value) { + var editor = this.editor; + editor.cmd.do('foreColor', value); + } +}; + +/* + menu - BackColor +*/ +// 构造函数 +function BackColor(editor) { + var _this = this; + + this.editor = editor; + this.$elem = $('
      '); + this.type = 'droplist'; + + // 获取配置的颜色 + var config = editor.config; + var colors = config.colors || []; + + // 当前是否 active 状态 + this._active = false; + + // 初始化 droplist + this.droplist = new DropList(this, { + width: 120, + $title: $('

      背景色

      '), + type: 'inline-block', // droplist 内容以 block 形式展示 + list: colors.map(function (color) { + return { $elem: $(''), value: color }; + }), + onClick: function onClick(value) { + // 注意 this 是指向当前的 BackColor 对象 + _this._command(value); + } + }); +} + +// 原型 +BackColor.prototype = { + constructor: BackColor, + + // 执行命令 + _command: function _command(value) { + var editor = this.editor; + editor.cmd.do('backColor', value); + } +}; + +/* + menu - quote +*/ +// 构造函数 +function Quote(editor) { + this.editor = editor; + this.$elem = $('
      \n \n
      '); + this.type = 'click'; + + // 当前是否 active 状态 + this._active = false; +} + +// 原型 +Quote.prototype = { + constructor: Quote, + + onClick: function onClick(e) { + var editor = this.editor; + var $selectionElem = editor.selection.getSelectionContainerElem(); + var nodeName = $selectionElem.getNodeName(); + + if (!UA.isIE()) { + if (nodeName === 'BLOCKQUOTE') { + // 撤销 quote + editor.cmd.do('formatBlock', '

      '); + } else { + // 转换为 quote + editor.cmd.do('formatBlock', '

      '); + } + return; + } + + // IE 中不支持 formatBlock
      ,要用其他方式兼容 + var content = void 0, + $targetELem = void 0; + if (nodeName === 'P') { + // 将 P 转换为 quote + content = $selectionElem.text(); + $targetELem = $('
      ' + content + '
      '); + $targetELem.insertAfter($selectionElem); + $selectionElem.remove(); + return; + } + if (nodeName === 'BLOCKQUOTE') { + // 撤销 quote + content = $selectionElem.text(); + $targetELem = $('

      ' + content + '

      '); + $targetELem.insertAfter($selectionElem); + $selectionElem.remove(); + } + }, + + tryChangeActive: function tryChangeActive(e) { + var editor = this.editor; + var $elem = this.$elem; + var reg = /^BLOCKQUOTE$/i; + var cmdValue = editor.cmd.queryCommandValue('formatBlock'); + if (reg.test(cmdValue)) { + this._active = true; + $elem.addClass('w-e-active'); + } else { + this._active = false; + $elem.removeClass('w-e-active'); + } + } +}; + +/* + menu - code +*/ +// 构造函数 +function Code(editor) { + this.editor = editor; + this.$elem = $('
      \n \n
      '); + this.type = 'panel'; + + // 当前是否 active 状态 + this._active = false; +} + +// 原型 +Code.prototype = { + constructor: Code, + + onClick: function onClick(e) { + var editor = this.editor; + var $startElem = editor.selection.getSelectionStartElem(); + var $endElem = editor.selection.getSelectionEndElem(); + var isSeleEmpty = editor.selection.isSelectionEmpty(); + var selectionText = editor.selection.getSelectionText(); + var $code = void 0; + + if (!$startElem.equal($endElem)) { + // 跨元素选择,不做处理 + editor.selection.restoreSelection(); + return; + } + if (!isSeleEmpty) { + // 选取不是空,用 包裹即可 + $code = $('' + selectionText + ''); + editor.cmd.do('insertElem', $code); + editor.selection.createRangeByElem($code, false); + editor.selection.restoreSelection(); + return; + } + + // 选取是空,且没有夸元素选择,则插入
      
      +        if (this._active) {
      +            // 选中状态,将编辑内容
      +            this._createPanel($startElem.html());
      +        } else {
      +            // 未选中状态,将创建内容
      +            this._createPanel();
      +        }
      +    },
      +
      +    _createPanel: function _createPanel(value) {
      +        var _this = this;
      +
      +        // value - 要编辑的内容
      +        value = value || '';
      +        var type = !value ? 'new' : 'edit';
      +        var textId = getRandom('texxt');
      +        var btnId = getRandom('btn');
      +
      +        var panel = new Panel(this, {
      +            width: 500,
      +            // 一个 Panel 包含多个 tab
      +            tabs: [{
      +                // 标题
      +                title: '插入代码',
      +                // 模板
      +                tpl: '
      \n \n
      \n \n
      \n
      ', + // 事件绑定 + events: [ + // 插入代码 + { + selector: '#' + btnId, + type: 'click', + fn: function fn() { + var $text = $('#' + textId); + var text = $text.val() || $text.html(); + text = replaceHtmlSymbol(text); + if (type === 'new') { + // 新插入 + _this._insertCode(text); + } else { + // 编辑更新 + _this._updateCode(text); + } + + // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 + return true; + } + }] + } // first tab end + ] // tabs end + }); // new Panel end + + // 显示 panel + panel.show(); + + // 记录属性 + this.panel = panel; + }, + + // 插入代码 + _insertCode: function _insertCode(value) { + var editor = this.editor; + editor.cmd.do('insertHTML', '
      ' + value + '


      '); + }, + + // 更新代码 + _updateCode: function _updateCode(value) { + var editor = this.editor; + var $selectionELem = editor.selection.getSelectionContainerElem(); + if (!$selectionELem) { + return; + } + $selectionELem.html(value); + editor.selection.restoreSelection(); + }, + + // 试图改变 active 状态 + tryChangeActive: function tryChangeActive(e) { + var editor = this.editor; + var $elem = this.$elem; + var $selectionELem = editor.selection.getSelectionContainerElem(); + if (!$selectionELem) { + return; + } + var $parentElem = $selectionELem.parent(); + if ($selectionELem.getNodeName() === 'CODE' && $parentElem.getNodeName() === 'PRE') { + this._active = true; + $elem.addClass('w-e-active'); + } else { + this._active = false; + $elem.removeClass('w-e-active'); + } + } +}; + +/* + menu - emoticon +*/ +// 构造函数 +function Emoticon(editor) { + this.editor = editor; + this.$elem = $('
      \n \n
      '); + this.type = 'panel'; + + // 当前是否 active 状态 + this._active = false; +} + +// 原型 +Emoticon.prototype = { + constructor: Emoticon, + + onClick: function onClick() { + this._createPanel(); + }, + + _createPanel: function _createPanel() { + var _this = this; + + var editor = this.editor; + var config = editor.config; + // 获取表情配置 + var emotions = config.emotions || []; + + // 创建表情 dropPanel 的配置 + var tabConfig = []; + emotions.forEach(function (emotData) { + var emotType = emotData.type; + var content = emotData.content || []; + + // 这一组表情最终拼接出来的 html + var faceHtml = ''; + + // emoji 表情 + if (emotType === 'emoji') { + content.forEach(function (item) { + if (item) { + faceHtml += '' + item + ''; + } + }); + } + // 图片表情 + if (emotType === 'image') { + content.forEach(function (item) { + var src = item.src; + var alt = item.alt; + if (src) { + // 加一个 data-w-e 属性,点击图片的时候不再提示编辑图片 + faceHtml += '' + alt + ''; + } + }); + } + + tabConfig.push({ + title: emotData.title, + tpl: '
      ' + faceHtml + '
      ', + events: [{ + selector: 'span.w-e-item', + type: 'click', + fn: function fn(e) { + var target = e.target; + var $target = $(target); + var nodeName = $target.getNodeName(); + + var insertHtml = void 0; + if (nodeName === 'IMG') { + // 插入图片 + insertHtml = $target.parent().html(); + } else { + // 插入 emoji + insertHtml = '' + $target.html() + ''; + } + + _this._insert(insertHtml); + // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 + return true; + } + }] + }); + }); + + var panel = new Panel(this, { + width: 300, + height: 200, + // 一个 Panel 包含多个 tab + tabs: tabConfig + }); + + // 显示 panel + panel.show(); + + // 记录属性 + this.panel = panel; + }, + + // 插入表情 + _insert: function _insert(emotHtml) { + var editor = this.editor; + editor.cmd.do('insertHTML', emotHtml); + } +}; + +/* + menu - table +*/ +// 构造函数 +function Table(editor) { + this.editor = editor; + this.$elem = $('
      '); + this.type = 'panel'; + + // 当前是否 active 状态 + this._active = false; +} + +// 原型 +Table.prototype = { + constructor: Table, + + onClick: function onClick() { + if (this._active) { + // 编辑现有表格 + this._createEditPanel(); + } else { + // 插入新表格 + this._createInsertPanel(); + } + }, + + // 创建插入新表格的 panel + _createInsertPanel: function _createInsertPanel() { + var _this = this; + + // 用到的 id + var btnInsertId = getRandom('btn'); + var textRowNum = getRandom('row'); + var textColNum = getRandom('col'); + + var panel = new Panel(this, { + width: 250, + // panel 包含多个 tab + tabs: [{ + // 标题 + title: '插入表格', + // 模板 + tpl: '
      \n

      \n \u521B\u5EFA\n \n \u884C\n \n \u5217\u7684\u8868\u683C\n

      \n
      \n \n
      \n
      ', + // 事件绑定 + events: [{ + // 点击按钮,插入表格 + selector: '#' + btnInsertId, + type: 'click', + fn: function fn() { + var rowNum = parseInt($('#' + textRowNum).val()); + var colNum = parseInt($('#' + textColNum).val()); + + if (rowNum && colNum && rowNum > 0 && colNum > 0) { + // form 数据有效 + _this._insert(rowNum, colNum); + } + + // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 + return true; + } + }] + } // first tab end + ] // tabs end + }); // panel end + + // 展示 panel + panel.show(); + + // 记录属性 + this.panel = panel; + }, + + // 插入表格 + _insert: function _insert(rowNum, colNum) { + // 拼接 table 模板 + var r = void 0, + c = void 0; + var html = ''; + for (r = 0; r < rowNum; r++) { + html += ''; + if (r === 0) { + for (c = 0; c < colNum; c++) { + html += ''; + } + } else { + for (c = 0; c < colNum; c++) { + html += ''; + } + } + html += ''; + } + html += '
        


      '; + + // 执行命令 + var editor = this.editor; + editor.cmd.do('insertHTML', html); + + // 防止 firefox 下出现 resize 的控制点 + editor.cmd.do('enableObjectResizing', false); + editor.cmd.do('enableInlineTableEditing', false); + }, + + // 创建编辑表格的 panel + _createEditPanel: function _createEditPanel() { + var _this2 = this; + + // 可用的 id + var addRowBtnId = getRandom('add-row'); + var addColBtnId = getRandom('add-col'); + var delRowBtnId = getRandom('del-row'); + var delColBtnId = getRandom('del-col'); + var delTableBtnId = getRandom('del-table'); + + // 创建 panel 对象 + var panel = new Panel(this, { + width: 320, + // panel 包含多个 tab + tabs: [{ + // 标题 + title: '编辑表格', + // 模板 + tpl: '
      \n
      \n \n \n \n \n
      \n
      \n \n \n
      ', + // 事件绑定 + events: [{ + // 增加行 + selector: '#' + addRowBtnId, + type: 'click', + fn: function fn() { + _this2._addRow(); + // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 + return true; + } + }, { + // 增加列 + selector: '#' + addColBtnId, + type: 'click', + fn: function fn() { + _this2._addCol(); + // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 + return true; + } + }, { + // 删除行 + selector: '#' + delRowBtnId, + type: 'click', + fn: function fn() { + _this2._delRow(); + // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 + return true; + } + }, { + // 删除列 + selector: '#' + delColBtnId, + type: 'click', + fn: function fn() { + _this2._delCol(); + // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 + return true; + } + }, { + // 删除表格 + selector: '#' + delTableBtnId, + type: 'click', + fn: function fn() { + _this2._delTable(); + // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 + return true; + } + }] + }] + }); + // 显示 panel + panel.show(); + }, + + // 获取选中的单元格的位置信息 + _getLocationData: function _getLocationData() { + var result = {}; + var editor = this.editor; + var $selectionELem = editor.selection.getSelectionContainerElem(); + if (!$selectionELem) { + return; + } + var nodeName = $selectionELem.getNodeName(); + if (nodeName !== 'TD' && nodeName !== 'TH') { + return; + } + + // 获取 td index + var $tr = $selectionELem.parent(); + var $tds = $tr.children(); + var tdLength = $tds.length; + $tds.forEach(function (td, index) { + if (td === $selectionELem[0]) { + // 记录并跳出循环 + result.td = { + index: index, + elem: td, + length: tdLength + }; + return false; + } + }); + + // 获取 tr index + var $tbody = $tr.parent(); + var $trs = $tbody.children(); + var trLength = $trs.length; + $trs.forEach(function (tr, index) { + if (tr === $tr[0]) { + // 记录并跳出循环 + result.tr = { + index: index, + elem: tr, + length: trLength + }; + return false; + } + }); + + // 返回结果 + return result; + }, + + // 增加行 + _addRow: function _addRow() { + // 获取当前单元格的位置信息 + var locationData = this._getLocationData(); + if (!locationData) { + return; + } + var trData = locationData.tr; + var $currentTr = $(trData.elem); + var tdData = locationData.td; + var tdLength = tdData.length; + + // 拼接即将插入的字符串 + var newTr = document.createElement('tr'); + var tpl = '', + i = void 0; + for (i = 0; i < tdLength; i++) { + tpl += ' '; + } + newTr.innerHTML = tpl; + // 插入 + $(newTr).insertAfter($currentTr); + }, + + // 增加列 + _addCol: function _addCol() { + // 获取当前单元格的位置信息 + var locationData = this._getLocationData(); + if (!locationData) { + return; + } + var trData = locationData.tr; + var tdData = locationData.td; + var tdIndex = tdData.index; + var $currentTr = $(trData.elem); + var $trParent = $currentTr.parent(); + var $trs = $trParent.children(); + + // 遍历所有行 + $trs.forEach(function (tr) { + var $tr = $(tr); + var $tds = $tr.children(); + var $currentTd = $tds.get(tdIndex); + var name = $currentTd.getNodeName().toLowerCase(); + + // new 一个 td,并插入 + var newTd = document.createElement(name); + $(newTd).insertAfter($currentTd); + }); + }, + + // 删除行 + _delRow: function _delRow() { + // 获取当前单元格的位置信息 + var locationData = this._getLocationData(); + if (!locationData) { + return; + } + var trData = locationData.tr; + var $currentTr = $(trData.elem); + $currentTr.remove(); + }, + + // 删除列 + _delCol: function _delCol() { + // 获取当前单元格的位置信息 + var locationData = this._getLocationData(); + if (!locationData) { + return; + } + var trData = locationData.tr; + var tdData = locationData.td; + var tdIndex = tdData.index; + var $currentTr = $(trData.elem); + var $trParent = $currentTr.parent(); + var $trs = $trParent.children(); + + // 遍历所有行 + $trs.forEach(function (tr) { + var $tr = $(tr); + var $tds = $tr.children(); + var $currentTd = $tds.get(tdIndex); + // 删除 + $currentTd.remove(); + }); + }, + + // 删除表格 + _delTable: function _delTable() { + var editor = this.editor; + var $selectionELem = editor.selection.getSelectionContainerElem(); + if (!$selectionELem) { + return; + } + var $table = $selectionELem.parentUntil('table'); + if (!$table) { + return; + } + $table.remove(); + }, + + // 试图改变 active 状态 + tryChangeActive: function tryChangeActive(e) { + var editor = this.editor; + var $elem = this.$elem; + var $selectionELem = editor.selection.getSelectionContainerElem(); + if (!$selectionELem) { + return; + } + var nodeName = $selectionELem.getNodeName(); + if (nodeName === 'TD' || nodeName === 'TH') { + this._active = true; + $elem.addClass('w-e-active'); + } else { + this._active = false; + $elem.removeClass('w-e-active'); + } + } +}; + +/* + menu - video +*/ +// 构造函数 +function Video(editor) { + this.editor = editor; + this.$elem = $('
      '); + this.type = 'panel'; + + // 当前是否 active 状态 + this._active = false; +} + +// 原型 +Video.prototype = { + constructor: Video, + + onClick: function onClick() { + this._createPanel(); + }, + + _createPanel: function _createPanel() { + var _this = this; + + // 创建 id + var textValId = getRandom('text-val'); + var btnId = getRandom('btn'); + + // 创建 panel + var panel = new Panel(this, { + width: 350, + // 一个 panel 多个 tab + tabs: [{ + // 标题 + title: '插入视频', + // 模板 + tpl: '
      \n \n
      \n \n
      \n
      ', + // 事件绑定 + events: [{ + selector: '#' + btnId, + type: 'click', + fn: function fn() { + var $text = $('#' + textValId); + var val = $text.val().trim(); + + // 测试用视频地址 + // + + if (val) { + // 插入视频 + _this._insert(val); + } + + // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 + return true; + } + }] + } // first tab end + ] // tabs end + }); // panel end + + // 显示 panel + panel.show(); + + // 记录属性 + this.panel = panel; + }, + + // 插入视频 + _insert: function _insert(val) { + var editor = this.editor; + editor.cmd.do('insertHTML', val + '


      '); + } +}; + +/* + menu - img +*/ +// 构造函数 +function Image(editor) { + this.editor = editor; + var imgMenuId = getRandom('w-e-img'); + this.$elem = $('
      '); + editor.imgMenuId = imgMenuId; + this.type = 'panel'; + + // 当前是否 active 状态 + this._active = false; +} + +// 原型 +Image.prototype = { + constructor: Image, + + onClick: function onClick() { + var editor = this.editor; + var config = editor.config; + if (config.qiniu) { + return; + } + if (this._active) { + this._createEditPanel(); + } else { + this._createInsertPanel(); + } + }, + + _createEditPanel: function _createEditPanel() { + var editor = this.editor; + + // id + var width30 = getRandom('width-30'); + var width50 = getRandom('width-50'); + var width100 = getRandom('width-100'); + var delBtn = getRandom('del-btn'); + + // tab 配置 + var tabsConfig = [{ + title: '编辑图片', + tpl: '
      \n
      \n \u6700\u5927\u5BBD\u5EA6\uFF1A\n \n \n \n
      \n
      \n \n \n
      ', + events: [{ + selector: '#' + width30, + type: 'click', + fn: function fn() { + var $img = editor._selectedImg; + if ($img) { + $img.css('max-width', '30%'); + } + // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 + return true; + } + }, { + selector: '#' + width50, + type: 'click', + fn: function fn() { + var $img = editor._selectedImg; + if ($img) { + $img.css('max-width', '50%'); + } + // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 + return true; + } + }, { + selector: '#' + width100, + type: 'click', + fn: function fn() { + var $img = editor._selectedImg; + if ($img) { + $img.css('max-width', '100%'); + } + // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 + return true; + } + }, { + selector: '#' + delBtn, + type: 'click', + fn: function fn() { + var $img = editor._selectedImg; + if ($img) { + $img.remove(); + } + // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 + return true; + } + }] + }]; + + // 创建 panel 并显示 + var panel = new Panel(this, { + width: 300, + tabs: tabsConfig + }); + panel.show(); + + // 记录属性 + this.panel = panel; + }, + + _createInsertPanel: function _createInsertPanel() { + var editor = this.editor; + var uploadImg = editor.uploadImg; + var config = editor.config; + + // id + var upTriggerId = getRandom('up-trigger'); + var upFileId = getRandom('up-file'); + var linkUrlId = getRandom('link-url'); + var linkBtnId = getRandom('link-btn'); + + // tabs 的配置 + var tabsConfig = [{ + title: '上传图片', + tpl: '
      \n
      \n \n
      \n
      \n \n
      \n
      ', + events: [{ + // 触发选择图片 + selector: '#' + upTriggerId, + type: 'click', + fn: function fn() { + var $file = $('#' + upFileId); + var fileElem = $file[0]; + if (fileElem) { + fileElem.click(); + } else { + // 返回 true 可关闭 panel + return true; + } + } + }, { + // 选择图片完毕 + selector: '#' + upFileId, + type: 'change', + fn: function fn() { + var $file = $('#' + upFileId); + var fileElem = $file[0]; + if (!fileElem) { + // 返回 true 可关闭 panel + return true; + } + + // 获取选中的 file 对象列表 + var fileList = fileElem.files; + if (fileList.length) { + uploadImg.uploadImg(fileList); + } + + // 返回 true 可关闭 panel + return true; + } + }] + }, // first tab end + { + title: '网络图片', + tpl: '
      \n \n
      \n \n
      \n
      ', + events: [{ + selector: '#' + linkBtnId, + type: 'click', + fn: function fn() { + var $linkUrl = $('#' + linkUrlId); + var url = $linkUrl.val().trim(); + + if (url) { + uploadImg.insertLinkImg(url); + } + + // 返回 true 表示函数执行结束之后关闭 panel + return true; + } + }] + } // second tab end + ]; // tabs end + + // 判断 tabs 的显示 + var tabsConfigResult = []; + if ((config.uploadImgShowBase64 || config.uploadImgServer || config.customUploadImg) && window.FileReader) { + // 显示“上传图片” + tabsConfigResult.push(tabsConfig[0]); + } + if (config.showLinkImg) { + // 显示“网络图片” + tabsConfigResult.push(tabsConfig[1]); + } + + // 创建 panel 并显示 + var panel = new Panel(this, { + width: 300, + tabs: tabsConfigResult + }); + panel.show(); + + // 记录属性 + this.panel = panel; + }, + + // 试图改变 active 状态 + tryChangeActive: function tryChangeActive(e) { + var editor = this.editor; + var $elem = this.$elem; + if (editor._selectedImg) { + this._active = true; + $elem.addClass('w-e-active'); + } else { + this._active = false; + $elem.removeClass('w-e-active'); + } + } +}; + +/* + 所有菜单的汇总 +*/ + +// 存储菜单的构造函数 +var MenuConstructors = {}; + +MenuConstructors.bold = Bold; + +MenuConstructors.head = Head; + +MenuConstructors.fontSize = FontSize; + +MenuConstructors.fontName = FontName; + +MenuConstructors.link = Link; + +MenuConstructors.italic = Italic; + +MenuConstructors.redo = Redo; + +MenuConstructors.strikeThrough = StrikeThrough; + +MenuConstructors.underline = Underline; + +MenuConstructors.undo = Undo; + +MenuConstructors.list = List; + +MenuConstructors.justify = Justify; + +MenuConstructors.foreColor = ForeColor; + +MenuConstructors.backColor = BackColor; + +MenuConstructors.quote = Quote; + +MenuConstructors.code = Code; + +MenuConstructors.emoticon = Emoticon; + +MenuConstructors.table = Table; + +MenuConstructors.video = Video; + +MenuConstructors.image = Image; + +/* + 菜单集合 +*/ +// 构造函数 +function Menus(editor) { + this.editor = editor; + this.menus = {}; +} + +// 修改原型 +Menus.prototype = { + constructor: Menus, + + // 初始化菜单 + init: function init() { + var _this = this; + + var editor = this.editor; + var config = editor.config || {}; + var configMenus = config.menus || []; // 获取配置中的菜单 + + // 根据配置信息,创建菜单 + configMenus.forEach(function (menuKey) { + var MenuConstructor = MenuConstructors[menuKey]; + if (MenuConstructor && typeof MenuConstructor === 'function') { + // 创建单个菜单 + _this.menus[menuKey] = new MenuConstructor(editor); + } + }); + + // 添加到菜单栏 + this._addToToolbar(); + + // 绑定事件 + this._bindEvent(); + }, + + // 添加到菜单栏 + _addToToolbar: function _addToToolbar() { + var editor = this.editor; + var $toolbarElem = editor.$toolbarElem; + var menus = this.menus; + var config = editor.config; + // config.zIndex 是配置的编辑区域的 z-index,菜单的 z-index 得在其基础上 +1 + var zIndex = config.zIndex + 1; + objForEach(menus, function (key, menu) { + var $elem = menu.$elem; + if ($elem) { + // 设置 z-index + $elem.css('z-index', zIndex); + $toolbarElem.append($elem); + } + }); + }, + + // 绑定菜单 click mouseenter 事件 + _bindEvent: function _bindEvent() { + var menus = this.menus; + var editor = this.editor; + objForEach(menus, function (key, menu) { + var type = menu.type; + if (!type) { + return; + } + var $elem = menu.$elem; + var droplist = menu.droplist; + var panel = menu.panel; + + // 点击类型,例如 bold + if (type === 'click' && menu.onClick) { + $elem.on('click', function (e) { + if (editor.selection.getRange() == null) { + return; + } + menu.onClick(e); + }); + } + + // 下拉框,例如 head + if (type === 'droplist' && droplist) { + $elem.on('mouseenter', function (e) { + if (editor.selection.getRange() == null) { + return; + } + // 显示 + droplist.showTimeoutId = setTimeout(function () { + droplist.show(); + }, 200); + }).on('mouseleave', function (e) { + // 隐藏 + droplist.hideTimeoutId = setTimeout(function () { + droplist.hide(); + }, 0); + }); + } + + // 弹框类型,例如 link + if (type === 'panel' && menu.onClick) { + $elem.on('click', function (e) { + e.stopPropagation(); + if (editor.selection.getRange() == null) { + return; + } + // 在自定义事件中显示 panel + menu.onClick(e); + }); + } + }); + }, + + // 尝试修改菜单状态 + changeActive: function changeActive() { + var menus = this.menus; + objForEach(menus, function (key, menu) { + if (menu.tryChangeActive) { + setTimeout(function () { + menu.tryChangeActive(); + }, 100); + } + }); + } +}; + +/* + 粘贴信息的处理 +*/ + +// 获取粘贴的纯文本 +function getPasteText(e) { + var clipboardData = e.clipboardData || e.originalEvent && e.originalEvent.clipboardData; + var pasteText = void 0; + if (clipboardData == null) { + pasteText = window.clipboardData && window.clipboardData.getData('text'); + } else { + pasteText = clipboardData.getData('text/plain'); + } + + return replaceHtmlSymbol(pasteText); +} + +// 获取粘贴的html +function getPasteHtml(e, filterStyle, ignoreImg) { + var clipboardData = e.clipboardData || e.originalEvent && e.originalEvent.clipboardData; + var pasteText = void 0, + pasteHtml = void 0; + if (clipboardData == null) { + pasteText = window.clipboardData && window.clipboardData.getData('text'); + } else { + pasteText = clipboardData.getData('text/plain'); + pasteHtml = clipboardData.getData('text/html'); + } + if (!pasteHtml && pasteText) { + pasteHtml = '

      ' + replaceHtmlSymbol(pasteText) + '

      '; + } + if (!pasteHtml) { + return; + } + + // 过滤word中状态过来的无用字符 + var docSplitHtml = pasteHtml.split(''); + if (docSplitHtml.length === 2) { + pasteHtml = docSplitHtml[0]; + } + + // 过滤无用标签 + pasteHtml = pasteHtml.replace(/<(meta|script|link).+?>/igm, ''); + // 去掉注释 + pasteHtml = pasteHtml.replace(//mg, ''); + // 过滤 data-xxx 属性 + pasteHtml = pasteHtml.replace(/\s?data-.+?=('|").+?('|")/igm, ''); + + if (ignoreImg) { + // 忽略图片 + pasteHtml = pasteHtml.replace(//igm, ''); + } + + if (filterStyle) { + // 过滤样式 + pasteHtml = pasteHtml.replace(/\s?(class|style)=('|").*?('|")/igm, ''); + } else { + // 保留样式 + pasteHtml = pasteHtml.replace(/\s?class=('|").*?('|")/igm, ''); + } + + return pasteHtml; +} + +// 获取粘贴的图片文件 +function getPasteImgs(e) { + var result = []; + var txt = getPasteText(e); + if (txt) { + // 有文字,就忽略图片 + return result; + } + + var clipboardData = e.clipboardData || e.originalEvent && e.originalEvent.clipboardData || {}; + var items = clipboardData.items; + if (!items) { + return result; + } + + objForEach(items, function (key, value) { + var type = value.type; + if (/image/i.test(type)) { + result.push(value.getAsFile()); + } + }); + + return result; +} + +/* + 编辑区域 +*/ + +// 获取一个 elem.childNodes 的 JSON 数据 +function getChildrenJSON($elem) { + var result = []; + var $children = $elem.childNodes() || []; // 注意 childNodes() 可以获取文本节点 + $children.forEach(function (curElem) { + var elemResult = void 0; + var nodeType = curElem.nodeType; + + // 文本节点 + if (nodeType === 3) { + elemResult = curElem.textContent; + elemResult = replaceHtmlSymbol(elemResult); + } + + // 普通 DOM 节点 + if (nodeType === 1) { + elemResult = {}; + + // tag + elemResult.tag = curElem.nodeName.toLowerCase(); + // attr + var attrData = []; + var attrList = curElem.attributes || {}; + var attrListLength = attrList.length || 0; + for (var i = 0; i < attrListLength; i++) { + var attr = attrList[i]; + attrData.push({ + name: attr.name, + value: attr.value + }); + } + elemResult.attrs = attrData; + // children(递归) + elemResult.children = getChildrenJSON($(curElem)); + } + + result.push(elemResult); + }); + return result; +} + +// 构造函数 +function Text(editor) { + this.editor = editor; +} + +// 修改原型 +Text.prototype = { + constructor: Text, + + // 初始化 + init: function init() { + // 绑定事件 + this._bindEvent(); + }, + + // 清空内容 + clear: function clear() { + this.html('


      '); + }, + + // 获取 设置 html + html: function html(val) { + var editor = this.editor; + var $textElem = editor.$textElem; + var html = void 0; + if (val == null) { + html = $textElem.html(); + // 未选中任何内容的时候点击“加粗”或者“斜体”等按钮,就得需要一个空的占位符 ​ ,这里替换掉 + html = html.replace(/\u200b/gm, ''); + return html; + } else { + $textElem.html(val); + + // 初始化选取,将光标定位到内容尾部 + editor.initSelection(); + } + }, + + // 获取 JSON + getJSON: function getJSON() { + var editor = this.editor; + var $textElem = editor.$textElem; + return getChildrenJSON($textElem); + }, + + // 获取 设置 text + text: function text(val) { + var editor = this.editor; + var $textElem = editor.$textElem; + var text = void 0; + if (val == null) { + text = $textElem.text(); + // 未选中任何内容的时候点击“加粗”或者“斜体”等按钮,就得需要一个空的占位符 ​ ,这里替换掉 + text = text.replace(/\u200b/gm, ''); + return text; + } else { + $textElem.text('

      ' + val + '

      '); + + // 初始化选取,将光标定位到内容尾部 + editor.initSelection(); + } + }, + + // 追加内容 + append: function append(html) { + var editor = this.editor; + var $textElem = editor.$textElem; + $textElem.append($(html)); + + // 初始化选取,将光标定位到内容尾部 + editor.initSelection(); + }, + + // 绑定事件 + _bindEvent: function _bindEvent() { + // 实时保存选取 + this._saveRangeRealTime(); + + // 按回车建时的特殊处理 + this._enterKeyHandle(); + + // 清空时保留


      + this._clearHandle(); + + // 粘贴事件(粘贴文字,粘贴图片) + this._pasteHandle(); + + // tab 特殊处理 + this._tabHandle(); + + // img 点击 + this._imgHandle(); + + // 拖拽事件 + this._dragHandle(); + }, + + // 实时保存选取 + _saveRangeRealTime: function _saveRangeRealTime() { + var editor = this.editor; + var $textElem = editor.$textElem; + + // 保存当前的选区 + function saveRange(e) { + // 随时保存选区 + editor.selection.saveRange(); + // 更新按钮 ative 状态 + editor.menus.changeActive(); + } + // 按键后保存 + $textElem.on('keyup', saveRange); + $textElem.on('mousedown', function (e) { + // mousedown 状态下,鼠标滑动到编辑区域外面,也需要保存选区 + $textElem.on('mouseleave', saveRange); + }); + $textElem.on('mouseup', function (e) { + saveRange(); + // 在编辑器区域之内完成点击,取消鼠标滑动到编辑区外面的事件 + $textElem.off('mouseleave', saveRange); + }); + }, + + // 按回车键时的特殊处理 + _enterKeyHandle: function _enterKeyHandle() { + var editor = this.editor; + var $textElem = editor.$textElem; + + function insertEmptyP($selectionElem) { + var $p = $('


      '); + $p.insertBefore($selectionElem); + editor.selection.createRangeByElem($p, true); + editor.selection.restoreSelection(); + $selectionElem.remove(); + } + + // 将回车之后生成的非

      的顶级标签,改为

      + function pHandle(e) { + var $selectionElem = editor.selection.getSelectionContainerElem(); + var $parentElem = $selectionElem.parent(); + + if ($parentElem.html() === '
      ') { + // 回车之前光标所在一个

      .....

      ,忽然回车生成一个空的


      + // 而且继续回车跳不出去,因此只能特殊处理 + insertEmptyP($selectionElem); + return; + } + + if (!$parentElem.equal($textElem)) { + // 不是顶级标签 + return; + } + + var nodeName = $selectionElem.getNodeName(); + if (nodeName === 'P') { + // 当前的标签是 P ,不用做处理 + return; + } + + if ($selectionElem.text()) { + // 有内容,不做处理 + return; + } + + // 插入

      ,并将选取定位到

      ,删除当前标签 + insertEmptyP($selectionElem); + } + + $textElem.on('keyup', function (e) { + if (e.keyCode !== 13) { + // 不是回车键 + return; + } + // 将回车之后生成的非

      的顶级标签,改为

      + pHandle(e); + }); + + //

      回车时 特殊处理 + function codeHandle(e) { + var $selectionElem = editor.selection.getSelectionContainerElem(); + if (!$selectionElem) { + return; + } + var $parentElem = $selectionElem.parent(); + var selectionNodeName = $selectionElem.getNodeName(); + var parentNodeName = $parentElem.getNodeName(); + + if (selectionNodeName !== 'CODE' || parentNodeName !== 'PRE') { + // 不符合要求 忽略 + return; + } + + if (!editor.cmd.queryCommandSupported('insertHTML')) { + // 必须原生支持 insertHTML 命令 + return; + } + + // 处理:光标定位到代码末尾,联系点击两次回车,即跳出代码块 + if (editor._willBreakCode === true) { + // 此时可以跳出代码块 + // 插入

      ,并将选取定位到

      + var $p = $('


      '); + $p.insertAfter($parentElem); + editor.selection.createRangeByElem($p, true); + editor.selection.restoreSelection(); + + // 修改状态 + editor._willBreakCode = false; + + e.preventDefault(); + return; + } + + var _startOffset = editor.selection.getRange().startOffset; + + // 处理:回车时,不能插入
      而是插入 \n ,因为是在 pre 标签里面 + editor.cmd.do('insertHTML', '\n'); + editor.selection.saveRange(); + if (editor.selection.getRange().startOffset === _startOffset) { + // 没起作用,再来一遍 + editor.cmd.do('insertHTML', '\n'); + } + + var codeLength = $selectionElem.html().length; + if (editor.selection.getRange().startOffset + 1 === codeLength) { + // 说明光标在代码最后的位置,执行了回车操作 + // 记录下来,以便下次回车时候跳出 code + editor._willBreakCode = true; + } + + // 阻止默认行为 + e.preventDefault(); + } + + $textElem.on('keydown', function (e) { + if (e.keyCode !== 13) { + // 不是回车键 + // 取消即将跳转代码块的记录 + editor._willBreakCode = false; + return; + } + //
      回车时 特殊处理 + codeHandle(e); + }); + }, + + // 清空时保留


      + _clearHandle: function _clearHandle() { + var editor = this.editor; + var $textElem = editor.$textElem; + + $textElem.on('keydown', function (e) { + if (e.keyCode !== 8) { + return; + } + var txtHtml = $textElem.html().toLowerCase().trim(); + if (txtHtml === '


      ') { + // 最后剩下一个空行,就不再删除了 + e.preventDefault(); + return; + } + }); + + $textElem.on('keyup', function (e) { + if (e.keyCode !== 8) { + return; + } + var $p = void 0; + var txtHtml = $textElem.html().toLowerCase().trim(); + + // firefox 时用 txtHtml === '
      ' 判断,其他用 !txtHtml 判断 + if (!txtHtml || txtHtml === '
      ') { + // 内容空了 + $p = $('


      '); + $textElem.html(''); // 一定要先清空,否则在 firefox 下有问题 + $textElem.append($p); + editor.selection.createRangeByElem($p, false, true); + editor.selection.restoreSelection(); + } + }); + }, + + // 粘贴事件(粘贴文字 粘贴图片) + _pasteHandle: function _pasteHandle() { + var editor = this.editor; + var config = editor.config; + var pasteFilterStyle = config.pasteFilterStyle; + var pasteTextHandle = config.pasteTextHandle; + var ignoreImg = config.pasteIgnoreImg; + var $textElem = editor.$textElem; + + // 粘贴图片、文本的事件,每次只能执行一个 + // 判断该次粘贴事件是否可以执行 + var pasteTime = 0; + function canDo() { + var now = Date.now(); + var flag = false; + if (now - pasteTime >= 100) { + // 间隔大于 100 ms ,可以执行 + flag = true; + } + pasteTime = now; + return flag; + } + function resetTime() { + pasteTime = 0; + } + + // 粘贴文字 + $textElem.on('paste', function (e) { + if (UA.isIE()) { + return; + } else { + // 阻止默认行为,使用 execCommand 的粘贴命令 + e.preventDefault(); + } + + // 粘贴图片和文本,只能同时使用一个 + if (!canDo()) { + return; + } + + // 获取粘贴的文字 + var pasteHtml = getPasteHtml(e, pasteFilterStyle, ignoreImg); + var pasteText = getPasteText(e); + pasteText = pasteText.replace(/\n/gm, '
      '); + + var $selectionElem = editor.selection.getSelectionContainerElem(); + if (!$selectionElem) { + return; + } + var nodeName = $selectionElem.getNodeName(); + + // code 中只能粘贴纯文本 + if (nodeName === 'CODE' || nodeName === 'PRE') { + if (pasteTextHandle && isFunction(pasteTextHandle)) { + // 用户自定义过滤处理粘贴内容 + pasteText = '' + (pasteTextHandle(pasteText) || ''); + } + editor.cmd.do('insertHTML', '

      ' + pasteText + '

      '); + return; + } + + // 先放开注释,有问题再追查 ———— + // // 表格中忽略,可能会出现异常问题 + // if (nodeName === 'TD' || nodeName === 'TH') { + // return + // } + + if (!pasteHtml) { + // 没有内容,可继续执行下面的图片粘贴 + resetTime(); + return; + } + try { + // firefox 中,获取的 pasteHtml 可能是没有
        包裹的
      • + // 因此执行 insertHTML 会报错 + if (pasteTextHandle && isFunction(pasteTextHandle)) { + // 用户自定义过滤处理粘贴内容 + pasteHtml = '' + (pasteTextHandle(pasteHtml) || ''); + } + editor.cmd.do('insertHTML', pasteHtml); + } catch (ex) { + // 此时使用 pasteText 来兼容一下 + if (pasteTextHandle && isFunction(pasteTextHandle)) { + // 用户自定义过滤处理粘贴内容 + pasteText = '' + (pasteTextHandle(pasteText) || ''); + } + editor.cmd.do('insertHTML', '

        ' + pasteText + '

        '); + } + }); + + // 粘贴图片 + $textElem.on('paste', function (e) { + if (UA.isIE()) { + return; + } else { + e.preventDefault(); + } + + // 粘贴图片和文本,只能同时使用一个 + if (!canDo()) { + return; + } + + // 获取粘贴的图片 + var pasteFiles = getPasteImgs(e); + if (!pasteFiles || !pasteFiles.length) { + return; + } + + // 获取当前的元素 + var $selectionElem = editor.selection.getSelectionContainerElem(); + if (!$selectionElem) { + return; + } + var nodeName = $selectionElem.getNodeName(); + + // code 中粘贴忽略 + if (nodeName === 'CODE' || nodeName === 'PRE') { + return; + } + + // 上传图片 + var uploadImg = editor.uploadImg; + uploadImg.uploadImg(pasteFiles); + }); + }, + + // tab 特殊处理 + _tabHandle: function _tabHandle() { + var editor = this.editor; + var $textElem = editor.$textElem; + + $textElem.on('keydown', function (e) { + if (e.keyCode !== 9) { + return; + } + if (!editor.cmd.queryCommandSupported('insertHTML')) { + // 必须原生支持 insertHTML 命令 + return; + } + var $selectionElem = editor.selection.getSelectionContainerElem(); + if (!$selectionElem) { + return; + } + var $parentElem = $selectionElem.parent(); + var selectionNodeName = $selectionElem.getNodeName(); + var parentNodeName = $parentElem.getNodeName(); + + if (selectionNodeName === 'CODE' && parentNodeName === 'PRE') { + //
         里面
        +                editor.cmd.do('insertHTML', '    ');
        +            } else {
        +                // 普通文字
        +                editor.cmd.do('insertHTML', '    ');
        +            }
        +
        +            e.preventDefault();
        +        });
        +    },
        +
        +    // img 点击
        +    _imgHandle: function _imgHandle() {
        +        var editor = this.editor;
        +        var $textElem = editor.$textElem;
        +
        +        // 为图片增加 selected 样式
        +        $textElem.on('click', 'img', function (e) {
        +            var img = this;
        +            var $img = $(img);
        +
        +            if ($img.attr('data-w-e') === '1') {
        +                // 是表情图片,忽略
        +                return;
        +            }
        +
        +            // 记录当前点击过的图片
        +            editor._selectedImg = $img;
        +
        +            // 修改选区并 restore ,防止用户此时点击退格键,会删除其他内容
        +            editor.selection.createRangeByElem($img);
        +            editor.selection.restoreSelection();
        +        });
        +
        +        // 去掉图片的 selected 样式
        +        $textElem.on('click  keyup', function (e) {
        +            if (e.target.matches('img')) {
        +                // 点击的是图片,忽略
        +                return;
        +            }
        +            // 删除记录
        +            editor._selectedImg = null;
        +        });
        +    },
        +
        +    // 拖拽事件
        +    _dragHandle: function _dragHandle() {
        +        var editor = this.editor;
        +
        +        // 禁用 document 拖拽事件
        +        var $document = $(document);
        +        $document.on('dragleave drop dragenter dragover', function (e) {
        +            e.preventDefault();
        +        });
        +
        +        // 添加编辑区域拖拽事件
        +        var $textElem = editor.$textElem;
        +        $textElem.on('drop', function (e) {
        +            e.preventDefault();
        +            var files = e.dataTransfer && e.dataTransfer.files;
        +            if (!files || !files.length) {
        +                return;
        +            }
        +
        +            // 上传图片
        +            var uploadImg = editor.uploadImg;
        +            uploadImg.uploadImg(files);
        +        });
        +    }
        +};
        +
        +/*
        +    命令,封装 document.execCommand
        +*/
        +
        +// 构造函数
        +function Command(editor) {
        +    this.editor = editor;
        +}
        +
        +// 修改原型
        +Command.prototype = {
        +    constructor: Command,
        +
        +    // 执行命令
        +    do: function _do(name, value) {
        +        var editor = this.editor;
        +
        +        // 使用 styleWithCSS
        +        if (!editor._useStyleWithCSS) {
        +            document.execCommand('styleWithCSS', null, true);
        +            editor._useStyleWithCSS = true;
        +        }
        +
        +        // 如果无选区,忽略
        +        if (!editor.selection.getRange()) {
        +            return;
        +        }
        +
        +        // 恢复选取
        +        editor.selection.restoreSelection();
        +
        +        // 执行
        +        var _name = '_' + name;
        +        if (this[_name]) {
        +            // 有自定义事件
        +            this[_name](value);
        +        } else {
        +            // 默认 command
        +            this._execCommand(name, value);
        +        }
        +
        +        // 修改菜单状态
        +        editor.menus.changeActive();
        +
        +        // 最后,恢复选取保证光标在原来的位置闪烁
        +        editor.selection.saveRange();
        +        editor.selection.restoreSelection();
        +
        +        // 触发 onchange
        +        editor.change && editor.change();
        +    },
        +
        +    // 自定义 insertHTML 事件
        +    _insertHTML: function _insertHTML(html) {
        +        var editor = this.editor;
        +        var range = editor.selection.getRange();
        +
        +        if (this.queryCommandSupported('insertHTML')) {
        +            // W3C
        +            this._execCommand('insertHTML', html);
        +        } else if (range.insertNode) {
        +            // IE
        +            range.deleteContents();
        +            range.insertNode($(html)[0]);
        +        } else if (range.pasteHTML) {
        +            // IE <= 10
        +            range.pasteHTML(html);
        +        }
        +    },
        +
        +    // 插入 elem
        +    _insertElem: function _insertElem($elem) {
        +        var editor = this.editor;
        +        var range = editor.selection.getRange();
        +
        +        if (range.insertNode) {
        +            range.deleteContents();
        +            range.insertNode($elem[0]);
        +        }
        +    },
        +
        +    // 封装 execCommand
        +    _execCommand: function _execCommand(name, value) {
        +        document.execCommand(name, false, value);
        +    },
        +
        +    // 封装 document.queryCommandValue
        +    queryCommandValue: function queryCommandValue(name) {
        +        return document.queryCommandValue(name);
        +    },
        +
        +    // 封装 document.queryCommandState
        +    queryCommandState: function queryCommandState(name) {
        +        return document.queryCommandState(name);
        +    },
        +
        +    // 封装 document.queryCommandSupported
        +    queryCommandSupported: function queryCommandSupported(name) {
        +        return document.queryCommandSupported(name);
        +    }
        +};
        +
        +/*
        +    selection range API
        +*/
        +
        +// 构造函数
        +function API(editor) {
        +    this.editor = editor;
        +    this._currentRange = null;
        +}
        +
        +// 修改原型
        +API.prototype = {
        +    constructor: API,
        +
        +    // 获取 range 对象
        +    getRange: function getRange() {
        +        return this._currentRange;
        +    },
        +
        +    // 保存选区
        +    saveRange: function saveRange(_range) {
        +        if (_range) {
        +            // 保存已有选区
        +            this._currentRange = _range;
        +            return;
        +        }
        +
        +        // 获取当前的选区
        +        var selection = window.getSelection();
        +        if (selection.rangeCount === 0) {
        +            return;
        +        }
        +        var range = selection.getRangeAt(0);
        +
        +        // 判断选区内容是否在编辑内容之内
        +        var $containerElem = this.getSelectionContainerElem(range);
        +        if (!$containerElem) {
        +            return;
        +        }
        +
        +        // 判断选区内容是否在不可编辑区域之内
        +        if ($containerElem.attr('contenteditable') === 'false' || $containerElem.parentUntil('[contenteditable=false]')) {
        +            return;
        +        }
        +
        +        var editor = this.editor;
        +        var $textElem = editor.$textElem;
        +        if ($textElem.isContain($containerElem)) {
        +            // 是编辑内容之内的
        +            this._currentRange = range;
        +        }
        +    },
        +
        +    // 折叠选区
        +    collapseRange: function collapseRange(toStart) {
        +        if (toStart == null) {
        +            // 默认为 false
        +            toStart = false;
        +        }
        +        var range = this._currentRange;
        +        if (range) {
        +            range.collapse(toStart);
        +        }
        +    },
        +
        +    // 选中区域的文字
        +    getSelectionText: function getSelectionText() {
        +        var range = this._currentRange;
        +        if (range) {
        +            return this._currentRange.toString();
        +        } else {
        +            return '';
        +        }
        +    },
        +
        +    // 选区的 $Elem
        +    getSelectionContainerElem: function getSelectionContainerElem(range) {
        +        range = range || this._currentRange;
        +        var elem = void 0;
        +        if (range) {
        +            elem = range.commonAncestorContainer;
        +            return $(elem.nodeType === 1 ? elem : elem.parentNode);
        +        }
        +    },
        +    getSelectionStartElem: function getSelectionStartElem(range) {
        +        range = range || this._currentRange;
        +        var elem = void 0;
        +        if (range) {
        +            elem = range.startContainer;
        +            return $(elem.nodeType === 1 ? elem : elem.parentNode);
        +        }
        +    },
        +    getSelectionEndElem: function getSelectionEndElem(range) {
        +        range = range || this._currentRange;
        +        var elem = void 0;
        +        if (range) {
        +            elem = range.endContainer;
        +            return $(elem.nodeType === 1 ? elem : elem.parentNode);
        +        }
        +    },
        +
        +    // 选区是否为空
        +    isSelectionEmpty: function isSelectionEmpty() {
        +        var range = this._currentRange;
        +        if (range && range.startContainer) {
        +            if (range.startContainer === range.endContainer) {
        +                if (range.startOffset === range.endOffset) {
        +                    return true;
        +                }
        +            }
        +        }
        +        return false;
        +    },
        +
        +    // 恢复选区
        +    restoreSelection: function restoreSelection() {
        +        var selection = window.getSelection();
        +        selection.removeAllRanges();
        +        selection.addRange(this._currentRange);
        +    },
        +
        +    // 创建一个空白(即 ​ 字符)选区
        +    createEmptyRange: function createEmptyRange() {
        +        var editor = this.editor;
        +        var range = this.getRange();
        +        var $elem = void 0;
        +
        +        if (!range) {
        +            // 当前无 range
        +            return;
        +        }
        +        if (!this.isSelectionEmpty()) {
        +            // 当前选区必须没有内容才可以
        +            return;
        +        }
        +
        +        try {
        +            // 目前只支持 webkit 内核
        +            if (UA.isWebkit()) {
        +                // 插入 ​
        +                editor.cmd.do('insertHTML', '​');
        +                // 修改 offset 位置
        +                range.setEnd(range.endContainer, range.endOffset + 1);
        +                // 存储
        +                this.saveRange(range);
        +            } else {
        +                $elem = $('');
        +                editor.cmd.do('insertElem', $elem);
        +                this.createRangeByElem($elem, true);
        +            }
        +        } catch (ex) {
        +            // 部分情况下会报错,兼容一下
        +        }
        +    },
        +
        +    // 根据 $Elem 设置选区
        +    createRangeByElem: function createRangeByElem($elem, toStart, isContent) {
        +        // $elem - 经过封装的 elem
        +        // toStart - true 开始位置,false 结束位置
        +        // isContent - 是否选中Elem的内容
        +        if (!$elem.length) {
        +            return;
        +        }
        +
        +        var elem = $elem[0];
        +        var range = document.createRange();
        +
        +        if (isContent) {
        +            range.selectNodeContents(elem);
        +        } else {
        +            range.selectNode(elem);
        +        }
        +
        +        if (typeof toStart === 'boolean') {
        +            range.collapse(toStart);
        +        }
        +
        +        // 存储 range
        +        this.saveRange(range);
        +    }
        +};
        +
        +/*
        +    上传进度条
        +*/
        +
        +function Progress(editor) {
        +    this.editor = editor;
        +    this._time = 0;
        +    this._isShow = false;
        +    this._isRender = false;
        +    this._timeoutId = 0;
        +    this.$textContainer = editor.$textContainerElem;
        +    this.$bar = $('
        '); +} + +Progress.prototype = { + constructor: Progress, + + show: function show(progress) { + var _this = this; + + // 状态处理 + if (this._isShow) { + return; + } + this._isShow = true; + + // 渲染 + var $bar = this.$bar; + if (!this._isRender) { + var $textContainer = this.$textContainer; + $textContainer.append($bar); + } else { + this._isRender = true; + } + + // 改变进度(节流,100ms 渲染一次) + if (Date.now() - this._time > 100) { + if (progress <= 1) { + $bar.css('width', progress * 100 + '%'); + this._time = Date.now(); + } + } + + // 隐藏 + var timeoutId = this._timeoutId; + if (timeoutId) { + clearTimeout(timeoutId); + } + timeoutId = setTimeout(function () { + _this._hide(); + }, 500); + }, + + _hide: function _hide() { + var $bar = this.$bar; + $bar.remove(); + + // 修改状态 + this._time = 0; + this._isShow = false; + this._isRender = false; + } +}; + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { + return typeof obj; +} : function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; +}; + +/* + 上传图片 +*/ + +// 构造函数 +function UploadImg(editor) { + this.editor = editor; +} + +// 原型 +UploadImg.prototype = { + constructor: UploadImg, + + // 根据 debug 弹出不同的信息 + _alert: function _alert(alertInfo, debugInfo) { + var editor = this.editor; + var debug = editor.config.debug; + var customAlert = editor.config.customAlert; + + if (debug) { + throw new Error('wangEditor: ' + (debugInfo || alertInfo)); + } else { + if (customAlert && typeof customAlert === 'function') { + customAlert(alertInfo); + } else { + alert(alertInfo); + } + } + }, + + // 根据链接插入图片 + insertLinkImg: function insertLinkImg(link) { + var _this2 = this; + + if (!link) { + return; + } + var editor = this.editor; + var config = editor.config; + + // 校验格式 + var linkImgCheck = config.linkImgCheck; + var checkResult = void 0; + if (linkImgCheck && typeof linkImgCheck === 'function') { + checkResult = linkImgCheck(link); + if (typeof checkResult === 'string') { + // 校验失败,提示信息 + alert(checkResult); + return; + } + } + + editor.cmd.do('insertHTML', ''); + + // 验证图片 url 是否有效,无效的话给出提示 + var img = document.createElement('img'); + img.onload = function () { + var callback = config.linkImgCallback; + if (callback && typeof callback === 'function') { + callback(link); + } + + img = null; + }; + img.onerror = function () { + img = null; + // 无法成功下载图片 + _this2._alert('插入图片错误', 'wangEditor: \u63D2\u5165\u56FE\u7247\u51FA\u9519\uFF0C\u56FE\u7247\u94FE\u63A5\u662F "' + link + '"\uFF0C\u4E0B\u8F7D\u8BE5\u94FE\u63A5\u5931\u8D25'); + return; + }; + img.onabort = function () { + img = null; + }; + img.src = link; + }, + + // 上传图片 + uploadImg: function uploadImg(files) { + var _this3 = this; + + if (!files || !files.length) { + return; + } + + // ------------------------------ 获取配置信息 ------------------------------ + var editor = this.editor; + var config = editor.config; + var uploadImgServer = config.uploadImgServer; + var uploadImgShowBase64 = config.uploadImgShowBase64; + + var maxSize = config.uploadImgMaxSize; + var maxSizeM = maxSize / 1024 / 1024; + var maxLength = config.uploadImgMaxLength || 10000; + var uploadFileName = config.uploadFileName || ''; + var uploadImgParams = config.uploadImgParams || {}; + var uploadImgParamsWithUrl = config.uploadImgParamsWithUrl; + var uploadImgHeaders = config.uploadImgHeaders || {}; + var hooks = config.uploadImgHooks || {}; + var timeout = config.uploadImgTimeout || 3000; + var withCredentials = config.withCredentials; + if (withCredentials == null) { + withCredentials = false; + } + var customUploadImg = config.customUploadImg; + + if (!customUploadImg) { + // 没有 customUploadImg 的情况下,需要如下两个配置才能继续进行图片上传 + if (!uploadImgServer && !uploadImgShowBase64) { + return; + } + } + + // ------------------------------ 验证文件信息 ------------------------------ + var resultFiles = []; + var errInfo = []; + arrForEach(files, function (file) { + var name = file.name; + var size = file.size; + + // chrome 低版本 name === undefined + if (!name || !size) { + return; + } + + if (/\.(jpg|jpeg|png|bmp|gif|webp)$/i.test(name) === false) { + // 后缀名不合法,不是图片 + errInfo.push('\u3010' + name + '\u3011\u4E0D\u662F\u56FE\u7247'); + return; + } + if (maxSize < size) { + // 上传图片过大 + errInfo.push('\u3010' + name + '\u3011\u5927\u4E8E ' + maxSizeM + 'M'); + return; + } + + // 验证通过的加入结果列表 + resultFiles.push(file); + }); + // 抛出验证信息 + if (errInfo.length) { + this._alert('图片验证未通过: \n' + errInfo.join('\n')); + return; + } + if (resultFiles.length > maxLength) { + this._alert('一次最多上传' + maxLength + '张图片'); + return; + } + + // ------------------------------ 自定义上传 ------------------------------ + if (customUploadImg && typeof customUploadImg === 'function') { + customUploadImg(resultFiles, this.insertLinkImg.bind(this)); + + // 阻止以下代码执行 + return; + } + + // 添加图片数据 + var formdata = new FormData(); + arrForEach(resultFiles, function (file) { + var name = uploadFileName || file.name; + formdata.append(name, file); + }); + + // ------------------------------ 上传图片 ------------------------------ + if (uploadImgServer && typeof uploadImgServer === 'string') { + // 添加参数 + var uploadImgServerArr = uploadImgServer.split('#'); + uploadImgServer = uploadImgServerArr[0]; + var uploadImgServerHash = uploadImgServerArr[1] || ''; + objForEach(uploadImgParams, function (key, val) { + // 因使用者反应,自定义参数不能默认 encode ,由 v3.1.1 版本开始注释掉 + // val = encodeURIComponent(val) + + // 第一,将参数拼接到 url 中 + if (uploadImgParamsWithUrl) { + if (uploadImgServer.indexOf('?') > 0) { + uploadImgServer += '&'; + } else { + uploadImgServer += '?'; + } + uploadImgServer = uploadImgServer + key + '=' + val; + } + + // 第二,将参数添加到 formdata 中 + formdata.append(key, val); + }); + if (uploadImgServerHash) { + uploadImgServer += '#' + uploadImgServerHash; + } + + // 定义 xhr + var xhr = new XMLHttpRequest(); + xhr.open('POST', uploadImgServer); + + // 设置超时 + xhr.timeout = timeout; + xhr.ontimeout = function () { + // hook - timeout + if (hooks.timeout && typeof hooks.timeout === 'function') { + hooks.timeout(xhr, editor); + } + + _this3._alert('上传图片超时'); + }; + + // 监控 progress + if (xhr.upload) { + xhr.upload.onprogress = function (e) { + var percent = void 0; + // 进度条 + var progressBar = new Progress(editor); + if (e.lengthComputable) { + percent = e.loaded / e.total; + progressBar.show(percent); + } + }; + } + + // 返回数据 + xhr.onreadystatechange = function () { + var result = void 0; + if (xhr.readyState === 4) { + if (xhr.status < 200 || xhr.status >= 300) { + // hook - error + if (hooks.error && typeof hooks.error === 'function') { + hooks.error(xhr, editor); + } + + // xhr 返回状态错误 + _this3._alert('上传图片发生错误', '\u4E0A\u4F20\u56FE\u7247\u53D1\u751F\u9519\u8BEF\uFF0C\u670D\u52A1\u5668\u8FD4\u56DE\u72B6\u6001\u662F ' + xhr.status); + return; + } + + result = xhr.responseText; + if ((typeof result === 'undefined' ? 'undefined' : _typeof(result)) !== 'object') { + try { + result = JSON.parse(result); + } catch (ex) { + // hook - fail + if (hooks.fail && typeof hooks.fail === 'function') { + hooks.fail(xhr, editor, result); + } + + _this3._alert('上传图片失败', '上传图片返回结果错误,返回结果是: ' + result); + return; + } + } + if (!hooks.customInsert && result.errno != '0') { + // hook - fail + if (hooks.fail && typeof hooks.fail === 'function') { + hooks.fail(xhr, editor, result); + } + + // 数据错误 + _this3._alert('上传图片失败', '上传图片返回结果错误,返回结果 errno=' + result.errno); + } else { + if (hooks.customInsert && typeof hooks.customInsert === 'function') { + // 使用者自定义插入方法 + hooks.customInsert(_this3.insertLinkImg.bind(_this3), result, editor); + } else { + // 将图片插入编辑器 + var data = result.data || []; + data.forEach(function (link) { + _this3.insertLinkImg(link); + }); + } + + // hook - success + if (hooks.success && typeof hooks.success === 'function') { + hooks.success(xhr, editor, result); + } + } + } + }; + + // hook - before + if (hooks.before && typeof hooks.before === 'function') { + var beforeResult = hooks.before(xhr, editor, resultFiles); + if (beforeResult && (typeof beforeResult === 'undefined' ? 'undefined' : _typeof(beforeResult)) === 'object') { + if (beforeResult.prevent) { + // 如果返回的结果是 {prevent: true, msg: 'xxxx'} 则表示用户放弃上传 + this._alert(beforeResult.msg); + return; + } + } + } + + // 自定义 headers + objForEach(uploadImgHeaders, function (key, val) { + xhr.setRequestHeader(key, val); + }); + + // 跨域传 cookie + xhr.withCredentials = withCredentials; + + // 发送请求 + xhr.send(formdata); + + // 注意,要 return 。不去操作接下来的 base64 显示方式 + return; + } + + // ------------------------------ 显示 base64 格式 ------------------------------ + if (uploadImgShowBase64) { + arrForEach(files, function (file) { + var _this = _this3; + var reader = new FileReader(); + reader.readAsDataURL(file); + reader.onload = function () { + _this.insertLinkImg(this.result); + }; + }); + } + } +}; + +/* + 编辑器构造函数 +*/ + +// id,累加 +var editorId = 1; + +// 构造函数 +function Editor(toolbarSelector, textSelector) { + if (toolbarSelector == null) { + // 没有传入任何参数,报错 + throw new Error('错误:初始化编辑器时候未传入任何参数,请查阅文档'); + } + // id,用以区分单个页面不同的编辑器对象 + this.id = 'wangEditor-' + editorId++; + + this.toolbarSelector = toolbarSelector; + this.textSelector = textSelector; + + // 自定义配置 + this.customConfig = {}; +} + +// 修改原型 +Editor.prototype = { + constructor: Editor, + + // 初始化配置 + _initConfig: function _initConfig() { + // _config 是默认配置,this.customConfig 是用户自定义配置,将它们 merge 之后再赋值 + var target = {}; + this.config = Object.assign(target, config, this.customConfig); + + // 将语言配置,生成正则表达式 + var langConfig = this.config.lang || {}; + var langArgs = []; + objForEach(langConfig, function (key, val) { + // key 即需要生成正则表达式的规则,如“插入链接” + // val 即需要被替换成的语言,如“insert link” + langArgs.push({ + reg: new RegExp(key, 'img'), + val: val + + }); + }); + this.config.langArgs = langArgs; + }, + + // 初始化 DOM + _initDom: function _initDom() { + var _this = this; + + var toolbarSelector = this.toolbarSelector; + var $toolbarSelector = $(toolbarSelector); + var textSelector = this.textSelector; + + var config$$1 = this.config; + var zIndex = config$$1.zIndex; + + // 定义变量 + var $toolbarElem = void 0, + $textContainerElem = void 0, + $textElem = void 0, + $children = void 0; + + if (textSelector == null) { + // 只传入一个参数,即是容器的选择器或元素,toolbar 和 text 的元素自行创建 + $toolbarElem = $('
        '); + $textContainerElem = $('
        '); + + // 将编辑器区域原有的内容,暂存起来 + $children = $toolbarSelector.children(); + + // 添加到 DOM 结构中 + $toolbarSelector.append($toolbarElem).append($textContainerElem); + + // 自行创建的,需要配置默认的样式 + $toolbarElem.css('background-color', '#f1f1f1').css('border', '1px solid #ccc'); + $textContainerElem.css('border', '1px solid #ccc').css('border-top', 'none').css('height', '300px'); + } else { + // toolbar 和 text 的选择器都有值,记录属性 + $toolbarElem = $toolbarSelector; + $textContainerElem = $(textSelector); + // 将编辑器区域原有的内容,暂存起来 + $children = $textContainerElem.children(); + } + + // 编辑区域 + $textElem = $('
        '); + $textElem.attr('contenteditable', 'true').css('width', '100%').css('height', '100%'); + + // 初始化编辑区域内容 + if ($children && $children.length) { + $textElem.append($children); + } else { + $textElem.append($('


        ')); + } + + // 编辑区域加入DOM + $textContainerElem.append($textElem); + + // 设置通用的 class + $toolbarElem.addClass('w-e-toolbar'); + $textContainerElem.addClass('w-e-text-container'); + $textContainerElem.css('z-index', zIndex); + $textElem.addClass('w-e-text'); + + // 添加 ID + var toolbarElemId = getRandom('toolbar-elem'); + $toolbarElem.attr('id', toolbarElemId); + var textElemId = getRandom('text-elem'); + $textElem.attr('id', textElemId); + + // 记录属性 + this.$toolbarElem = $toolbarElem; + this.$textContainerElem = $textContainerElem; + this.$textElem = $textElem; + this.toolbarElemId = toolbarElemId; + this.textElemId = textElemId; + + // 记录输入法的开始和结束 + var compositionEnd = true; + $textContainerElem.on('compositionstart', function () { + // 输入法开始输入 + compositionEnd = false; + }); + $textContainerElem.on('compositionend', function () { + // 输入法结束输入 + compositionEnd = true; + }); + + // 绑定 onchange + $textContainerElem.on('click keyup', function () { + // 输入法结束才出发 onchange + compositionEnd && _this.change && _this.change(); + }); + $toolbarElem.on('click', function () { + this.change && this.change(); + }); + + //绑定 onfocus 与 onblur 事件 + if (config$$1.onfocus || config$$1.onblur) { + // 当前编辑器是否是焦点状态 + this.isFocus = false; + + $(document).on('click', function (e) { + //判断当前点击元素是否在编辑器内 + var isChild = $textElem.isContain($(e.target)); + + //判断当前点击元素是否为工具栏 + var isToolbar = $toolbarElem.isContain($(e.target)); + var isMenu = $toolbarElem[0] == e.target ? true : false; + + if (!isChild) { + //若为选择工具栏中的功能,则不视为成blur操作 + if (isToolbar && !isMenu) { + return; + } + + if (_this.isFocus) { + _this.onblur && _this.onblur(); + } + _this.isFocus = false; + } else { + if (!_this.isFocus) { + _this.onfocus && _this.onfocus(); + } + _this.isFocus = true; + } + }); + } + }, + + // 封装 command + _initCommand: function _initCommand() { + this.cmd = new Command(this); + }, + + // 封装 selection range API + _initSelectionAPI: function _initSelectionAPI() { + this.selection = new API(this); + }, + + // 添加图片上传 + _initUploadImg: function _initUploadImg() { + this.uploadImg = new UploadImg(this); + }, + + // 初始化菜单 + _initMenus: function _initMenus() { + this.menus = new Menus(this); + this.menus.init(); + }, + + // 添加 text 区域 + _initText: function _initText() { + this.txt = new Text(this); + this.txt.init(); + }, + + // 初始化选区,将光标定位到内容尾部 + initSelection: function initSelection(newLine) { + var $textElem = this.$textElem; + var $children = $textElem.children(); + if (!$children.length) { + // 如果编辑器区域无内容,添加一个空行,重新设置选区 + $textElem.append($('


        ')); + this.initSelection(); + return; + } + + var $last = $children.last(); + + if (newLine) { + // 新增一个空行 + var html = $last.html().toLowerCase(); + var nodeName = $last.getNodeName(); + if (html !== '
        ' && html !== '' || nodeName !== 'P') { + // 最后一个元素不是


        ,添加一个空行,重新设置选区 + $textElem.append($('


        ')); + this.initSelection(); + return; + } + } + + this.selection.createRangeByElem($last, false, true); + this.selection.restoreSelection(); + }, + + // 绑定事件 + _bindEvent: function _bindEvent() { + // -------- 绑定 onchange 事件 -------- + var onChangeTimeoutId = 0; + var beforeChangeHtml = this.txt.html(); + var config$$1 = this.config; + + // onchange 触发延迟时间 + var onchangeTimeout = config$$1.onchangeTimeout; + onchangeTimeout = parseInt(onchangeTimeout, 10); + if (!onchangeTimeout || onchangeTimeout <= 0) { + onchangeTimeout = 200; + } + + var onchange = config$$1.onchange; + if (onchange && typeof onchange === 'function') { + // 触发 change 的有三个场景: + // 1. $textContainerElem.on('click keyup') + // 2. $toolbarElem.on('click') + // 3. editor.cmd.do() + this.change = function () { + // 判断是否有变化 + var currentHtml = this.txt.html(); + + if (currentHtml.length === beforeChangeHtml.length) { + // 需要比较每一个字符 + if (currentHtml === beforeChangeHtml) { + return; + } + } + + // 执行,使用节流 + if (onChangeTimeoutId) { + clearTimeout(onChangeTimeoutId); + } + onChangeTimeoutId = setTimeout(function () { + // 触发配置的 onchange 函数 + onchange(currentHtml); + beforeChangeHtml = currentHtml; + }, onchangeTimeout); + }; + } + + // -------- 绑定 onblur 事件 -------- + var onblur = config$$1.onblur; + if (onblur && typeof onblur === 'function') { + this.onblur = function () { + var currentHtml = this.txt.html(); + onblur(currentHtml); + }; + } + + // -------- 绑定 onfocus 事件 -------- + var onfocus = config$$1.onfocus; + if (onfocus && typeof onfocus === 'function') { + this.onfocus = function () { + onfocus(); + }; + } + }, + + // 创建编辑器 + create: function create() { + // 初始化配置信息 + this._initConfig(); + + // 初始化 DOM + this._initDom(); + + // 封装 command API + this._initCommand(); + + // 封装 selection range API + this._initSelectionAPI(); + + // 添加 text + this._initText(); + + // 初始化菜单 + this._initMenus(); + + // 添加 图片上传 + this._initUploadImg(); + + // 初始化选区,将光标定位到内容尾部 + this.initSelection(true); + + // 绑定事件 + this._bindEvent(); + }, + + // 解绑所有事件(暂时不对外开放) + _offAllEvent: function _offAllEvent() { + $.offAll(); + } +}; + +// 检验是否浏览器环境 +try { + document; +} catch (ex) { + throw new Error('请在浏览器环境下运行'); +} + +// polyfill +polyfill(); + +// 这里的 `inlinecss` 将被替换成 css 代码的内容,详情可去 ./gulpfile.js 中搜索 `inlinecss` 关键字 +var inlinecss = '.w-e-toolbar,.w-e-text-container,.w-e-menu-panel { padding: 0; margin: 0; box-sizing: border-box;}.w-e-toolbar *,.w-e-text-container *,.w-e-menu-panel * { padding: 0; margin: 0; box-sizing: border-box;}.w-e-clear-fix:after { content: ""; display: table; clear: both;}.w-e-toolbar .w-e-droplist { position: absolute; left: 0; top: 0; background-color: #fff; border: 1px solid #f1f1f1; border-right-color: #ccc; border-bottom-color: #ccc;}.w-e-toolbar .w-e-droplist .w-e-dp-title { text-align: center; color: #999; line-height: 2; border-bottom: 1px solid #f1f1f1; font-size: 13px;}.w-e-toolbar .w-e-droplist ul.w-e-list { list-style: none; line-height: 1;}.w-e-toolbar .w-e-droplist ul.w-e-list li.w-e-item { color: #333; padding: 5px 0;}.w-e-toolbar .w-e-droplist ul.w-e-list li.w-e-item:hover { background-color: #f1f1f1;}.w-e-toolbar .w-e-droplist ul.w-e-block { list-style: none; text-align: left; padding: 5px;}.w-e-toolbar .w-e-droplist ul.w-e-block li.w-e-item { display: inline-block; *display: inline; *zoom: 1; padding: 3px 5px;}.w-e-toolbar .w-e-droplist ul.w-e-block li.w-e-item:hover { background-color: #f1f1f1;}@font-face { font-family: \'w-e-icon\'; src: url(data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAABhQAAsAAAAAGAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAABCAAAAGAAAABgDxIPBGNtYXAAAAFoAAABBAAAAQQrSf4BZ2FzcAAAAmwAAAAIAAAACAAAABBnbHlmAAACdAAAEvAAABLwfpUWUWhlYWQAABVkAAAANgAAADYQp00kaGhlYQAAFZwAAAAkAAAAJAfEA+FobXR4AAAVwAAAAIQAAACEeAcD7GxvY2EAABZEAAAARAAAAERBSEX+bWF4cAAAFogAAAAgAAAAIAAsALZuYW1lAAAWqAAAAYYAAAGGmUoJ+3Bvc3QAABgwAAAAIAAAACAAAwAAAAMD3gGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAA8fwDwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEAOgAAAA2ACAABAAWAAEAIOkG6Q3pEulH6Wbpd+m56bvpxunL6d/qDepc6l/qZepo6nHqefAN8BTxIPHc8fz//f//AAAAAAAg6QbpDekS6UfpZel36bnpu+nG6cvp3+oN6lzqX+pi6mjqcep38A3wFPEg8dzx/P/9//8AAf/jFv4W+Bb0FsAWoxaTFlIWURZHFkMWMBYDFbUVsxWxFa8VpxWiEA8QCQ7+DkMOJAADAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAB//8ADwABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAACAAD/wAQAA8AABAATAAABNwEnAQMuAScTNwEjAQMlATUBBwGAgAHAQP5Anxc7MmOAAYDA/oDAAoABgP6ATgFAQAHAQP5A/p0yOxcBEU4BgP6A/YDAAYDA/oCAAAQAAAAABAADgAAQACEALQA0AAABOAExETgBMSE4ATEROAExITUhIgYVERQWMyEyNjURNCYjBxQGIyImNTQ2MzIWEyE1EwEzNwPA/IADgPyAGiYmGgOAGiYmGoA4KCg4OCgoOED9AOABAEDgA0D9AAMAQCYa/QAaJiYaAwAaJuAoODgoKDg4/biAAYD+wMAAAAIAAABABAADQAA4ADwAAAEmJy4BJyYjIgcOAQcGBwYHDgEHBhUUFx4BFxYXFhceARcWMzI3PgE3Njc2Nz4BNzY1NCcuAScmJwERDQED1TY4OXY8PT8/PTx2OTg2CwcICwMDAwMLCAcLNjg5djw9Pz89PHY5ODYLBwgLAwMDAwsIBwv9qwFA/sADIAgGBggCAgICCAYGCCkqKlktLi8vLi1ZKiopCAYGCAICAgIIBgYIKSoqWS0uLy8uLVkqKin94AGAwMAAAAAAAgDA/8ADQAPAABsAJwAAASIHDgEHBhUUFx4BFxYxMDc+ATc2NTQnLgEnJgMiJjU0NjMyFhUUBgIAQjs6VxkZMjJ4MjIyMngyMhkZVzo7QlBwcFBQcHADwBkZVzo7Qnh9fcxBQUFBzH19eEI7OlcZGf4AcFBQcHBQUHAAAAEAAAAABAADgAArAAABIgcOAQcGBycRISc+ATMyFx4BFxYVFAcOAQcGBxc2Nz4BNzY1NCcuAScmIwIANTIyXCkpI5YBgJA1i1BQRUZpHh4JCSIYGB5VKCAgLQwMKCiLXl1qA4AKCycbHCOW/oCQNDweHmlGRVArKClJICEaYCMrK2I2NjlqXV6LKCgAAQAAAAAEAAOAACoAABMUFx4BFxYXNyYnLgEnJjU0Nz4BNzYzMhYXByERByYnLgEnJiMiBw4BBwYADAwtICAoVR4YGCIJCR4eaUZFUFCLNZABgJYjKSlcMjI1al1eiygoAYA5NjZiKysjYBohIEkpKCtQRUZpHh48NJABgJYjHBsnCwooKIteXQAAAAACAAAAQAQBAwAAJgBNAAATMhceARcWFRQHDgEHBiMiJy4BJyY1JzQ3PgE3NjMVIgYHDgEHPgEhMhceARcWFRQHDgEHBiMiJy4BJyY1JzQ3PgE3NjMVIgYHDgEHPgHhLikpPRESEhE9KSkuLikpPRESASMjelJRXUB1LQkQBwgSAkkuKSk9ERISET0pKS4uKSk9ERIBIyN6UlFdQHUtCRAHCBICABIRPSkpLi4pKT0REhIRPSkpLiBdUVJ6IyOAMC4IEwoCARIRPSkpLi4pKT0REhIRPSkpLiBdUVJ6IyOAMC4IEwoCAQAABgBA/8AEAAPAAAMABwALABEAHQApAAAlIRUhESEVIREhFSEnESM1IzUTFTMVIzU3NSM1MxUVESM1MzUjNTM1IzUBgAKA/YACgP2AAoD9gMBAQECAwICAwMCAgICAgIACAIACAIDA/wDAQP3yMkCSPDJAku7+wEBAQEBAAAYAAP/ABAADwAADAAcACwAXACMALwAAASEVIREhFSERIRUhATQ2MzIWFRQGIyImETQ2MzIWFRQGIyImETQ2MzIWFRQGIyImAYACgP2AAoD9gAKA/YD+gEs1NUtLNTVLSzU1S0s1NUtLNTVLSzU1SwOAgP8AgP8AgANANUtLNTVLS/61NUtLNTVLS/61NUtLNTVLSwADAAAAAAQAA6AAAwANABQAADchFSElFSE1EyEVITUhJQkBIxEjEQAEAPwABAD8AIABAAEAAQD9YAEgASDggEBAwEBAAQCAgMABIP7g/wABAAAAAAACAB7/zAPiA7QAMwBkAAABIiYnJicmNDc2PwE+ATMyFhcWFxYUBwYPAQYiJyY0PwE2NCcuASMiBg8BBhQXFhQHDgEjAyImJyYnJjQ3Nj8BNjIXFhQPAQYUFx4BMzI2PwE2NCcmNDc2MhcWFxYUBwYPAQ4BIwG4ChMIIxISEhIjwCNZMTFZIyMSEhISI1gPLA8PD1gpKRQzHBwzFMApKQ8PCBMKuDFZIyMSEhISI1gPLA8PD1gpKRQzHBwzFMApKQ8PDysQIxISEhIjwCNZMQFECAckLS1eLS0kwCIlJSIkLS1eLS0kVxAQDysPWCl0KRQVFRTAKXQpDysQBwj+iCUiJC0tXi0tJFcQEA8rD1gpdCkUFRUUwCl0KQ8rEA8PJC0tXi0tJMAiJQAAAAAFAAD/wAQAA8AAGwA3AFMAXwBrAAAFMjc+ATc2NTQnLgEnJiMiBw4BBwYVFBceARcWEzIXHgEXFhUUBw4BBwYjIicuAScmNTQ3PgE3NhMyNz4BNzY3BgcOAQcGIyInLgEnJicWFx4BFxYnNDYzMhYVFAYjIiYlNDYzMhYVFAYjIiYCAGpdXosoKCgoi15dampdXosoKCgoi15dalZMTHEgISEgcUxMVlZMTHEgISEgcUxMVisrKlEmJiMFHBtWODc/Pzc4VhscBSMmJlEqK9UlGxslJRsbJQGAJRsbJSUbGyVAKCiLXl1qal1eiygoKCiLXl1qal1eiygoA6AhIHFMTFZWTExxICEhIHFMTFZWTExxICH+CQYGFRAQFEM6OlYYGRkYVjo6QxQQEBUGBvcoODgoKDg4KCg4OCgoODgAAAMAAP/ABAADwAAbADcAQwAAASIHDgEHBhUUFx4BFxYzMjc+ATc2NTQnLgEnJgMiJy4BJyY1NDc+ATc2MzIXHgEXFhUUBw4BBwYTBycHFwcXNxc3JzcCAGpdXosoKCgoi15dampdXosoKCgoi15dalZMTHEgISEgcUxMVlZMTHEgISEgcUxMSqCgYKCgYKCgYKCgA8AoKIteXWpqXV6LKCgoKIteXWpqXV6LKCj8YCEgcUxMVlZMTHEgISEgcUxMVlZMTHEgIQKgoKBgoKBgoKBgoKAAAQBl/8ADmwPAACkAAAEiJiMiBw4BBwYVFBYzLgE1NDY3MAcGAgcGBxUhEzM3IzceATMyNjcOAQMgRGhGcVNUbRobSUgGDWVKEBBLPDxZAT1sxizXNC1VJi5QGB09A7AQHh1hPj9BTTsLJjeZbwN9fv7Fj5AjGQIAgPYJDzdrCQcAAAAAAgAAAAAEAAOAAAkAFwAAJTMHJzMRIzcXIyURJyMRMxUhNTMRIwcRA4CAoKCAgKCggP8AQMCA/oCAwEDAwMACAMDAwP8AgP1AQEACwIABAAADAMAAAANAA4AAFgAfACgAAAE+ATU0Jy4BJyYjIREhMjc+ATc2NTQmATMyFhUUBisBEyMRMzIWFRQGAsQcIBQURi4vNf7AAYA1Ly5GFBRE/oRlKjw8KWafn58sPj4B2yJULzUvLkYUFPyAFBRGLi81RnQBRks1NUv+gAEASzU1SwAAAAACAMAAAANAA4AAHwAjAAABMxEUBw4BBwYjIicuAScmNREzERQWFx4BMzI2Nz4BNQEhFSECwIAZGVc6O0JCOzpXGRmAGxgcSSgoSRwYG/4AAoD9gAOA/mA8NDVOFhcXFk41NDwBoP5gHjgXGBsbGBc4Hv6ggAAAAAABAIAAAAOAA4AACwAAARUjATMVITUzASM1A4CA/sCA/kCAAUCAA4BA/QBAQAMAQAABAAAAAAQAA4AAPQAAARUjHgEVFAYHDgEjIiYnLgE1MxQWMzI2NTQmIyE1IS4BJy4BNTQ2Nz4BMzIWFx4BFSM0JiMiBhUUFjMyFhcEAOsVFjUwLHE+PnEsMDWAck5OcnJO/gABLAIEATA1NTAscT4+cSwwNYByTk5yck47bisBwEAdQSI1YiQhJCQhJGI1NExMNDRMQAEDASRiNTViJCEkJCEkYjU0TEw0NEwhHwAAAAcAAP/ABAADwAADAAcACwAPABMAGwAjAAATMxUjNzMVIyUzFSM3MxUjJTMVIwMTIRMzEyETAQMhAyMDIQMAgIDAwMABAICAwMDAAQCAgBAQ/QAQIBACgBD9QBADABAgEP2AEAHAQEBAQEBAQEBAAkD+QAHA/oABgPwAAYD+gAFA/sAAAAoAAAAABAADgAADAAcACwAPABMAFwAbAB8AIwAnAAATESERATUhFR0BITUBFSE1IxUhNREhFSElIRUhETUhFQEhFSEhNSEVAAQA/YABAP8AAQD/AED/AAEA/wACgAEA/wABAPyAAQD/AAKAAQADgPyAA4D9wMDAQMDAAgDAwMDA/wDAwMABAMDA/sDAwMAAAAUAAAAABAADgAADAAcACwAPABMAABMhFSEVIRUhESEVIREhFSERIRUhAAQA/AACgP2AAoD9gAQA/AAEAPwAA4CAQID/AIABQID/AIAAAAAABQAAAAAEAAOAAAMABwALAA8AEwAAEyEVIRchFSERIRUhAyEVIREhFSEABAD8AMACgP2AAoD9gMAEAPwABAD8AAOAgECA/wCAAUCA/wCAAAAFAAAAAAQAA4AAAwAHAAsADwATAAATIRUhBSEVIREhFSEBIRUhESEVIQAEAPwAAYACgP2AAoD9gP6ABAD8AAQA/AADgIBAgP8AgAFAgP8AgAAAAAABAD8APwLmAuYALAAAJRQPAQYjIi8BBwYjIi8BJjU0PwEnJjU0PwE2MzIfATc2MzIfARYVFA8BFxYVAuYQThAXFxCoqBAXFhBOEBCoqBAQThAWFxCoqBAXFxBOEBCoqBDDFhBOEBCoqBAQThAWFxCoqBAXFxBOEBCoqBAQThAXFxCoqBAXAAAABgAAAAADJQNuABQAKAA8AE0AVQCCAAABERQHBisBIicmNRE0NzY7ATIXFhUzERQHBisBIicmNRE0NzY7ATIXFhcRFAcGKwEiJyY1ETQ3NjsBMhcWExEhERQXFhcWMyEyNzY3NjUBIScmJyMGBwUVFAcGKwERFAcGIyEiJyY1ESMiJyY9ATQ3NjsBNzY3NjsBMhcWHwEzMhcWFQElBgUIJAgFBgYFCCQIBQaSBQUIJQgFBQUFCCUIBQWSBQUIJQgFBQUFCCUIBQVJ/gAEBAUEAgHbAgQEBAT+gAEAGwQGtQYEAfcGBQg3Ghsm/iUmGxs3CAUFBQUIsSgIFxYXtxcWFgkosAgFBgIS/rcIBQUFBQgBSQgFBgYFCP63CAUFBQUIAUkIBQYGBQj+twgFBQUFCAFJCAUGBgX+WwId/eMNCwoFBQUFCgsNAmZDBQICBVUkCAYF/eMwIiMhIi8CIAUGCCQIBQVgFQ8PDw8VYAUFCAACAAcASQO3Aq8AGgAuAAAJAQYjIi8BJjU0PwEnJjU0PwE2MzIXARYVFAcBFRQHBiMhIicmPQE0NzYzITIXFgFO/vYGBwgFHQYG4eEGBh0FCAcGAQoGBgJpBQUI/dsIBQUFBQgCJQgFBQGF/vYGBhwGCAcG4OEGBwcGHQUF/vUFCAcG/vslCAUFBQUIJQgFBQUFAAAAAQAjAAAD3QNuALMAACUiJyYjIgcGIyInJjU0NzY3Njc2NzY9ATQnJiMhIgcGHQEUFxYXFjMWFxYVFAcGIyInJiMiBwYjIicmNTQ3Njc2NzY3Nj0BETQ1NDU0JzQnJicmJyYnJicmIyInJjU0NzYzMhcWMzI3NjMyFxYVFAcGIwYHBgcGHQEUFxYzITI3Nj0BNCcmJyYnJjU0NzYzMhcWMzI3NjMyFxYVFAcGByIHBgcGFREUFxYXFhcyFxYVFAcGIwPBGTMyGhkyMxkNCAcJCg0MERAKEgEHFf5+FgcBFQkSEw4ODAsHBw4bNTUaGDExGA0HBwkJCwwQDwkSAQIBAgMEBAUIEhENDQoLBwcOGjU1GhgwMRgOBwcJCgwNEBAIFAEHDwGQDgcBFAoXFw8OBwcOGTMyGRkxMRkOBwcKCg0NEBEIFBQJEREODQoLBwcOAAICAgIMCw8RCQkBAQMDBQxE4AwFAwMFDNRRDQYBAgEICBIPDA0CAgICDAwOEQgJAQIDAwUNRSEB0AINDQgIDg4KCgsLBwcDBgEBCAgSDwwNAgICAg0MDxEICAECAQYMULYMBwEBBwy2UAwGAQEGBxYPDA0CAgICDQwPEQgIAQECBg1P/eZEDAYCAgEJCBEPDA0AAAIAAP+3A/8DtwATADkAAAEyFxYVFAcCBwYjIicmNTQ3ATYzARYXFh8BFgcGIyInJicmJyY1FhcWFxYXFjMyNzY3Njc2NzY3NjcDmygeHhq+TDdFSDQ0NQFtISn9+BcmJy8BAkxMe0c2NiEhEBEEExQQEBIRCRcIDxITFRUdHR4eKQO3GxooJDP+mUY0NTRJSTABSx/9sSsfHw0oek1MGhsuLzo6RAMPDgsLCgoWJRsaEREKCwQEAgABAAAAAAAA9evv618PPPUACwQAAAAAANbEBFgAAAAA1sQEWAAA/7cEAQPAAAAACAACAAAAAAAAAAEAAAPA/8AAAAQAAAD//wQBAAEAAAAAAAAAAAAAAAAAAAAhBAAAAAAAAAAAAAAAAgAAAAQAAAAEAAAABAAAAAQAAMAEAAAABAAAAAQAAAAEAABABAAAAAQAAAAEAAAeBAAAAAQAAAAEAABlBAAAAAQAAMAEAADABAAAgAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAMlAD8DJQAAA74ABwQAACMD/wAAAAAAAAAKABQAHgBMAJQA+AE2AXwBwgI2AnQCvgLoA34EHgSIBMoE8gU0BXAFiAXgBiIGagaSBroG5AcoB+AIKgkcCXgAAQAAACEAtAAKAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAA4ArgABAAAAAAABAAcAAAABAAAAAAACAAcAYAABAAAAAAADAAcANgABAAAAAAAEAAcAdQABAAAAAAAFAAsAFQABAAAAAAAGAAcASwABAAAAAAAKABoAigADAAEECQABAA4ABwADAAEECQACAA4AZwADAAEECQADAA4APQADAAEECQAEAA4AfAADAAEECQAFABYAIAADAAEECQAGAA4AUgADAAEECQAKADQApGljb21vb24AaQBjAG8AbQBvAG8AblZlcnNpb24gMS4wAFYAZQByAHMAaQBvAG4AIAAxAC4AMGljb21vb24AaQBjAG8AbQBvAG8Abmljb21vb24AaQBjAG8AbQBvAG8AblJlZ3VsYXIAUgBlAGcAdQBsAGEAcmljb21vb24AaQBjAG8AbQBvAG8AbkZvbnQgZ2VuZXJhdGVkIGJ5IEljb01vb24uAEYAbwBuAHQAIABnAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAEkAYwBvAE0AbwBvAG4ALgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=) format(\'truetype\'); font-weight: normal; font-style: normal;}[class^="w-e-icon-"],[class*=" w-e-icon-"] { /* use !important to prevent issues with browser extensions that change fonts */ font-family: \'w-e-icon\' !important; speak: none; font-style: normal; font-weight: normal; font-variant: normal; text-transform: none; line-height: 1; /* Better Font Rendering =========== */ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;}.w-e-icon-close:before { content: "\\f00d";}.w-e-icon-upload2:before { content: "\\e9c6";}.w-e-icon-trash-o:before { content: "\\f014";}.w-e-icon-header:before { content: "\\f1dc";}.w-e-icon-pencil2:before { content: "\\e906";}.w-e-icon-paint-brush:before { content: "\\f1fc";}.w-e-icon-image:before { content: "\\e90d";}.w-e-icon-play:before { content: "\\e912";}.w-e-icon-location:before { content: "\\e947";}.w-e-icon-undo:before { content: "\\e965";}.w-e-icon-redo:before { content: "\\e966";}.w-e-icon-quotes-left:before { content: "\\e977";}.w-e-icon-list-numbered:before { content: "\\e9b9";}.w-e-icon-list2:before { content: "\\e9bb";}.w-e-icon-link:before { content: "\\e9cb";}.w-e-icon-happy:before { content: "\\e9df";}.w-e-icon-bold:before { content: "\\ea62";}.w-e-icon-underline:before { content: "\\ea63";}.w-e-icon-italic:before { content: "\\ea64";}.w-e-icon-strikethrough:before { content: "\\ea65";}.w-e-icon-table2:before { content: "\\ea71";}.w-e-icon-paragraph-left:before { content: "\\ea77";}.w-e-icon-paragraph-center:before { content: "\\ea78";}.w-e-icon-paragraph-right:before { content: "\\ea79";}.w-e-icon-terminal:before { content: "\\f120";}.w-e-icon-page-break:before { content: "\\ea68";}.w-e-icon-cancel-circle:before { content: "\\ea0d";}.w-e-icon-font:before { content: "\\ea5c";}.w-e-icon-text-heigh:before { content: "\\ea5f";}.w-e-toolbar { display: -webkit-box; display: -ms-flexbox; display: flex; padding: 0 5px; /* flex-wrap: wrap; */ /* 单个菜单 */}.w-e-toolbar .w-e-menu { position: relative; text-align: center; padding: 5px 10px; cursor: pointer;}.w-e-toolbar .w-e-menu i { color: #999;}.w-e-toolbar .w-e-menu:hover i { color: #333;}.w-e-toolbar .w-e-active i { color: #1e88e5;}.w-e-toolbar .w-e-active:hover i { color: #1e88e5;}.w-e-text-container .w-e-panel-container { position: absolute; top: 0; left: 50%; border: 1px solid #ccc; border-top: 0; box-shadow: 1px 1px 2px #ccc; color: #333; background-color: #fff; /* 为 emotion panel 定制的样式 */ /* 上传图片的 panel 定制样式 */}.w-e-text-container .w-e-panel-container .w-e-panel-close { position: absolute; right: 0; top: 0; padding: 5px; margin: 2px 5px 0 0; cursor: pointer; color: #999;}.w-e-text-container .w-e-panel-container .w-e-panel-close:hover { color: #333;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-title { list-style: none; display: -webkit-box; display: -ms-flexbox; display: flex; font-size: 14px; margin: 2px 10px 0 10px; border-bottom: 1px solid #f1f1f1;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-title .w-e-item { padding: 3px 5px; color: #999; cursor: pointer; margin: 0 3px; position: relative; top: 1px;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-title .w-e-active { color: #333; border-bottom: 1px solid #333; cursor: default; font-weight: 700;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content { padding: 10px 15px 10px 15px; font-size: 16px; /* 输入框的样式 */ /* 按钮的样式 */}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input:focus,.w-e-text-container .w-e-panel-container .w-e-panel-tab-content textarea:focus,.w-e-text-container .w-e-panel-container .w-e-panel-tab-content button:focus { outline: none;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content textarea { width: 100%; border: 1px solid #ccc; padding: 5px;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content textarea:focus { border-color: #1e88e5;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input[type=text] { border: none; border-bottom: 1px solid #ccc; font-size: 14px; height: 20px; color: #333; text-align: left;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input[type=text].small { width: 30px; text-align: center;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input[type=text].block { display: block; width: 100%; margin: 10px 0;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input[type=text]:focus { border-bottom: 2px solid #1e88e5;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button { font-size: 14px; color: #1e88e5; border: none; padding: 5px 10px; background-color: #fff; cursor: pointer; border-radius: 3px;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button.left { float: left; margin-right: 10px;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button.right { float: right; margin-left: 10px;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button.gray { color: #999;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button.red { color: #c24f4a;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button:hover { background-color: #f1f1f1;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container:after { content: ""; display: table; clear: both;}.w-e-text-container .w-e-panel-container .w-e-emoticon-container .w-e-item { cursor: pointer; font-size: 18px; padding: 0 3px; display: inline-block; *display: inline; *zoom: 1;}.w-e-text-container .w-e-panel-container .w-e-up-img-container { text-align: center;}.w-e-text-container .w-e-panel-container .w-e-up-img-container .w-e-up-btn { display: inline-block; *display: inline; *zoom: 1; color: #999; cursor: pointer; font-size: 60px; line-height: 1;}.w-e-text-container .w-e-panel-container .w-e-up-img-container .w-e-up-btn:hover { color: #333;}.w-e-text-container { position: relative;}.w-e-text-container .w-e-progress { position: absolute; background-color: #1e88e5; bottom: 0; left: 0; height: 1px;}.w-e-text { padding: 0 10px; overflow-y: scroll;}.w-e-text p,.w-e-text h1,.w-e-text h2,.w-e-text h3,.w-e-text h4,.w-e-text h5,.w-e-text table,.w-e-text pre { margin: 10px 0; line-height: 1.5;}.w-e-text ul,.w-e-text ol { margin: 10px 0 10px 20px;}.w-e-text blockquote { display: block; border-left: 8px solid #d0e5f2; padding: 5px 10px; margin: 10px 0; line-height: 1.4; font-size: 100%; background-color: #f1f1f1;}.w-e-text code { display: inline-block; *display: inline; *zoom: 1; background-color: #f1f1f1; border-radius: 3px; padding: 3px 5px; margin: 0 3px;}.w-e-text pre code { display: block;}.w-e-text table { border-top: 1px solid #ccc; border-left: 1px solid #ccc;}.w-e-text table td,.w-e-text table th { border-bottom: 1px solid #ccc; border-right: 1px solid #ccc; padding: 3px 5px;}.w-e-text table th { border-bottom: 2px solid #ccc; text-align: center;}.w-e-text:focus { outline: none;}.w-e-text img { cursor: pointer;}.w-e-text img:hover { box-shadow: 0 0 5px #333;}'; + +// 将 css 代码添加到 \ No newline at end of file diff --git a/admin-core/src/main/resources/templates/login.html b/admin-core/src/main/resources/templates/login.html index 2f4cc1270725b5cbc6bbfc26714e23db5f97d269..bcbfc52e93560bff9be47b77a48a498a15c22ba6 100644 --- a/admin-core/src/main/resources/templates/login.html +++ b/admin-core/src/main/resources/templates/login.html @@ -1,47 +1,133 @@ - - - - - Spring Boot开发平台 - - - - - - - - -
        - 用户登录 -
        - -
        -
        - -
        - -
        -
        -
        - -
        - -
        -
        -
        -
        - -
        -
        -
        - + + + + + 郑大学科管理平台 + + + + +
        +
        +
        + 学科管理系统 +
        +
        +
        +
        + +
        + +
        + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 2ee021aa3bbfe976e955b5a666f8e3070b1201a1..a5f7f86f5f9fdc6c0fd7e953708dfced059cf01c 100644 --- a/pom.xml +++ b/pom.xml @@ -14,6 +14,7 @@ admin-core admin-console + newcapec-discipline org.springframework.boot @@ -31,10 +32,9 @@ org.springframework.boot spring-boot-starter-test - - + ${project.artifactId}-${project.version} org.apache.maven.plugins @@ -42,6 +42,9 @@ 1.8 1.8 + + -parameters + true