增加权限验证

This commit is contained in:
暮光:城中城
2018-12-02 21:12:04 +08:00
parent f3d2b4eeab
commit 67c584761d
70 changed files with 21137 additions and 366 deletions

View File

@@ -8,7 +8,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
* Mapper 接口
* </p>
*
* @author hongli.zhang
* @author 暮光:城中城
* @since 2018-11-27
*/
public interface ZyplayerStorageMapper extends BaseMapper<ZyplayerStorage> {

View File

@@ -8,7 +8,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
* Mapper 接口
* </p>
*
* @author hongli.zhang
* @author 暮光:城中城
* @since 2018-11-27
*/
public interface ZyplayerStorageMapper extends BaseMapper<ZyplayerStorage> {

View File

@@ -10,7 +10,7 @@ import java.io.Serializable;
*
* </p>
*
* @author hongli.zhang
* @author 暮光:城中城
* @since 2018-11-27
*/
public class ZyplayerStorage implements Serializable {

View File

@@ -10,7 +10,7 @@ import java.io.Serializable;
*
* </p>
*
* @author hongli.zhang
* @author 暮光:城中城
* @since 2018-11-27
*/
public class ZyplayerStorage implements Serializable {

View File

@@ -8,7 +8,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
* 服务类
* </p>
*
* @author hongli.zhang
* @author 暮光:城中城
* @since 2018-11-27
*/
public interface ZyplayerStorageService extends IService<ZyplayerStorage> {

View File

@@ -8,7 +8,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
* 服务类
* </p>
*
* @author hongli.zhang
* @author 暮光:城中城
* @since 2018-11-27
*/
public interface ZyplayerStorageService extends IService<ZyplayerStorage> {

View File

@@ -11,7 +11,7 @@ import org.springframework.stereotype.Service;
* 服务实现类
* </p>
*
* @author hongli.zhang
* @author 暮光:城中城
* @since 2018-11-27
*/
@Service

View File

@@ -11,7 +11,7 @@ import org.springframework.stereotype.Service;
* 服务实现类
* </p>
*
* @author hongli.zhang
* @author 暮光:城中城
* @since 2018-11-27
*/
@Service

View File

@@ -40,10 +40,19 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
@@ -72,6 +81,11 @@
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
<!-- 整合spring security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
<build>

View File

@@ -8,7 +8,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
* Mapper 接口
* </p>
*
* @author hongli.zhang
* @author 暮光:城中城
* @since 2018-11-27
*/
public interface ZyplayerStorageMapper extends BaseMapper<ZyplayerStorage> {

View File

@@ -8,7 +8,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
* Mapper 接口
* </p>
*
* @author hongli.zhang
* @author 暮光:城中城
* @since 2018-11-27
*/
public interface ZyplayerStorageMapper extends BaseMapper<ZyplayerStorage> {

View File

@@ -10,7 +10,7 @@ import java.io.Serializable;
*
* </p>
*
* @author hongli.zhang
* @author 暮光:城中城
* @since 2018-11-27
*/
public class ZyplayerStorage implements Serializable {

View File

@@ -10,7 +10,7 @@ import java.io.Serializable;
*
* </p>
*
* @author hongli.zhang
* @author 暮光:城中城
* @since 2018-11-27
*/
public class ZyplayerStorage implements Serializable {

View File

@@ -8,7 +8,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
* 服务类
* </p>
*
* @author hongli.zhang
* @author 暮光:城中城
* @since 2018-11-27
*/
public interface ZyplayerStorageService extends IService<ZyplayerStorage> {

View File

@@ -8,7 +8,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
* 服务类
* </p>
*
* @author hongli.zhang
* @author 暮光:城中城
* @since 2018-11-27
*/
public interface ZyplayerStorageService extends IService<ZyplayerStorage> {

View File

@@ -11,7 +11,7 @@ import org.springframework.stereotype.Service;
* 服务实现类
* </p>
*
* @author hongli.zhang
* @author 暮光:城中城
* @since 2018-11-27
*/
@Service

View File

@@ -11,7 +11,7 @@ import org.springframework.stereotype.Service;
* 服务实现类
* </p>
*
* @author hongli.zhang
* @author 暮光:城中城
* @since 2018-11-27
*/
@Service

View File

@@ -1,8 +1,5 @@
package com.zyplayer.doc.manage;
import java.net.InetAddress;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
@@ -12,11 +9,12 @@ import org.springframework.boot.web.servlet.support.SpringBootServletInitializer
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;
import java.net.InetAddress;
/**
* 程序启动器
*/
@SpringBootApplication
@MapperScan("com.zyplayer.doc.manage.repository")
public class Application extends SpringBootServletInitializer {
private static Logger logger = LoggerFactory.getLogger(Application.class);
@@ -25,15 +23,15 @@ public class Application extends SpringBootServletInitializer {
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext application = SpringApplication.run(Application.class, args);
Environment env = application.getEnvironment();
logger.info("\n----------------------------------------------------------\n\t" +
"\t\t地址列表\n\t"+
"文档地址http://{}:{}/document.html\n"+
"----------------------------------------------------------",
InetAddress.getLocalHost().getHostAddress(), env.getProperty("server.port")
"\t\t地址列表\n\t" +
"文档地址http://{}:{}/document.html\n" +
"----------------------------------------------------------",
InetAddress.getLocalHost().getHostAddress(), env.getProperty("server.port")
);
}
}

View File

@@ -56,5 +56,15 @@ public class MgStorageServiceImpl implements MgStorageService {
zyplayerStorageService.save(entity);
}
}
/**
* 删除一个key
*/
@Override
public void remove(String key) {
UpdateWrapper<ZyplayerStorage> queryWrapper = new UpdateWrapper<>();
queryWrapper.eq(true, "doc_key", key);
zyplayerStorageService.remove(queryWrapper);
}
}

View File

@@ -0,0 +1,141 @@
package com.zyplayer.doc.manage.framework.config;
import com.atomikos.icatch.jta.UserTransactionImp;
import com.atomikos.icatch.jta.UserTransactionManager;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.zyplayer.doc.manage.repository.support.interceptor.SqlLogInterceptor;
import org.apache.ibatis.plugin.Interceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.jta.JtaTransactionManager;
import javax.sql.DataSource;
import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;
import java.util.Properties;
/**
* mybatis plus数据库配置
*/
@Configuration
public class MybatisPlusConfig {
/**
* sql日志
**/
private static final SqlLogInterceptor SQL_LOG_INTERCEPTOR;
static {
SQL_LOG_INTERCEPTOR = new SqlLogInterceptor();
Properties properties = new Properties();
SQL_LOG_INTERCEPTOR.setProperties(properties);
}
/**
* 分布式事务配置
*/
@Configuration
static class JTATransactionManagerConfig {
@Bean(name = "userTransaction")
public UserTransaction userTransaction() throws Throwable {
UserTransactionImp userTransactionImp = new UserTransactionImp();
userTransactionImp.setTransactionTimeout(300);
return userTransactionImp;
}
@Bean(name = "atomikosTransactionManager")
public TransactionManager atomikosTransactionManager() {
UserTransactionManager userTransactionManager = new UserTransactionManager();
userTransactionManager.setForceShutdown(true);
return userTransactionManager;
}
@Bean(name = "transactionManager")
public PlatformTransactionManager transactionManager() throws Throwable {
UserTransaction userTransaction = userTransaction();
TransactionManager atomikosTransactionManager = atomikosTransactionManager();
JtaTransactionManager jtaTransactionManager = new JtaTransactionManager(userTransaction, atomikosTransactionManager);
jtaTransactionManager.setAllowCustomIsolationLevels(true);
jtaTransactionManager.setGlobalRollbackOnParticipationFailure(true);
jtaTransactionManager.setDefaultTimeout(30);
return jtaTransactionManager;
}
}
/**
* 数据库配置
*/
@Configuration
@EnableTransactionManagement
@MapperScan(value = "com.zyplayer.doc.manage.repository.manage.mapper", sqlSessionFactoryRef = "manageSqlSessionFactory")
static class ManageMybatisDbConfig {
@Value("${zyplayer.datasource.manage.driverClassName}")
private String driverClassName;
@Value("${zyplayer.datasource.manage.url}")
private String url;
@Value("${zyplayer.datasource.manage.username}")
private String username;
@Value("${zyplayer.datasource.manage.password}")
private String password;
@Bean(name = "manageDatasource")
public DataSource manageDatasource() {
Properties xaProperties = new Properties();
xaProperties.setProperty("driverClassName", driverClassName);
xaProperties.setProperty("url", url);
xaProperties.setProperty("username", username);
xaProperties.setProperty("password", password);
xaProperties.setProperty("maxActive", "500");
xaProperties.setProperty("testOnBorrow", "true");
xaProperties.setProperty("testWhileIdle", "true");
xaProperties.setProperty("validationQuery", "select 'x'");
AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
xaDataSource.setXaProperties(xaProperties);
xaDataSource.setXaDataSourceClassName("com.alibaba.druid.pool.xa.DruidXADataSource");
xaDataSource.setUniqueResourceName("manageDatasource");
xaDataSource.setMaxPoolSize(500);
xaDataSource.setMinPoolSize(1);
xaDataSource.setMaxLifetime(60);
return xaDataSource;
}
@Bean(name = "manageSqlSessionFactory")
public MybatisSqlSessionFactoryBean manageSqlSessionFactory() throws Exception {
MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(manageDatasource());
sqlSessionFactoryBean.setPlugins(new Interceptor[]{SQL_LOG_INTERCEPTOR});
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:/mapper/manage/*Mapper.xml"));
return sqlSessionFactoryBean;
}
}
@Bean
public PerformanceInterceptor performanceInterceptor() {
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
/* <!-- SQL 执行性能分析,开发环境使用,线上不推荐。 maxTime 指的是 sql 最大执行时长 --> */
performanceInterceptor.setMaxTime(1000);
/* <!--SQL是否格式化 默认false--> */
performanceInterceptor.setFormat(true);
return performanceInterceptor;
}
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}

View File

@@ -0,0 +1,46 @@
package com.zyplayer.doc.manage.framework.config.security;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;
/**
* 备用
* @author Administrator
*
*/
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
private RequestCache requestCache = new HttpSessionRequestCache();
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
SavedRequest savedRequest = requestCache.getRequest(request, response);
String targetUrl = savedRequest.getRedirectUrl();
// boolean isAjax = HttpHelper.isAjaxRequest(request);
boolean isAjax = true;
if (isAjax) {
Map<String, Object> result = new HashMap<String, Object>();
result.put("url", targetUrl);
response.getWriter().print(result.toString());
response.getWriter().flush();
} else {
redirectStrategy.sendRedirect(request, response, targetUrl);
}
System.out.println("Redirecting to DefaultSavedRequest Url: " + targetUrl);
}
}

View File

@@ -0,0 +1,79 @@
package com.zyplayer.doc.manage.framework.config.security;
import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
public class MyUserDetails implements UserDetails {
private static final long serialVersionUID = 1L;
private Integer userId;
private String username;
private String password;
private boolean enabled;
private Collection<? extends GrantedAuthority> authorities;
public MyUserDetails(Integer userId, String username, String password, boolean enabled) {
super();
this.userId = userId;
this.username = username;
this.password = password;
this.enabled = enabled;
}
public MyUserDetails(Integer userId, String username, String password, boolean enabled,
Collection<? extends GrantedAuthority> authorities) {
super();
this.userId = userId;
this.username = username;
this.password = password;
this.enabled = enabled;
this.authorities = authorities;
}
public Integer getUserId() {
return this.userId;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return username;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return enabled;
}
@Override
public String toString() {
return "MyUserDetails [userId=" + userId + ", username=" + username + ", password=" + password + ", enabled="
+ enabled + ", authorities=" + authorities + "]";
}
}

View File

@@ -0,0 +1,49 @@
package com.zyplayer.doc.manage.framework.config.security;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang.StringUtils;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
public class MyUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
// 是否开启验证码功能
private boolean isOpenValidateCode = true;
public static final String VALIDATE_CODE = "validateCode";
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (isOpenValidateCode) {
checkValidateCode(request);
}
return super.attemptAuthentication(request, response);
}
protected void checkValidateCode(HttpServletRequest request) {
HttpSession session = request.getSession();
String sessionValidateCode = obtainSessionValidateCode(session);
sessionValidateCode = "1234";// 做个假的验证码;
// 让上一次的验证码失效
session.setAttribute(VALIDATE_CODE, null);
String validateCodeParameter = obtainValidateCodeParameter(request);
if (StringUtils.isEmpty(validateCodeParameter) || !sessionValidateCode.equalsIgnoreCase(validateCodeParameter)) {
throw new AuthenticationServiceException("验证码错误!");
}
}
private String obtainValidateCodeParameter(HttpServletRequest request) {
Object obj = request.getParameter(VALIDATE_CODE);
return null == obj ? "" : obj.toString();
}
protected String obtainSessionValidateCode(HttpSession session) {
Object obj = session.getAttribute(VALIDATE_CODE);
return null == obj ? "" : obj.toString();
}
}

View File

@@ -0,0 +1,30 @@
package com.zyplayer.doc.manage.framework.config.security;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if ("1".equals(username)) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority("ROLE_1"));
String pwd = DigestUtils.md5DigestAsHex("1".getBytes());
return new MyUserDetails(1, "1", pwd, true, authorities);
}
throw new UsernameNotFoundException("用户名 '" + username + "'没有找到!");
}
}

View File

@@ -0,0 +1,26 @@
package com.zyplayer.doc.manage.framework.config.security;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
/**
* 用户工具类
*/
public class UserUtil {
/**
* 获取当前用户
* @return
*/
public static MyUserDetails getCurrentUser() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Object principal = null;
if (authentication != null) {
principal = authentication.getPrincipal();
}
if (principal != null && principal instanceof MyUserDetails) {
return (MyUserDetails) principal;
}
return null;
}
}

View File

@@ -0,0 +1,113 @@
package com.zyplayer.doc.manage.framework.config.security;
//package com.zyplayer.doc.manage.framework.config.security;
//
//import java.io.IOException;
//import java.io.PrintWriter;
//
//import javax.servlet.ServletException;
//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletResponse;
//
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
//import org.springframework.security.config.annotation.web.builders.HttpSecurity;
//import org.springframework.security.config.annotation.web.builders.WebSecurity;
//import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
//import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
//import org.springframework.security.core.Authentication;
//import org.springframework.security.core.AuthenticationException;
//import org.springframework.security.web.authentication.AuthenticationFailureHandler;
//import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
//import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
//import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
//
//@Configuration
//@EnableWebSecurity // 注解开启Spring Security的功能
//public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
//
// @Override
// protected void configure(HttpSecurity http) throws Exception {
// http.authorizeRequests()//定义哪些url需要保护哪些url不需要保护
// .antMatchers("/statics/lib/**", "/message/").permitAll()//定义不需要认证就可以访问
// .anyRequest()
// .authenticated()
// .and()
// .formLogin()
// .loginPage("/statics/manage/login.html")// 定义当需要用户登录时候,转到的登录页面
// .successHandler(new AuthenticationSuccessHandler() {
// @Override
// public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
// httpServletResponse.setContentType("application/json;charset=utf-8");
// PrintWriter out = httpServletResponse.getWriter();
// out.write("{\"status\":\"ok\",\"msg\":\"登录成功\"}");
// out.flush();
// out.close();
// }
// }).failureHandler(new AuthenticationFailureHandler() {
// @Override
// public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
// httpServletResponse.setContentType("application/json;charset=utf-8");
// PrintWriter out = httpServletResponse.getWriter();
// out.write("{\"status\":\"error\",\"msg\":\"登录失败\"}");
// out.flush();
// out.close();
// }
// })
// .permitAll()
// .loginProcessingUrl("/user/login")
// .usernameParameter("username")
// .passwordParameter("password")
// .permitAll()
// .and()
// .logout()
// .permitAll()
// .and()
// .csrf()
// .disable();
// }
//
// @Override
// protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// auth.userDetailsService(userDetailsServiceImpl());//.passwordEncoder(new Md5PasswordEncoder());
// }
//
// @Bean
// public UserDetailsServiceImpl userDetailsServiceImpl() {
// return new UserDetailsServiceImpl();
// }
//
// @Bean
// public MyUsernamePasswordAuthenticationFilter myUsernamePasswordAuthenticationFilter() throws Exception {
// MyUsernamePasswordAuthenticationFilter myFilter = new MyUsernamePasswordAuthenticationFilter();
// myFilter.setAuthenticationManager(authenticationManagerBean());
// myFilter.setAuthenticationSuccessHandler(authenticationSuccessHandler());
// myFilter.setAuthenticationFailureHandler(authenticationFailureHandler());
// myFilter.setRememberMeServices(tokenBasedRememberMeServices());
// return myFilter;
// }
//
// @Bean
// public AuthenticationSuccessHandler authenticationSuccessHandler() {
// return new SimpleUrlAuthenticationSuccessHandler("/login/success");
// }
//
// @Bean
// public AuthenticationFailureHandler authenticationFailureHandler() {
// return new SimpleUrlAuthenticationFailureHandler("/login/failure");
// }
//
// @Override
// public void configure(WebSecurity web) throws Exception {
// web.ignoring().antMatchers("/statics/lib/**", "**/css/**", "**/js/**", "**/img/**");
// }
//
// @Autowired
// public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// //在内存中创建了一个用户该用户的名称为user密码为password用户角色为ADMIN
// auth.inMemoryAuthentication()
// .withUser("user").password("password").roles("ADMIN");
// }
//}
//

View File

@@ -0,0 +1,137 @@
package com.zyplayer.doc.manage.framework.config.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.RememberMeAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices;
import org.springframework.util.DigestUtils;
@Configuration
@EnableWebSecurity
@Order(1)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
/**
* 忽略静态文件
*/
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/statics/lib/**", "/css/**", "/js/**", "/img/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/login/**").permitAll()//为了测试其他功能,设置“ /** ”允许所有请求
// user权限可以访问的请求
.antMatchers("/security/user").hasRole("user")
// admin权限可以访问的请求
.antMatchers("/security/admin").hasRole("admin")
// SpEL表达式:需要拥有user权限且进行了完全认证
.antMatchers("/user/account").access("hasRole('user') and isFullyAuthenticated()")
// 其他地址的访问均需验证权限(需要登录)
.anyRequest().authenticated().and()
// 添加验证码验证
.addFilterAt(myUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class).exceptionHandling()
.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/statics/manage/login.html")).and()
.addFilterAt(rememberMeAuthenticationFilter(), RememberMeAuthenticationFilter.class)
// 指定登录页面的请求路径
.formLogin().loginPage("/statics/manage/login.html")
// 登陆处理路径
.loginProcessingUrl("/login").permitAll().and()
// 退出请求的默认路径为logout下面改为signout
// 成功退出登录后的url可以用logoutSuccessUrl设置
.logout().deleteCookies("remember-me")
.logoutUrl("/signout")
.logoutSuccessUrl("/statics/manage/login.html")
.permitAll().and()
// 开启rememberMe设置一个私钥专供testall项目使用注意与下面TokenBasedRememberMeServices的key保持一致
// .rememberMe().key("testallKey").and()
// 关闭csrf
.csrf().disable();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsServiceImpl())
.passwordEncoder(new PasswordEncoder() {
@Override
public String encode(CharSequence charSequence) {
return DigestUtils.md5DigestAsHex(charSequence.toString().getBytes());
}
@Override
public boolean matches(CharSequence charSequence, String s) {
return s.equals(DigestUtils.md5DigestAsHex(charSequence.toString().getBytes()));
}
}).and().authenticationProvider(rememberMeAuthenticationProvider());
}
@Bean
public UserDetailsServiceImpl userDetailsServiceImpl() {
return new UserDetailsServiceImpl();
}
@Bean
public MyUsernamePasswordAuthenticationFilter myUsernamePasswordAuthenticationFilter() throws Exception {
MyUsernamePasswordAuthenticationFilter myFilter = new MyUsernamePasswordAuthenticationFilter();
myFilter.setAuthenticationManager(authenticationManagerBean());
myFilter.setAuthenticationSuccessHandler(authenticationSuccessHandler());
myFilter.setAuthenticationFailureHandler(authenticationFailureHandler());
myFilter.setRememberMeServices(tokenBasedRememberMeServices());
return myFilter;
}
@Bean
public AuthenticationSuccessHandler authenticationSuccessHandler() {
return new SimpleUrlAuthenticationSuccessHandler("/login/success");
}
@Bean
public AuthenticationFailureHandler authenticationFailureHandler() {
return new SimpleUrlAuthenticationFailureHandler("/login/failure");
}
@Bean
public TokenBasedRememberMeServices tokenBasedRememberMeServices() {
TokenBasedRememberMeServices tbrms = new TokenBasedRememberMeServices("testallKey", userDetailsServiceImpl());
// 设置cookie过期时间为2天
tbrms.setTokenValiditySeconds(60 * 60 * 24 * 2);
// 设置checkbox的参数名为rememberMe默认为remember-me注意如果是ajax请求参数名不是checkbox的name而是在ajax的data里
tbrms.setParameter("rememberMe");
tbrms.setAlwaysRemember(false);
return tbrms;
}
@Bean
public RememberMeAuthenticationProvider rememberMeAuthenticationProvider() {
RememberMeAuthenticationProvider rmap = new RememberMeAuthenticationProvider("testallKey");
return rmap;
}
@Bean
public RememberMeAuthenticationFilter rememberMeAuthenticationFilter() throws Exception {
RememberMeAuthenticationFilter myFilter = new RememberMeAuthenticationFilter(authenticationManagerBean(), tokenBasedRememberMeServices());
return myFilter;
}
}

View File

@@ -0,0 +1,38 @@
package com.zyplayer.doc.manage.framework.interceptor;
import javax.servlet.ServletContext;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
import org.springframework.web.context.ServletContextAware;
/**
* 所有bean初始化后执行bean初始化了再初始化一些自己的东西
*/
@Component
public class InitServletContextAware implements InitializingBean,ServletContextAware {
private ServletContext context;
@Override
public void setServletContext(ServletContext context) {
this.context = context;
}
@Override
public void afterPropertiesSet() throws Exception {
ctx();
}
private void ctx(){
String ctx = context.getContextPath();
if (ctx != null && ctx.trim().length() > 0 && !ctx.trim().equals("/")) {
context.setAttribute("ctx", ctx+"/");
context.setAttribute("statics", ctx+"/statics/");
} else {
context.setAttribute("ctx", "/");
context.setAttribute("statics", "/statics/");
}
}
}

View File

@@ -0,0 +1,127 @@
package com.zyplayer.doc.manage.repository.support.interceptor;
import java.text.DateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Intercepts({
@Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }),
@Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class })
})
public class SqlLogInterceptor implements Interceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(SqlLogInterceptor.class);
@Override
public Object intercept(Invocation invocation) throws Throwable {
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
Object parameter = null;
if (invocation.getArgs().length > 1) {
parameter = invocation.getArgs()[1];
}
BoundSql boundSql = mappedStatement.getBoundSql(parameter);
Configuration configuration = mappedStatement.getConfiguration();
// 获取sql语句
String sql = getSqlString(configuration, boundSql);
LOGGER.info(sql);
// 执行结果
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
if (target instanceof Executor) {
return Plugin.wrap(target, this);
} else {
return target;
}
}
@Override
public void setProperties(Properties properties) {
}
private String getParameterValue(Object obj) {
String value = null;
if (obj instanceof String) {
value = "'" + obj.toString() + "'";
} else if (obj instanceof Date) {
DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);
value = "'" + formatter.format(obj) + "'";
//System.out.println(value);
} else {
if (obj != null) {
value = obj.toString();
} else {
value = "'null'";
}
}
return value;
}
public String getSqlString(Configuration configuration, BoundSql boundSql) {
Object parameterObject = boundSql.getParameterObject();
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
StringBuilder sqlSb = new StringBuilder(boundSql.getSql().replaceAll("[\\s]+", " "));
int fromIndex = 0;
if (parameterMappings.size() > 0 && parameterObject != null) {
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
//sqlSb = sqlSb.replaceFirst("\\?", getParameterValue(parameterObject));
fromIndex = replacePlaceholder(sqlSb, fromIndex, getParameterValue(parameterObject));
} else {
MetaObject metaObject = configuration.newMetaObject(parameterObject);
for (ParameterMapping parameterMapping : parameterMappings) {
String propertyName = parameterMapping.getProperty();
if (metaObject.hasGetter(propertyName)) {
Object obj = metaObject.getValue(propertyName);
//sqlSb = sqlSb.replaceFirst("\\?", getParameterValue(obj));
fromIndex = replacePlaceholder(sqlSb, fromIndex, getParameterValue(obj));
} else if (boundSql.hasAdditionalParameter(propertyName)) {
Object obj = boundSql.getAdditionalParameter(propertyName);
//sqlSb = sqlSb.replaceFirst("\\?", getParameterValue(obj));
fromIndex = replacePlaceholder(sqlSb, fromIndex, getParameterValue(obj));
}
}
}
}
return sqlSb.toString();
}
/**
* 替换?占位符
* @author 暮光:城中城
* @since 2018年10月27日
* @param sql
* @param fromIndex
* @param replaceStr
* @return
*/
private int replacePlaceholder(StringBuilder sql, int fromIndex, String replaceStr) {
int index = sql.indexOf("?", fromIndex);
if (index >= 0) {
sql.replace(index, index + 1, replaceStr);
}
return index + replaceStr.length();
}
}

View File

@@ -0,0 +1,23 @@
package com.zyplayer.doc.manage.web.manage;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloController {
// @RequestMapping("/")
// public String index() {
// return "manage/index";
// }
//
// @RequestMapping("/hello")
// public String hello() {
// return "manage/hello";
// }
//
// @RequestMapping("/login")
// public String login() {
// return "statics/manage/hello.html";
// }
}

View File

@@ -0,0 +1,123 @@
package com.zyplayer.doc.manage.web.manage;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.WebAttributes;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import com.zyplayer.doc.manage.framework.config.security.MyUserDetails;
import com.zyplayer.doc.manage.framework.config.security.UserUtil;
@RestController
public class UserController {
private RequestCache requestCache = new HttpSessionRequestCache();
@RequestMapping(value = "/login_page", method = RequestMethod.GET)
public ModelAndView loginPage(HttpServletRequest request) {
if (true) {
return new ModelAndView("/login/ajax");
} else {
return new ModelAndView("login.html");
}
}
/**
* 如果是访问受限页面后跳转到登录页的则在targetUrl保存之前受限页面的路径供页面调用
*
* @param request
* @param response
* @return
*/
@RequestMapping(value = "/login/success", method = RequestMethod.GET)
public Map<String, Object> loginSuccess(HttpServletRequest request, HttpServletResponse response) {
SavedRequest savedRequest = requestCache.getRequest(request, response);
String targetUrl = null;
if (savedRequest != null) {
targetUrl = savedRequest.getRedirectUrl();
}
Map<String, Object> result = new HashMap<String, Object>();
result.put("success", true);
result.put("targetUrl", targetUrl);
return result;
}
/**
* 获取异常信息返回给页面
* @param request
* @param response
* @return
*/
@RequestMapping(value = "/login/failure", method = RequestMethod.GET)
public Map<String, Object> loginFailure(HttpServletRequest request, HttpServletResponse response) {
AuthenticationException ae = (AuthenticationException) request.getSession().getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
Map<String, Object> result = new HashMap<String, Object>();
result.put("success", false);
result.put("message", ae.getMessage());
return result;
}
@RequestMapping(value = "/login/ajax", method = RequestMethod.GET)
public Map<String, Object> loginAjax() {
Map<String, Object> result = new HashMap<String, Object>();
result.put("success", false);
result.put("message", "you need login!");
return result;
}
@RequestMapping(value = "/security/user", method = RequestMethod.GET)
public Map<String, Object> securityUser(HttpServletRequest request) {
MyUserDetails user = UserUtil.getCurrentUser();
Map<String, Object> result = new HashMap<String, Object>();
StringBuilder userRole = new StringBuilder();
if (user != null) {
result.put("userId", user.getUserId());
result.put("userName", user.getUsername());
Collection<? extends GrantedAuthority> roleLst = user.getAuthorities();
for (GrantedAuthority sga : roleLst) {
userRole.append(sga.toString() + "; ");
}
}
result.put("userRole", userRole.toString());
result.put("message", "This message is only visible to the user");
return result;
}
@RequestMapping(value = "/security/admin", method = RequestMethod.GET)
public Map<String, Object> securityAdmin(HttpServletRequest request) {
MyUserDetails user = UserUtil.getCurrentUser();
Map<String, Object> result = new HashMap<String, Object>();
StringBuilder userRole = new StringBuilder();
if (user != null) {
result.put("userId", user.getUserId());
result.put("userName", user.getUsername());
Collection<? extends GrantedAuthority> roleLst = user.getAuthorities();
for (GrantedAuthority sga : roleLst) {
userRole.append(sga.toString() + "; ");
}
}
result.put("userRole", userRole.toString());
result.put("message", "This message is only visible to the admin");
return result;
}
@RequestMapping(value = "/user/account", method = RequestMethod.GET)
public Map<String, Object> getUserAcctunt(HttpServletRequest request) {
Map<String, Object> result = new HashMap<String, Object>();
result.put("message", "需要进行完整认证的请求不是通过Remember-me功能进行的认证");
return result;
}
}

View File

@@ -1,16 +1,44 @@
spring:
application:
name: zyplayer-doc-manage
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/zyplayer-doc-manage?characterEncoding=utf8&amp;zeroDateTimeBehavior=convertToNull&amp;autoReconnect=true
username: root
password: root
velocity:
layout-url: common/default.vm
cache: false
suffix: .vm
expose-spring-macro-helpers: true
date-tool-attribute: dateTool
number-tool-attribute: numberTool
contentType: text/html;charset=UTF-8
resource-loader-path: classpath:/vm/
default-content-type: text/html
ignore-accept-header: true
charset: UTF-8
properties:
input:
encoding: UTF-8
output:
encoding: UTF-8
# datasource:
# driver-class-name: com.mysql.jdbc.Driver
# url: jdbc:mysql://127.0.0.1:3306/zyplayer-doc-manage?characterEncoding=utf8&amp;zeroDateTimeBehavior=convertToNull&amp;autoReconnect=true
# username: root
# password: root
server:
port: 8082
contextPath: /
servlet:
context-path: /
zyplayer:
datasource:
manage:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/zyplayer-doc-manage?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&autoReconnect=true&useSSL=false
username: root
password: root
mybatis-plus:
mapper-locations: classpath:/mapper/**/*Mapper.xml
#实体扫描多个package用逗号或者分号分隔

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>
[%d{yyyy-MM-dd HH:mm:ss}][%-5level][%logger{0}] %msg%n
</pattern>
</encoder>
</appender>
<logger name="com.atomikos.jdbc" level="warn"/>
<logger name="com.atomikos.datasource.xa" level="warn"/>
<logger name="com.atomikos.icatch.imp" level="warn"/>
<root level="info">
<appender-ref ref="STDOUT"/>
</root>
</configuration>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,340 @@
/**
* 一些公用方法
* @author 暮光:城中城
* @since 2017年5月7日
*/
function serialize(value) {
if (typeof value === 'string') {
return value;
}
return JSON.stringify(value);
}
function deserialize(value) {
if (typeof value !== 'string' || isEmpty(value)) {
return undefined;
}
try {
return JSON.parse(value);
} catch (e) {
try {
return eval('(' + value + ')');// 处理变态的单双引号共存字符串
} catch (e) {
return value || undefined;
}
}
}
function validateResult(result) {
if(result.errCode == 200) {
return true;
} else {
alert(result.errMsg);
}
return false;
}
function getNowDate() {
var date = new Date();
var month = date.getMonth() + 1;
var strDate = date.getDate();
if (month >= 1 && month <= 9) {
month = "0" + month;
}
if (strDate >= 0 && strDate <= 9) {
strDate = "0" + strDate;
}
var currentdate = date.getFullYear() + "-" + month + "-" + strDate;
return currentdate;
}
function getNowTime() {
var date = new Date();
var hours = date.getHours();
var minutes = date.getMinutes();
var seconds = date.getSeconds();
if (hours >= 1 && hours <= 9) {
hours = "0" + hours;
}
if (minutes >= 0 && minutes <= 9) {
minutes = "0" + minutes;
}
if (seconds >= 0 && seconds <= 9) {
seconds = "0" + seconds;
}
var currentdate = hours + ":" + minutes + ":" + seconds;
return currentdate;
}
function getNowDateTime() {
var currentdate = getNowDate() + " " + getNowTime();
return currentdate;
}
/**
* 返回不为空的字符串为空返回def
*/
function getNotEmptyStr(str, def) {
if (isEmpty(str)) {
return isEmpty(def) ? "" : def;
}
return str;
}
/**
* 是否是空对象
* @param obj
* @returns
*/
function isEmptyObject(obj){
return $.isEmptyObject(obj);
}
/**
* 是否是空字符串
* @param str
* @returns
*/
function isNull(str){
return (str == null || str == undefined);
}
/**
* 是否不是空字符串
* @param str
* @returns
*/
function isNotNull(str){
return !isNull(str);
}
/**
* 是否是空字符串
* @param str
* @returns
*/
function isEmpty(str){
return (str == "" || str == null || str == undefined);
}
/**
* 是否不是空字符串
* @param str
* @returns
*/
function isNotEmpty(str){
return !isEmpty(str);
}
/**
* 数组转字符串,使用空格分隔
* @param array
* @returns
*/
function arrToString(array){
var temStr = "";
if(isEmpty(array)){
return temStr;
}
array.forEach(function(e){
if(isNotEmpty(temStr)) {
temStr += " ";
}
temStr += e;
});
return temStr;
}
/**
* 数组array中是否包含str字符串
* @param array
* @param str
* @returns
*/
function haveString(array, str){
if(isEmpty(array)) {
return false;
}
for (var i = 0; i < array.length; i++) {
if(array[i] == str) {
return true;
}
}
return false;
}
/**
* 直接返回对象的第一个属性
* @param data
* @returns
*/
function getObjectFirstAttribute(data) {
for ( var key in data) {
return data[key];
}
}
/**
* 如果对象只有一个属性则返回第一个属性否则返回null
* @param data
* @returns
*/
function getObjectFirstAttributeIfOnly(data) {
var len = 0, value = "";
for ( var key in data) {
if (++len > 1) {
return null;
}
value = data[key];
}
return value;
}
function post(url, param, success, fail, complete) {
ajaxTemp(url, "POST", "JSON", param, success, fail, complete);
}
/**
* ajax处理事件模板
*
* @url 后台处理的url即action
* @dataSentType 数据发送的方式有postget方式
* @dataReceiveType 数据接收格式有html json text等
* @paramsStr 传入后台的参数
* @successFunction ajax成功后执行的函数名 ajaxTemp("", "GET", "html", {}, function(){},
* function(){}, "");
*/
function ajaxTemp(url, dataSentType, dataReceiveType, paramsStr, successFunction, errorFunction, completeFunction, id) {
$.ajax({
url : url, // 后台处理程序
sync : false,
type : dataSentType, // 数据发送方式
dataType : dataReceiveType, // 接受数据格式
data : eval(paramsStr),
contentType : "application/x-www-form-urlencoded; charset=UTF-8",
success : function(msg) {
if(typeof successFunction == "function") {
successFunction(msg,id);
}
},
beforeSend : function() {
},
complete : function(msg) {
if(typeof completeFunction == "function") {
completeFunction(msg,id);
}
},
error : function(msg) {
if(typeof errorFunction == "function") {
errorFunction(msg,id);
}
}
});
}
/**
* 获取cookie
* @param name
* @returns
*/
function getCookie(name) {
var arr,reg=new RegExp("(^| )"+name+"=([^;]*)(;|$)");
if(arr=document.cookie.match(reg)){
return unescape(arr[2]);
}
return null;
}
/**
* 字符串格式化
*/
String.prototype.format = function(args) {
if (arguments.length > 0) {
var result = this;
if (arguments.length == 1 && typeof (args) == "object") {
for ( var key in args) {
var reg = new RegExp("({" + key + "})", "g");
result = result.replace(reg, args[key]);
}
} else {
for (var i = 0; i < arguments.length; i++) {
if (arguments[i] == undefined) {
return "";
} else {
var reg = new RegExp("({[" + i + "]})", "g");
result = result.replace(reg, arguments[i]);
}
}
}
return result;
} else {
return this;
}
}
String.prototype.endWith = function(str) {
if (str == null || str == "" || this.length == 0 || str.length > this.length) {
return false;
}
return (this.substring(this.length - str.length) == str);
};
String.prototype.startWith = function(str) {
if (str == null || str == "" || this.length == 0 || str.length > this.length) {
return false;
}
return (this.substr(0, str.length) == str);
};
var common = {
//获取页面顶部被卷起来的高度函数
scrollTop : function(){
return Math.max(
//chrome
document.body.scrollTop,
//firefox/IE
document.documentElement.scrollTop);
},
//获取页面文档的总高度
documentHeight : function(){
//现代浏览器IE9+和其他浏览器和IE8的document.body.scrollHeight和document.documentElement.scrollHeight都可以
return Math.max(document.body.scrollHeight,document.documentElement.scrollHeight);
},
//获取页面浏览器视口的高度
windowHeight : function(){
return (document.compatMode == "CSS1Compat")?
document.documentElement.clientHeight:
document.body.clientHeight;
},
//提取地址栏信息
getRequest: function () {
var url = location.search;// 获取url中"?"符后的字串
url = decodeURIComponent(url);
var theRequest = {};
if (url.indexOf("?") != -1) {
var str = url.substr(1);
strs = str.split("&");
for (var i = 0; i < strs.length; i++) {
theRequest[strs[i].split("=")[0]] = unescape(strs[i].split("=")[1]);
}
}
return theRequest;
},
getParam: function(name){
var url = location.search;// 获取url中"?"符后的字串
url = decodeURIComponent(url);
if (url.indexOf("?") != -1) {
var str = url.substr(1);
strs = str.split("&");
for (var i = 0; i < strs.length; i++) {
var nameTemp = strs[i].split("=")[0];
if(name == nameTemp) {
return unescape(strs[i].split("=")[1]);
}
}
}
return "";
}
};

View File

@@ -0,0 +1,106 @@
/**
* 两个元素上下、左右拖动动态改变大小
* @author 暮光:城中城
* @since 2017年5月7日
*/
(function($){
$.fn.mgResizebleHeight = function(options) {
var defaults = {prev:this,next:this, prevHtMin:0, prevHtMax:999, nextHtMin:0, nextHtMax:999};
var opts = $.extend(defaults, options);
var disY = 0, prevH = 0, nextH = 0, isStart = false;
var prev, next, thisObj = this;
$(document).mousemove(function(ev){
if(!isStart){return;}
var ev = ev || window.event;
var H = ev.clientY - disY;
var prevHNow = prevH+H, nextHNow = nextH-H;
if(opts.prevHtMin >= prevHNow) {
prevHNow = opts.prevHtMin;
nextHNow = next.outerHeight();
}
if(opts.nextHtMin >= nextHNow) {
nextHNow = opts.nextHtMin;
prevHNow = prev.outerHeight();
}
if(opts.prevHtMax <= prevHNow) {
prevHNow = opts.prevHtMax;
nextHNow = next.outerHeight();
}
if(opts.nextHtMax <= nextHNow) {
nextHNow = opts.nextHtMax;
prevHNow = prev.outerHeight();
}
//prev.css("height", prevHNow + 'px');
//next.css("height", nextHNow + 'px');
if(typeof opts.onresize == 'function') {
opts.onresize(prevHNow, nextHNow);
}
}).mouseup(function(ev){
isStart = false;
});
$(this).mousedown(function(ev){
var ev = ev || window.event;
disY = ev.clientY;
prev = (opts.prev == thisObj)?$(opts.prev).prev():$(opts.prev);
next = (opts.next == thisObj)?$(opts.next).next():$(opts.next);
prevH = prev.outerHeight();
nextH = next.outerHeight();
isStart = true;
});
}
/**
* 改变宽度的功能,只是实现各种消息的通知,实际改变大小需要在回调里面自己操作
*/
$.fn.mgResizebleWidth = function(options) {
var defaults = {prev:this,next:this, prevWtMin:0, prevWtMax:999, nextWtMin:0, nextWtMax:999};
var opts = $.extend(defaults, options);
var disX = 0, prevW = 0, nextW = 0, isStart = false;
var prev, next, thisObj = this;
$(document).mousemove(function(ev){
if(!isStart){return;}
var ev = ev || window.event;
var W = ev.clientX - disX;
var prevWNow = prevW+W, nextWNow = nextW-W;
if(opts.prevWtMin >= prevWNow) {
prevWNow = opts.prevWtMin;
nextWNow = next.outerWidth();
}
if(opts.nextWtMin >= nextWNow) {
nextWNow = opts.nextWtMin;
prevWNow = prev.outerWidth();
}
if(opts.prevWtMax <= prevWNow) {
prevWNow = opts.prevWtMax;
nextWNow = next.outerWidth();
}
if(opts.nextWtMax <= nextWNow) {
nextWNow = opts.nextWtMax;
prevWNow = prev.outerWidth();
}
//prev.css("width", prevWNow + 'px');
//next.css("width", nextWNow + 'px');
if(typeof opts.onresize == 'function') {
opts.onresize(prevWNow, nextWNow);
}
}).mouseup(function(ev){
if(!isStart){return;}
isStart = false;
if(typeof opts.onfinish == 'function') {
opts.onfinish();
}
});
$(this).mousedown(function(ev){
var ev = ev || window.event;
disX = ev.clientX;
prev = (opts.prev == thisObj)?$(opts.prev).prev():$(opts.prev);
next = (opts.next == thisObj)?$(opts.next).next():$(opts.next);
prevW = prev.outerWidth();
nextW = next.outerWidth();
isStart = true;
if(typeof opts.onstart == 'function') {
opts.onstart();
}
});
}
})(jQuery);

View File

@@ -0,0 +1,33 @@
/**
* 提示工具类
* @author 暮光:城中城
* @since 2017年5月7日
*/
var Toast = {
notOpen:function(){
var data = {
message:"该功能暂未开放,敬请期待!",
icon: 'exclamation-sign',type:"warning",
};
this.show(data);
},
warn:function(msg, time){
var data = {
message:msg,time:time,
icon: 'exclamation-sign',type:'warning',
};
this.show(data);
},
error:function(msg, time){
var data = {
message:msg,time:time,
icon: 'exclamation-sign',type:'danger',
};
this.show(data);
},
show:function(data){
data.time = isEmpty(data.time)?2000:data.time;
data.placement = isEmpty(data.placement)?'top':data.placement;
new $.zui.Messager(data.message, data).show();
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 290 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 290 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,146 @@
/*!
* ZUI: 标签页管理器 - v1.8.1 - 2018-01-18
* http://zui.sexy
* GitHub: https://github.com/easysoft/zui.git
* Copyright (c) 2018 cnezsoft.com; Licensed MIT
*/
.tabs {
position: relative;
min-height: 400px;
}
.tabs-navbar {
padding: 4px 4px 0 4px;
}
.tabs-nav {
height: 30px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
border-bottom: none;
border-bottom: 1px solid #ddd;
}
.tab-nav-item {
width: 160px;
min-width: 0;
max-width: 160px;
padding-right: 2px;
margin-bottom: 0;
border: none;
}
.tab-nav-item:hover {
min-width: 95px;
}
.tab-nav-link {
position: relative;
height: 30px;
margin: 0;
overflow: hidden;
background-color: rgba(255, 255, 255, .65);
background-color: #e5e5e5;
border-color: #ddd;
border-bottom: none;
border-radius: 2px 2px 0 0;
}
.tab-nav-link > .title {
position: absolute;
top: 5px;
right: 5px;
left: 30px;
display: block;
overflow: hidden;
font-size: 14px;
line-height: 20px;
text-overflow: ellipsis;
white-space: nowrap;
}
.tab-nav-link > .icon {
position: absolute;
top: 5px;
left: 5px;
display: block;
width: 20px;
height: 20px;
line-height: 20px;
text-align: center;
opacity: .8;
}
.tab-nav-item.loading .tab-nav-link > .icon:before {
content: '\e97b';
-webkit-animation: spin 2s infinite linear;
-o-animation: spin 2s infinite linear;
animation: spin 2s infinite linear;
}
.tab-nav-link > .close {
position: absolute;
top: 5px;
right: 5px;
width: 20px;
height: 20px;
font-weight: 200;
line-height: 16px;
text-align: center;
text-shadow: none;
visibility: hidden;
border-radius: 4px;
opacity: 0;
-webkit-transition: all .2s;
-o-transition: all .2s;
transition: all .2s;
}
.tab-nav-link > .close:hover {
color: #fff;
background-color: #ea644a;
}
.tab-nav-link:hover > .title {
right: 25px;
}
.tab-nav-link:hover > .close {
visibility: visible;
opacity: 1;
}
.tab-nav-link.not-closable > .close {
display: none;
}
.nav-tabs.tabs-nav > li > a,
.nav-tabs.tabs-nav > li > a:hover,
.nav-tabs.tabs-nav > li > a:focus {
border-color: #ddd #ddd transparent #ddd;
}
.tab-nav-condensed .tab-nav-link > .title {
left: 5px;
text-overflow: initial;
}
.tab-nav-condensed .tab-nav-link > .icon {
display: none;
}
.tabs-container {
position: absolute;
top: 34px;
right: 0;
bottom: 0;
left: 0;
}
.tabs-container > .tab-pane {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: none;
}
.tabs-container > .tab-pane.active {
display: block;
}
.tab-iframe-cover {
display: none;
}
.tabs-show-contextmenu .tab-iframe-cover {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: block;
}

View File

@@ -0,0 +1,488 @@
/*!
* ZUI: 标签页管理器 - v1.8.1 - 2018-01-18
* http://zui.sexy
* GitHub: https://github.com/easysoft/zui.git
* Copyright (c) 2018 cnezsoft.com; Licensed MIT
*/
/* ========================================================================
* ZUI: tabs.js
* http://zui.sexy
* ========================================================================
* Copyright (c) 2017-2018 cnezsoft.com; Licensed MIT
* ======================================================================== */
(function($) {
'use strict';
/**
* Tab object
* @param {Object | String} tab
*/
var Tab = function(tab) {
var that = this;
if(typeof tab === 'string') {
that.url = tab;
} else if($.isPlainObject(tab)) {
$.extend(that, tab);
}
if(!that.id) {
that.id = $.zui.uuid();
}
if(!that.type) {
if(that.iframe) {
that.type = 'iframe';
that.url = that.url || that.iframe;
} else if(that.ajax) {
that.type = 'ajax';
that.url = that.url || ($.isPlainObject(that.ajax) ? that.ajax.url : that.ajax);
} else if(that.url) {
that.type = tab.ajax ? 'ajax' : 'iframe';
} else {
that.type = 'custom';
}
}
that.createTime = new Date().getTime();
that.openTime = 0;
that.onCreate && that.onCreate.call(that);
};
Tab.prototype.open = function() {
var that = this;
that.openTime = new Date().getTime();
that.onOpen && that.onOpen.call(that);
};
Tab.prototype.close = function() {
var that = this;
that.openTime = 0;
that.onClose && that.onClose.call(that);
};
Tab.create = function(data) {
if (data instanceof Tab) {
return data;
}
return new Tab(data);
};
var NAME = 'zui.tabs'; // model name
var DEFAULTS = {
tabs: [],
defaultTabIcon: 'icon-window',
contextMenu: true,
errorTemplate: '<div class="alert alert-block alert-danger with-icon"><i class="icon-warning-sign"></i><div class="content">{0}</div></div>',
// messagerOptions: null,
showMessage: true,
navTemplate: '<nav class="tabs-navbar"></nav>',
containerTemplate: '<div class="tabs-container"></div>'
};
var LANG = {
zh_cn: {
reload: '重新加载',
close: '关闭',
closeOthers: '关闭其他标签页',
closeRight: '关闭右侧标签页',
reopenLast: '恢复上次关闭的标签页',
errorCannotFetchFromRemote: '无法从远程服务器({0})获取内容。'
},
zh_tw: {
reload: '重新加載',
close: '關閉',
closeOthers: '關閉其他標籤頁',
closeRight: '關閉右側標籤頁',
reopenLast: '恢復上次關閉的標籤頁',
errorCannotFetchFromRemote: '無法從遠程服務器({0})獲取內容。'
},
en: {
reload: 'Reload',
close: 'Close',
closeOthers: 'Close others',
closeRight: 'Close right',
reopenLast: 'Reopen last',
errorCannotFetchFromRemote: 'Cannot fetch data from remote server {0}.'
}
};
// The tabs model class
var Tabs = function(element, options) {
var that = this;
that.name = NAME;
that.$ = $(element);
options = that.options = $.extend({}, DEFAULTS, this.$.data(), options);
var lang = options.lang || 'zh_cn';
that.lang = $.isPlainObject(lang) ? ($.extend(true, {}, LANG[lang.lang || $.zui.clientLang()], lang)) : LANG[lang];
// Initialize here
var $navbar = that.$.find('.tabs-navbar');
if (!$navbar.length) {
$navbar = $(options.navTemplate).appendTo(that.$);
}
that.$navbar = $navbar;
var $nav = $navbar.find('.tabs-nav');
if (!$nav.length) {
$nav = $('<ul class="tabs-nav nav nav-tabs"></ul>').appendTo($navbar);
}
that.$nav = $nav;
var $tabs = that.$.find('.tabs-container');
if (!$tabs.length) {
$tabs = $(options.containerTemplate).appendTo(that.$);
}
that.$tabs = $tabs;
that.activeTabId = options.defaultTab;
var tabs = options.tabs || [];
that.tabs = {};
$.each(tabs, function(index, item) {
var tab = Tab.create(item);
that.tabs[tab.id] = tab;
if (!that.activeTabId) {
that.activeTabId = tab.id;
}
that.renderTab(tab);
});
that.closedTabs = [];
that.open(that.getActiveTab());
$nav.on('click.' + NAME, '.tab-nav-link', function () {
that.open(that.getTab($(this).data('id')));
}).on('click.' + NAME, '.tab-nav-close', function (e) {
that.close($(this).closest('.tab-nav-link').data('id'));
e.stopPropagation();
}).on('resize.' + NAME, function () {
that.adjustNavs();
});
if (options.contextMenu) {
$nav.contextmenu({
selector: '.tab-nav-link',
itemsCreator: function (e) {
return that.createMenuItems(that.getTab($(this).data('id')));
},
onShow: function () {
that.$.addClass('tabs-show-contextmenu');
},
onHide: function () {
that.$.removeClass('tabs-show-contextmenu');
}
});
}
};
Tabs.prototype.createMenuItems = function (tab) {
var that = this;
var lang = that.lang;
return [{
label: lang.reload,
onClick: function () {
that.open(tab, true);
}
}, '-', {
label: lang.close,
disabled: tab.forbidClose,
onClick: function () {
that.close(tab.id);
}
}, {
label: lang.closeOthers,
disabled: that.$nav.find('.tab-nav-item:not(.hidden)').length <= 1,
onClick: function () {
that.closeOthers(tab.id);
}
}, {
label: lang.closeRight,
disabled: !$('#tab-nav-item-' + tab.id).next('.tab-nav-item:not(.hidden)').length,
onClick: function () {
that.closeRight(tab.id);
}
}, '-', {
label: lang.reopenLast,
disabled: !that.closedTabs.length,
onClick: function () {
that.reopen();
}
}];
};
Tabs.prototype.adjustNavs = function (immediately) {
var that = this;
if (!immediately) {
if (that.adjustNavsTimer) {
clearTimeout(that.adjustNavsTimer);
}
that.adjustNavsTimer = setTimeout(function() {
that.adjustNavs(true);
}, 50);
return;
}
if (that.adjustNavsTimer) {
that.adjustNavsTimer = null;
}
var $nav = that.$nav;
var $navItems = $nav.find('.tab-nav-item:not(.hidden)');
var totalWidth = $nav.width();
var totalCount = $navItems.length;
var maxWidth = Math.floor(totalWidth/totalCount);
if(maxWidth < 96) {
maxWidth = Math.floor((totalWidth-96)/(totalCount-1))
}
$nav.toggleClass('tab-nav-condensed', maxWidth <= 50);
$navItems.css('max-width', maxWidth);
};
Tabs.prototype.renderTab = function(tab, beforeTabId) {
var that = this;
var $nav = that.$nav;
var $tabNav = $('#tab-nav-item-' + tab.id);
if (!$tabNav.length) {
var $a = $('<a class="tab-nav-link"><i class="icon"></i><span class="title"></span><i class="close tab-nav-close" title="' + that.lang.close + '">&times;</i></a>').attr({
href: '#tabs-item-' + tab.id,
'data-id': tab.id
});
$tabNav = $('<li class="tab-nav-item" data-id="' + tab.id + '" id="tab-nav-item-' + tab.id + '" />').append($a).appendTo(that.$nav);
if (beforeTabId) {
var $before$nav = $('#tab-nav-item-' + beforeTabId);
if ($before$nav.length) {
$tabNav.insertAfter($before$nav);
}
}
that.adjustNavs();
}
var $a = $tabNav.find('a').attr('title', tab.desc).toggleClass('not-closable', !!tab.forbidClose);
$a.find('.icon').attr('class', 'icon ' + (tab.icon || that.options.defaultTabIcon));
$a.find('.title').text(tab.title || tab.defaultTitle || '');
return $tabNav;
};
Tabs.prototype.getActiveTab = function() {
var that = this;
return that.activeTabId ? that.tabs[that.activeTabId] : null;
};
Tabs.prototype.getTab = function(tabId) {
var that = this;
if (!tabId) {
return that.getActiveTab();
}
if (typeof tabId === 'object') {
tabId = tabId.id;
}
return that.tabs[tabId];
};
Tabs.prototype.close = function(tabId, forceClose) {
var that = this;
var tab = that.getTab(tabId);
if (tab && (forceClose || !tab.forbidClose)) {
$('#tab-nav-item-' + tab.id).remove();
$('#tab-' + tab.id).remove();
tab.close();
delete that.tabs[tab.id];
that.closedTabs.push(tab);
that.$.callComEvent(that, 'onClose', tab);
var lastTab;
$.each(that.tabs, function (tabId, tab) {
if (!lastTab || lastTab.openTime < tab.openTime) {
lastTab = tab;
}
});
lastTab && that.open(lastTab);
}
};
Tabs.prototype.open = function(tab, forceReload) {
var that = this;
if (!(tab instanceof Tab)) {
tab = Tab.create(tab);
}
var $tabNav = that.renderTab(tab);
that.$nav.find('.tab-nav-item.active').removeClass('active');
$tabNav.addClass('active');
var $tabPane = $('#tab-' + tab.id);
if (!$tabPane.length) {
$tabPane = $('<div class="tab-pane" id="tab-' + tab.id + '" />').appendTo(that.$tabs);
}
that.$tabs.find('.tab-pane.active').removeClass('active');
$tabPane.addClass('active');
tab.open();
that.activeTabId = tab.id;
that.tabs[tab.id] = tab;
if (forceReload || !tab.loaded) {
that.reload(tab);
}
that.$.callComEvent(that, 'onOpen', tab);
};
Tabs.prototype.showMessage = function (message, type) {
$.zui.messager.show(message, $.extend({
placement: 'center'
}, this.options.messagerOptions, {
type: type
}));
};
Tabs.prototype.reload = function(tab) {
var that = this;
if (typeof tab === 'string') {
tab = that.getTab(tab);
} else if (!tab) {
tab = that.getActiveTab();
}
if (!tab) {
return;
}
if (!tab.openTime) {
return that.open(tab);
}
var $tabNav = $('#tab-nav-item-' + tab.id).addClass('loading').removeClass('has-error');
var $tabPane = $('#tab-' + tab.id).addClass('loading').removeClass('has-error');
var afterRefresh = function (content, error) {
if (!tab.openTime) {
return;
}
$tabNav.removeClass('loading');
$tabPane.removeClass('loading');
that.$.callComEvent(that, 'onLoad', tab);
if(typeof content === 'string' || content instanceof $) {
if (tab.contentConverter) {
content = tab.contentConverter(content, tab);
}
$tabPane.empty().append(content);
if (!tab.title) {
content = $tabPane.text().replace(/\n/g, '');
tab.title = content.length > 10 ? content.substr(0, 10) : content;
that.renderTab(tab);
}
}
if (error) {
$tabNav.addClass('has-error');
$tabPane.addClass('has-error');
var showMessage = that.options.showMessage;
if (showMessage) {
if ($.isFunction(showMessage)) {
error = showMessage(error);
}
that.showMessage(error, 'danger');
}
if (!content) {
$tabPane.html(that.options.errorTemplate.format(error));
}
}
tab.loaded = new Date().getTime();
};
if (tab.type === 'ajax') {
var ajaxOption = {
type: 'get',
url: tab.url,
error: function(jqXHR, textStatus, errorThrown) {
afterRefresh(false, that.lang.errorCannotFetchFromRemote.format(tab.url));
},
success: function(data) {
afterRefresh(data);
}
};
if($.isPlainObject(tab.ajax)) {
ajaxOption = $.extend(ajaxOption, tab.ajax);
}
$.ajax(ajaxOption);
} else if (tab.type === 'iframe') {
try {
var iframeName = 'tab-iframe-' + tab.id;
var $iframe = $('<iframe id="' + iframeName + '" name="' + iframeName + '" src="' + (tab.url) + '" frameborder="no" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true" allowtransparency="true" scrolling="auto" style="width: 100%; height: 100%; left: 0px;"></iframe>');
$iframe.appendTo($tabPane.empty());
$('<div class="tab-iframe-cover" />').appendTo($tabPane);
var frame = document.getElementById(iframeName);
frame.onload = frame.onreadystatechange = function() {
if(this.readyState && this.readyState != 'complete') return;
afterRefresh();
var contentDocument = frame.contentDocument;
if (contentDocument && !tab.title) {
tab.title = contentDocument.title;
that.renderTab(tab);
}
};
} catch (e) {
afterRefresh();
}
} else {
var content = tab.content || tab.custom;
if (typeof content === 'function') {
content = content(tab, afterRefresh, that);
if (content !== true) {
afterRefresh(content);
}
} else {
afterRefresh(content);
}
}
};
Tabs.prototype.closeOthers = function(tabId) {
var that = this;
that.$nav.find('.tab-nav-link:not(.hidden)').each(function() {
var thisTabId = $(this).data('id');
if (thisTabId !== tabId) {
that.close(thisTabId);
}
});
};
Tabs.prototype.closeRight = function(tabId) {
var $tabNav = $('#tab-nav-item-' + tabId);
var $rightNav = $tabNav.next('.tab-nav-item:not(.hidden)');
while ($rightNav.length) {
this.close($rightNav.data('id'));
$rightNav = $tabNav.next('.tab-nav-item:not(.hidden)');
}
};
Tabs.prototype.closeAll = function() {
var that = this;
that.$nav.find('.tab-nav-link:not(.hidden)').each(function() {
that.close($(this).data('id'));
});
};
Tabs.prototype.reopen = function() {
var that = this;
if(that.closedTabs.length) {
that.open(that.closedTabs.pop());
}
};
// Extense jquery element
$.fn.tabs = function(option) {
return this.each(function() {
var $this = $(this);
var data = $this.data(NAME);
var options = typeof option == 'object' && option;
if(!data) $this.data(NAME, (data = new Tabs(this, options)));
if(typeof option == 'string') data[option]();
});
};
Tabs.NAME = NAME;
$.fn.tabs.Constructor = Tabs;
}(jQuery));

View File

@@ -0,0 +1,6 @@
/*!
* ZUI: 标签页管理器 - v1.8.1 - 2018-01-18
* http://zui.sexy
* GitHub: https://github.com/easysoft/zui.git
* Copyright (c) 2018 cnezsoft.com; Licensed MIT
*/.tabs{position:relative;min-height:400px}.tabs-navbar{padding:4px 4px 0 4px}.tabs-nav{height:30px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border-bottom:none;border-bottom:1px solid #ddd}.tab-nav-item{width:160px;min-width:0;max-width:160px;padding-right:2px;margin-bottom:0;border:none}.tab-nav-item:hover{min-width:95px}.tab-nav-link{position:relative;height:30px;margin:0;overflow:hidden;background-color:rgba(255,255,255,.65);background-color:#e5e5e5;border-color:#ddd;border-bottom:none;border-radius:2px 2px 0 0}.tab-nav-link>.title{position:absolute;top:5px;right:5px;left:30px;display:block;overflow:hidden;font-size:14px;line-height:20px;text-overflow:ellipsis;white-space:nowrap}.tab-nav-link>.icon{position:absolute;top:5px;left:5px;display:block;width:20px;height:20px;line-height:20px;text-align:center;opacity:.8}.tab-nav-item.loading .tab-nav-link>.icon:before{content:'\e97b';-webkit-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}.tab-nav-link>.close{position:absolute;top:5px;right:5px;width:20px;height:20px;font-weight:200;line-height:16px;text-align:center;text-shadow:none;visibility:hidden;border-radius:4px;opacity:0;-webkit-transition:all .2s;-o-transition:all .2s;transition:all .2s}.tab-nav-link>.close:hover{color:#fff;background-color:#ea644a}.tab-nav-link:hover>.title{right:25px}.tab-nav-link:hover>.close{visibility:visible;opacity:1}.tab-nav-link.not-closable>.close{display:none}.nav-tabs.tabs-nav>li>a,.nav-tabs.tabs-nav>li>a:focus,.nav-tabs.tabs-nav>li>a:hover{border-color:#ddd #ddd transparent #ddd}.tab-nav-condensed .tab-nav-link>.title{left:5px;text-overflow:initial}.tab-nav-condensed .tab-nav-link>.icon{display:none}.tabs-container{position:absolute;top:34px;right:0;bottom:0;left:0}.tabs-container>.tab-pane{position:absolute;top:0;right:0;bottom:0;left:0;display:none}.tabs-container>.tab-pane.active{display:block}.tab-iframe-cover{display:none}.tabs-show-contextmenu .tab-iframe-cover{position:absolute;top:0;right:0;bottom:0;left:0;display:block}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,26 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>hello</title>
</head>
<body>
<div id="app">fasfasfasfa艾斯德斯大所大所大所多撒多撒多撒多</div>
</body>
<script>
</script>
<style>
.reason {
color: #f00;
font-size: 12px;
}
</style>
</html>

View File

@@ -0,0 +1,80 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>登录</title>
<link rel="stylesheet" type="text/css" href="../lib/mzui/css/mzui.min.css">
</head>
<body>
<div id="app">
<div class="page fade scale-from-center display in" style="overflow: hidden">
<div class="dock blur-lg" style="background: url('../lib/mzui/img/loginBg.jpg') no-repeat center; background-size: cover; top: -2rem; right: -2rem; bottom: -2rem; left: -2rem"></div>
<div class="dock flex flex-center">
<div class="modal rounded" style="width: 18rem; height: 10rem; margin: auto;">
<div class="heading divider primary-pale">
<div class="title">登录 <span class="reason"> 您没有权限访问该内容或需要登录</span></div>
</div>
<form action="/login" method="post">
<div class="content box">
<div class="control has-label-left"><!-- has-error -->
<input type="text" name="username" class="input" v-model="userId" placeholder="用户名">
<label for="account"><i class="icon-user"></i></label>
<div class="help-text" v-if="errorInfo.length > 0">{{errorInfo}}</div>
</div>
<div class="control has-label-left">
<input type="password" name="password" v-model="password" class="input" placeholder="密码">
<input type="hidden" name="validateCode" value="1234">
<label for="account"><i class="icon-key"></i></label>
</div>
<div class="control">
<button type="submit" v-on:click="loginSubmit1" class="btn block primary">登录</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</body>
<script src="../lib/jquery/jquery-3.1.0.min.js"></script>
<script src="../lib/mzui/js/mzui.min.js"></script>
<script src="../lib/vue/vue.js"></script>
<script src="../lib/mg/js/common.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
userId: "",
password: "",
errorInfo: ""
},
methods: {
loginSubmit: function() {
var param = {
username: app.userId,
password: app.password,
validateCode: "1234"
};
post("/login", param, function(result) {
if(result.errCode == 200) {
//location.href = "/manage/web/home";
alert("登录失败1" + result.errMsg);
} else {
alert("登录失败," + result.errMsg);
}
});
}
}
});
</script>
<style>
.reason{color: #f00;font-size: 12px;}
</style>
</html>

View File

@@ -13,6 +13,8 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
@@ -43,6 +45,8 @@ import springfox.documentation.swagger.web.SwaggerResource;
@RequestMapping("/swagger-mg-ui/document")
public class MgDocumentController {
private static Logger logger = LoggerFactory.getLogger(MgDocumentController.class);
@Autowired(required = false)
private MgStorageService storageService;
@@ -144,7 +148,7 @@ public class MgDocumentController {
String resourcesStr = HttpRequest.get(resourcesUrl).timeout(3000).execute().body();
resourceList = JSON.parseArray(resourcesStr, SwaggerResource.class);
} catch (Exception e) {
e.printStackTrace();
logger.error("获取文档失败:{}{}", resourcesUrl, e.getMessage());
}
if (resourceList == null || resourceList.isEmpty()) {
continue;
@@ -183,7 +187,7 @@ public class MgDocumentController {
+ resourceStr;
swaggerResourceStrList.add(resourceStr);
} catch (Exception e) {
e.printStackTrace();
logger.error("获取文档失败:{}{}", location, e.getMessage());
}
}
}
@@ -245,7 +249,7 @@ public class MgDocumentController {
}
resourcesSet.add(resourcesUrl);
} catch (Exception e) {
e.printStackTrace();
logger.error("获取文档失败:{}{}", resourcesUrl, e.getMessage());
return MgUiResponseJson.warn("改地址查找文档失败");
}
storageService.put(StorageKeys.SWAGGER_RESOURCES_LIST, JSON.toJSONString(resourcesSet));

View File

@@ -25,7 +25,7 @@ public class MgStorageController {
@PostMapping(value = "/checkConfig")
public MgUiResponseJson checkConfig() {
// 本接口能访问而且实现了MgStorageService才算配置好了
// 本接口能访问而且实现了MgStorageService才算配置好了
if (storageService == null) {
return MgUiResponseJson.error("服务不可用");
}
@@ -43,6 +43,19 @@ public class MgStorageController {
storageService.put(key, value);
return MgUiResponseJson.ok();
}
@PostMapping(value = "/delete")
public MgUiResponseJson delete(String key) {
if (storageService == null) {
return MgUiResponseJson.warn(Toast.AUTOWIRED_ERROR);
}
if (key == null) {
return MgUiResponseJson.warn("参数名不能为空");
}
String value = storageService.get(key);
value = (value == null) ? "" : value;
return MgUiResponseJson.ok(value);
}
@GetMapping(value = "/data")
public MgUiResponseJson getData(String key) {

View File

@@ -25,4 +25,12 @@ public interface MgStorageService {
*/
void put(String key, String value);
/**
* 删除数据
* @author 暮光:城中城
* @since 2018年8月19日
* @param key
*/
void remove(String key);
}

View File

@@ -96,97 +96,46 @@ $(document).ready(function(){
paramSendToServer.header = JSON.stringify(requestHeaderStore);
//console.log(paramBodySend);
var beforSendTime = new Date().getTime();
if(serverStorage) {
paramSendToServer.url = postUrl;
paramSendToServer.method = options;
ajaxTemp("swagger-mg-ui/http/request", "post", "json", paramSendToServer, function(result){
//console.log(result);
setStorage('p-request-obj-' + docUrl, storeRequestParam);
var afterSendTime = new Date().getTime();
$("#httpRequestStatus").text(result.status);
$("#httpRequestTime").text((afterSendTime - beforSendTime) + "ms");
try {
var htmlStr = Formatjson.processObjectToHtmlPre(JSON.parse(result.data), 0, false, false, false, false);
$("#responseBodyJsonDiv").html(htmlStr);
} catch (e) {
$("#responseBodyJsonDiv").html("<iframe id='responseBodyJsonIframe'></iframe>");
setTimeout(function(){
$("#responseBodyJsonIframe").contents().find("body").html(result.data);
}, 300);
}
$("#tabResponseHeader table tbody").empty();
$("#tabResponseCookie table tbody").empty();
var headers = result.header||[];
for (var i = 0; i < headers.length; i++) {
var name = getNotEmptyStr(headers[i].name);
var value = getNotEmptyStr(headers[i].value);
$("#tabResponseHeader table tbody").append(
'<tr>'+'<td>'+name+'</td>' + '<td>'+value+'</td>'+'</tr>'
);
}
var cookies = result.cookie||[];
for (var i = 0; i < cookies.length; i++) {
var name = getNotEmptyStr(cookies[i].name);
var value = getNotEmptyStr(cookies[i].value);
$("#tabResponseCookie table tbody").append(
'<tr>'+'<td>'+name+'</td>' + '<td>'+value+'</td>'+'</tr>'
);
}
}, function(){
Toast.error("请求失败!");
}, function(){
$(".send-request .icon").addClass("hide");
});
} else {
$.ajax({
url : postUrl,
sync : false,
type : options, // 数据发送方式
dataType : "JSON", // 接受数据格式
data : paramBodySend,//requestParamForm,
contentType : "application/x-www-form-urlencoded; charset=UTF-8",
beforeSend : function(request) {
Object.keys(requestHeaderStore).forEach(function(key){
request.setRequestHeader(key, requestHeaderStore[key]);
});
},
success : function(data, status, xhr) {
},
complete : function(xhr) {
//console.log(xhr);
setStorage('p-request-obj-' + docUrl, storeRequestParam);
$(".send-request .icon").addClass("hide");
var afterSendTime = new Date().getTime();
$("#httpRequestStatus").text(xhr.status + "-" + xhr.statusText);
$("#httpRequestTime").text((afterSendTime - beforSendTime) + "ms");
try {
var htmlStr = Formatjson.processObjectToHtmlPre(JSON.parse(xhr.responseText), 0, false, false, false, false);
$("#responseBodyJsonDiv").html(htmlStr);
} catch (e) {
$("#responseBodyJsonDiv").html("<iframe id='responseBodyJsonIframe'></iframe>");
setTimeout(function(){
$("#responseBodyJsonIframe").contents().find("body").html(xhr.responseText);
}, 300);
}
var allHeaders = xhr.getAllResponseHeaders();
var headers = allHeaders.split("\r\n");
$("#tabResponseHeader table tbody").empty();
$("#tabResponseCookie table tbody").empty();
for (var i = 0; i < headers.length; i++) {
if(isEmpty(headers[i])){
continue;
}
var headerArr = headers[i].split(":");
$("#tabResponseHeader table tbody").append(
'<tr>'+'<td>'+headerArr[0]+'</td>' + '<td>'+headerArr[1]+'</td>'+'</tr>'
);
}
},
error : function(data) {
}
});
}
paramSendToServer.url = postUrl;
paramSendToServer.method = options;
ajaxTemp("swagger-mg-ui/http/request", "post", "json", paramSendToServer, function(result){
//console.log(result);
setStorage('p-request-obj-' + docUrl, storeRequestParam);
var afterSendTime = new Date().getTime();
$("#httpRequestStatus").text(result.status);
$("#httpRequestTime").text((afterSendTime - beforSendTime) + "ms");
try {
var htmlStr = Formatjson.processObjectToHtmlPre(JSON.parse(result.data), 0, false, false, false, false);
$("#responseBodyJsonDiv").html(htmlStr);
} catch (e) {
$("#responseBodyJsonDiv").html("<iframe id='responseBodyJsonIframe'></iframe>");
setTimeout(function(){
$("#responseBodyJsonIframe").contents().find("body").html(result.data);
}, 300);
}
$("#tabResponseHeader table tbody").empty();
$("#tabResponseCookie table tbody").empty();
var headers = result.header||[];
for (var i = 0; i < headers.length; i++) {
var name = getNotEmptyStr(headers[i].name);
var value = getNotEmptyStr(headers[i].value);
$("#tabResponseHeader table tbody").append(
'<tr>'+'<td>'+name+'</td>' + '<td>'+value+'</td>'+'</tr>'
);
}
var cookies = result.cookie||[];
for (var i = 0; i < cookies.length; i++) {
var name = getNotEmptyStr(cookies[i].name);
var value = getNotEmptyStr(cookies[i].value);
$("#tabResponseCookie table tbody").append(
'<tr>'+'<td>'+name+'</td>' + '<td>'+value+'</td>'+'</tr>'
);
}
}, function(){
Toast.error("请求失败!");
}, function(){
$(".send-request .icon").addClass("hide");
});
});
/**
* 输入框输入之后,如果是最后一行则在增加一行
@@ -259,10 +208,6 @@ $(document).ready(function(){
* 提交模拟返回值
*/
$("#simulationResultSubmit").click(function(){
if(!serverStorage) {
Toast.error("没有开启服务器端存储模拟返回是无效的");
return;
}
var value = $("#simulationResultText").val();
value = getNotEmptyStr(value, "");
var docUrl = $("#simulationResultUrl").text();
@@ -276,10 +221,6 @@ $(document).ready(function(){
* 获取模拟返回值
*/
$("#simulationResultGet").click(function(){
if(!serverStorage) {
Toast.error("没有开启服务器端存储模拟返回是无效的");
return;
}
var docUrl = $("#simulationResultUrl").text();
getStorage('p-simulation-response-' + docUrl, function(data){
$("#simulationResultText").val(data);

View File

@@ -13,8 +13,6 @@ var definitionsDataMap = new Map();
var treePathDataMap = new Map();
var globalLoadingMessager;
// 服务器端存储能力是否开启
var serverStorage = false;
// 树的下表
var projectTreeIdIndex = 1;
// 文档url加载的下标
@@ -60,57 +58,20 @@ $(document).ready(function(){
}, function(msg){
}, function(xhr){
showGlobalLoadingMessage('服务检查完成,请稍候...', true);
var serverStorage = false;
if(!isEmptyObject(xhr.responseJSON)) {
serverStorage = (xhr.responseJSON.errCode == 200);
}
if(!serverStorage) {
console.warn("服务器端存储能力配置有误,仅能使用浏览器存储,建议配置好服务器端存储能力" +
"\n请参考https://gitee.com/zyplayer/swagger-mg-ui-demo");
Toast.error("服务器端能力配置有误,新版本必须开启才能使用", 999999);
documentLoadFinish();
} else {
initUserSettings();
}
initUserSettings();
}
);
});
/**
* 增加文档
* @returns
*/
function addDocumentByUrl(fullUrl, isInSetting) {
// 获取原始的swagger的json对象
ajaxTemp(fullUrl, "get", "json", {}, function(json){
console.log(json);
if(isEmptyObject(json) || isEmpty(json.swagger)) {
Toast.error("获取文档错误,请检查:" + fullUrl);
return
}
// 拼接地址
json.fullUrl = fullUrl;
var v2Index = fullUrl.indexOf("/v2/api-docs");
if(v2Index > 0) {
var domainUrl = fullUrl.substring(0, v2Index + 1);
json.domainUrl = domainUrl;
}
documentJsonArr.push(json);// 加到所有文档
addHomePageDashboard(json, fullUrl);
createDefinitionsMapByJson(json);
if(userSettings.catalogShowType == 1) {
createTreeViewByTree(json);// url分成一层一层的展示
} else if(userSettings.catalogShowType == 2){
createTreeViewByTag(json);// tag方式整个url显示为一层
} else {
createTreeViewByTree(json);// url分成一层一层的展示
}
}, function(msg){
Toast.error("获取文档失败,请检查:" + fullUrl);
}, function(msg){
projectLoadingIndex--;
if(projectLoadingIndex == 0) {
documentLoadFinish();
}
});
}
/**
* 获取所有文档列表提供选择
* @returns
@@ -167,67 +128,6 @@ function addDocumentByService(choiseDocList) {
});
}
/**
* 增加文档
* @returns
*/
function loadSwaggerResources(fullUrl, isInSetting) {
// 获取原始的swagger的resources配置
ajaxTemp(fullUrl, "get", "json", {}, function(json){
//console.log(json);
if(isEmptyObject(json) || json.length <= 0) {
Toast.error("获取文档错误,请检查:" + fullUrl);
return;
}
if(!isInSetting) {
if(!haveString(userSettings.projects, fullUrl)) {
userSettings.projects.push(fullUrl);
}
storeUserSettings();
document.location.reload();
}
var removedProjects = userSettings.removedProjects;
if(removedProjects == null || removedProjects == undefined) {
removedProjects = [];
}
// 将http://192.168.5.172:8081/swagger-resources
// 变成http://192.168.5.172:8081/v2/api-docs
var locationHref = fullUrl.substring(0, fullUrl.lastIndexOf("/"));
for (var i = 0; i < json.length; i++) {
var tempLocation = locationHref + json[i].location;
// 如果是新加的,判断在删除的数组里面,则从删除数组中移除,新的开始
if(!isInSetting) {
for (var j = 0; j < removedProjects.length; j++) {
if(removedProjects[j] == tempLocation) {
removedProjects[j] = "";
}
}
}
// 不存在则添加
if(!haveString(swaggerApiDocsArr, tempLocation)) {
swaggerApiDocsArr.push(tempLocation);
}
}
// 去掉被删除的路劲
var removedProjectsNew = [];
for (var i = 0; i < removedProjects.length; i++) {
if(isNotEmpty(removedProjects[i])) {
removedProjectsNew.push(removedProjects[i]);
}
}
userSettings.removedProjects = removedProjectsNew;
storeUserSettings();
}, function(msg){
Toast.error("获取文档失败,请检查:" + fullUrl);
}, function(msg){
projectLoadingIndex--;
showGlobalLoadingMessage('剩余'+projectLoadingIndex+'份文档,请稍候...', true);
if(projectLoadingIndex == 0) {
loadSwaggerResourcesFinish();
}
});
}
/**
* 自由拖动改变左右框架的宽度
*/
@@ -424,18 +324,7 @@ $("#choiseDocBtn").click(function(){
}
allDocListObj.push(tempUrl);
});
if(serverStorage) {
addDocumentByService(choiseDocList);
} else {
if(choiseDocListObj.length <= 0) {
choiseDocListObj = allDocListObj;
}
// 请求url获取文档配置增加树形菜单等
projectLoadingIndex = choiseDocListObj.length;
for (var i = 0; i < choiseDocListObj.length; i++) {
addDocumentByUrl(choiseDocListObj[i]);
}
}
addDocumentByService(choiseDocList);
$('#choiseDocModal').modal('hide');
});
@@ -448,16 +337,11 @@ $("#addNewDocumentBtn").click(function(){
Toast.error("地址不可以为空");return;
}
projectLoadingIndex = 1;
if(serverStorage) {
ajaxTemp("swagger-mg-ui/document/addSwaggerResources", "post", "json", {resourcesUrl: addNewDocumentInput}, function(json){
if(validateResult(json)) {
document.location.reload();
}
});
} else {
loadSwaggerResources(addNewDocumentInput, false);
$('#addNewDocumentModal').modal('hide');
}
ajaxTemp("swagger-mg-ui/document/addSwaggerResources", "post", "json", {resourcesUrl: addNewDocumentInput}, function(json){
if(validateResult(json)) {
document.location.reload();
}
});
});
/**
@@ -1104,23 +988,11 @@ function documentLoadFinish() {
// 被移除
afterPanelRemoved:function(id){
//console.log(id);
if(serverStorage) {
ajaxTemp("swagger-mg-ui/document/deleteSwaggerDoc", "post", "json", {docUrl: id}, function(json){
if(validateResult(json)) {
document.location.reload();
}
});
} else {
var tempProjects = [], nowIndex = 0;
for ( var i = 0; i < userSettings.projects.length; i++){
if(userSettings.projects[i] != id) {
tempProjects[nowIndex++] = userSettings.projects[i];
}
ajaxTemp("swagger-mg-ui/document/deleteSwaggerDoc", "post", "json", {docUrl: id}, function(json){
if(validateResult(json)) {
document.location.reload();
}
userSettings.projects = tempProjects;
userSettings.removedProjects.push(id);
storeUserSettings();
}
});
},
});
}
@@ -1136,9 +1008,7 @@ function updateUserSettingsUi() {
$("input[name='showParamType'][value='"+userSettings.showParamType+"']").prop("checked",true);
$("input[name='onlyUseLastParam'][value='"+userSettings.onlyUseLastParam+"']").prop("checked",true);
$("input[name='autoFillParam'][value='"+userSettings.autoFillParam+"']").prop("checked",true);
if(!serverStorage) {
$(".local-storage").show();// 服务器存储了就不用管理了
}
//$(".local-storage").show();// 服务器存储了就不用管理了
}
/**
@@ -1181,65 +1051,45 @@ function storeUserSettings() {
* 获取数据,异步的操作
*/
function getStorage(key, success, fail) {
if(serverStorage) {
ajaxTemp("swagger-mg-ui/storage/data", "get", "json", {key: key}, function(json){
if(json.errCode == 200) {
if(typeof success == "function") {
var result = deserialize(json.data);
success(result);
}
} else {
if(typeof fail == "function") {
fail();
}
ajaxTemp("swagger-mg-ui/storage/data", "get", "json", {key: key}, function(json){
if(json.errCode == 200) {
if(typeof success == "function") {
var result = deserialize(json.data);
success(result);
}
}, function(msg){
} else {
if(typeof fail == "function") {
fail();
}
});
} else {
var value = $.zui.store.get(key);
if(typeof success == "function") {
success(value);
}
}
}, function(msg){
if(typeof fail == "function") {
fail();
}
});
}
/**
* 存储数据,异步的操作
*/
function setStorage(key, value, success, fail) {
if(serverStorage) {
value = $.zui.store.serialize(value);
ajaxTemp("swagger-mg-ui/storage/data", "post", "json", {key: key, value: value}, function(json){
if(json.errCode == 200) {
if(typeof success == "function") {
success();
}
} else {
if(typeof fail == "function") {
fail(getNotEmptyStr(json.errMsg));
}
value = $.zui.store.serialize(value);
ajaxTemp("swagger-mg-ui/storage/data", "post", "json", {key: key, value: value}, function(json){
if(json.errCode == 200) {
if(typeof success == "function") {
success();
}
}, function(msg){
} else {
if(typeof fail == "function") {
fail("");
fail(getNotEmptyStr(json.errMsg));
}
console.log("存储数据到服务器失败,请检查");
});
} else {
$.zui.store.set(key, value);
}
}
/**
* 初始化用户的设置--通过服务器数据
* @param
* @returns
*/
function initUserSettingsByServer() {
}
}, function(msg){
if(typeof fail == "function") {
fail("");
}
console.log("存储数据到服务器失败,请检查");
});
}
/**
@@ -1257,25 +1107,7 @@ function initUserSettings() {
updateTreeShowType();
updateUserSettingsUi();
// 增加文档
if(serverStorage) {
getDocumentListByService();
} else {
var projects = userSettings.projects;
if(isEmptyObject(projects) || projects.length <= 0) {
// 没有文档时默认本项目的文档
userSettings.projects = [];
var locationHref = document.location.href;
locationHref = locationHref.substring(0, locationHref.lastIndexOf("/"));
projectLoadingIndex = 1;
loadSwaggerResources(locationHref + "/swagger-resources", false);
} else {
projectLoadingIndex = projects.length;
for ( var i = 0; i < projects.length; i++){
// 请求url获取文档配置增加树形菜单等
loadSwaggerResources(projects[i], true);
}
}
}
getDocumentListByService();
});
}
@@ -1286,24 +1118,3 @@ function showGlobalLoadingMessage(text, loading) {
globalLoadingMessager.$.find(".messager-content").html(text);
}
function loadSwaggerResourcesFinish() {
projectLoadingIndex = swaggerApiDocsArr.length;
if (projectLoadingIndex <= 0) {
documentLoadFinish();
} else {
if(swaggerApiDocsArr.length > 1) {
showGlobalLoadingMessage('等待选择需展示的文档,请选择...', true);
for (var i = 0; i < swaggerApiDocsArr.length; i++) {
var item = swaggerApiDocsArr[i];
$("#choiseDocListUl").append('<li value="'+item+'">'+item+'</li>');
}
$('#choiseDocModal').modal({moveable:true, backdrop:'static', keyboard: false});
} else {
for ( var i = 0; i < swaggerApiDocsArr.length; i++){
// 请求url获取文档配置增加树形菜单等
addDocumentByUrl(swaggerApiDocsArr[i]);
}
}
swaggerApiDocsArr = [];
}
}