| @ -1,34 +1,32 @@ | ||||
| * [首页](/?t=1565916799573) | ||||
| * [首页](/?t=1567561041568) | ||||
| * 开发文档 | ||||
|   * [快速体验](files/10010_快速体验.md?t=1565916799577) | ||||
|   * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1565916799596) | ||||
|   * [新增接口](files/10020_新增接口.md?t=1565916799596) | ||||
|   * [业务参数校验](files/10030_业务参数校验.md?t=1565916799596) | ||||
|   * [错误处理](files/10040_错误处理.md?t=1565916799596) | ||||
|   * [编写文档](files/10041_编写文档.md?t=1565916799596) | ||||
|   * [接口交互详解](files/10050_接口交互详解.md?t=1565916799597) | ||||
|   * [easyopen支持](files/10070_easyopen支持.md?t=1565916799597) | ||||
|   * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1565916799597) | ||||
|   * [ISV管理](files/10085_ISV管理.md?t=1565916799597) | ||||
|   * [自定义路由](files/10086_自定义路由.md?t=1565916799597) | ||||
|   * [自定义返回结果](files/10087_自定义返回结果.md?t=1565916799597) | ||||
|   * [自定义过滤器](files/10088_自定义过滤器.md?t=1565916799597) | ||||
|   * [路由授权](files/10090_路由授权.md?t=1565916799598) | ||||
|   * [接口限流](files/10092_接口限流.md?t=1565916799598) | ||||
|   * [监控日志](files/10093_监控日志.md?t=1565916799598) | ||||
|   * [SDK开发](files/10095_SDK开发.md?t=1565916799598) | ||||
|   * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1565916799598) | ||||
|   * [应用授权](files/10097_应用授权.md?t=1565916799598) | ||||
|   * [传统web开发](files/10100_传统web开发.md?t=1565916799598) | ||||
|   * [文件上传](files/10104_文件上传.md?t=1565916799598) | ||||
|   * [nacos注册中心](files/10106_nacos注册中心.md?t=1565916799599) | ||||
|   * [扩展其它注册中心](files/10107_扩展其它注册中心.md?t=1565916799599) | ||||
|   * [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1565916799599) | ||||
|   * [预发布灰度发布](files/10110_预发布灰度发布.md?t=1565916799599) | ||||
|   * [动态修改请求参数](files/10111_动态修改请求参数.md?t=1565916799599) | ||||
|   * [快速体验](files/10010_快速体验.md?t=1567561041571) | ||||
|   * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1567561041592) | ||||
|   * [新增接口](files/10020_新增接口.md?t=1567561041592) | ||||
|   * [开发流程](files/10021_开发流程.md?t=1567561041592) | ||||
|   * [业务参数校验](files/10030_业务参数校验.md?t=1567561041592) | ||||
|   * [错误处理](files/10040_错误处理.md?t=1567561041592) | ||||
|   * [编写文档](files/10041_编写文档.md?t=1567561041592) | ||||
|   * [接口交互详解](files/10050_接口交互详解.md?t=1567561041593) | ||||
|   * [easyopen支持](files/10070_easyopen支持.md?t=1567561041593) | ||||
|   * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1567561041593) | ||||
|   * [ISV管理](files/10085_ISV管理.md?t=1567561041593) | ||||
|   * [自定义返回结果](files/10087_自定义返回结果.md?t=1567561041593) | ||||
|   * [自定义过滤器](files/10088_自定义过滤器.md?t=1567561041593) | ||||
|   * [路由授权](files/10090_路由授权.md?t=1567561041594) | ||||
|   * [接口限流](files/10092_接口限流.md?t=1567561041594) | ||||
|   * [监控日志](files/10093_监控日志.md?t=1567561041594) | ||||
|   * [SDK开发](files/10095_SDK开发.md?t=1567561041594) | ||||
|   * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1567561041594) | ||||
|   * [应用授权](files/10097_应用授权.md?t=1567561041594) | ||||
|   * [传统web开发](files/10100_传统web开发.md?t=1567561041594) | ||||
|   * [文件上传](files/10104_文件上传.md?t=1567561041594) | ||||
|   * [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1567561041594) | ||||
|   * [预发布灰度发布](files/10110_预发布灰度发布.md?t=1567561041595) | ||||
|   * [动态修改请求参数](files/10111_动态修改请求参数.md?t=1567561041595) | ||||
| * 原理分析 | ||||
|   * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1565916799599) | ||||
|   * [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1565916799599) | ||||
|   * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1565916799599) | ||||
|   * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1565916799600) | ||||
|   * [常见问题](files/90100_常见问题.md?t=1565916799600) | ||||
|   * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1567561041595) | ||||
|   * [原理分析之如何存储路由](files/90011_原理分析之如何存储路由.md?t=1567561041595) | ||||
|   * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1567561041595) | ||||
|   * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1567561041595) | ||||
|   * [常见问题](files/90100_常见问题.md?t=1567561041595) | ||||
|  | ||||
| @ -1,23 +0,0 @@ | ||||
| # 自定义路由 | ||||
| 
 | ||||
| 假设有一个非java开发的接口,比如php开发的接口,然后需要接入到SOP,使用接口名版本号进行路由跳转。 | ||||
| 
 | ||||
| 操作方式如下: | ||||
| 
 | ||||
| - 登录sop-admin,服务管理--路由管理 | ||||
| - 新建一个自定义服务:`php-service` | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| - 选中php-service,新建一个路由,输入接口名、版本号、uri | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| - 请求网关 | ||||
| 
 | ||||
| `http://localhost:8081/api?method=php.goods.list&version=1.0`会跳转到`http://www.xxx.com/api/listGoods.php` | ||||
| 
 | ||||
| 注意: | ||||
| 
 | ||||
| - php接口返回数据必须是json格式,返回其它内容可能会调用失败 | ||||
| - 只有自定义服务、路由可以删除 | ||||
| @ -1,90 +0,0 @@ | ||||
| # nacos注册中心 | ||||
| 
 | ||||
| 使用nacos作为注册中心,源码在`registry-nacos`分支 | ||||
| 
 | ||||
| 这里演示如何将默认的eureka注册中心替换成nacos,步骤如下: | ||||
| 
 | ||||
| - 准备工作 | ||||
| 
 | ||||
| 1.安装nacos,前往[最新稳定版本](https://github.com/alibaba/nacos/releases),下载最新版nacos | ||||
| 
 | ||||
| 2.启动nacos服务器,cd nacos/bin | ||||
| 
 | ||||
| Linux/Unix/Mac,启动命令(standalone代表着单机模式运行,非集群模式): | ||||
| 
 | ||||
| `sh startup.sh -m standalone` | ||||
| 
 | ||||
| Windows,启动命令: | ||||
| 
 | ||||
| `cmd startup.cmd` | ||||
| 
 | ||||
| 或者双击startup.cmd运行文件。  | ||||
| 
 | ||||
| 更多访问:https://nacos.io/zh-cn/docs/quick-start.html | ||||
| 
 | ||||
| - 微服务端修改 | ||||
| 
 | ||||
| 1.修改微服务应用pom,打开`sop-example/sop-story/sop-story-web/pom.xml`,注释eureka服务发现依赖,添加nacos服务发现依赖 | ||||
| 
 | ||||
| ```xml | ||||
| <!-- 注册中心【只能用一个,不用的注释掉】 --> | ||||
| <!-- 使用eureka注册中心 | ||||
| <dependency> | ||||
|     <groupId>org.springframework.cloud</groupId> | ||||
|     <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> | ||||
| </dependency> | ||||
| --> | ||||
| 
 | ||||
| <!-- 使用nacos注册中心 | ||||
|     版本 0.2.x.RELEASE 对应的是 Spring Boot 2.x 版本,版本 0.1.x.RELEASE 对应的是 Spring Boot 1.x 版本。 | ||||
|    https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-alibaba-nacos-discovery | ||||
| --> | ||||
| <dependency> | ||||
|     <groupId>org.springframework.cloud</groupId> | ||||
|     <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> | ||||
|     <version>0.2.2.RELEASE</version> | ||||
| </dependency> | ||||
| <!-- 注册中心end --> | ||||
| ``` | ||||
| 
 | ||||
| 2.yml文件新增nacos配置,并注释掉eureka相关配置 | ||||
| 
 | ||||
| ```yaml | ||||
| spring: | ||||
|   cloud: | ||||
|     # nacos注册中心,和eureka只能用一个 | ||||
|     nacos: | ||||
|       discovery: | ||||
|         server-addr: 127.0.0.1:8848 | ||||
| ``` | ||||
| 
 | ||||
| - 网关修改 | ||||
| 
 | ||||
| 找到`sop-gateway`工程,步骤同上 | ||||
| 
 | ||||
| - SOP-admin修改 | ||||
| 
 | ||||
| 
 | ||||
| 修改yml文件,设置nacos服务器地址,`registry.name`填nacos | ||||
| 
 | ||||
| ```yaml | ||||
| # 注册中心地址,根据实际情况改,这里只是参数,并不会去注册 | ||||
| registry: | ||||
|   eureka-server-addr: http://localhost:1111/eureka/ | ||||
|   # nacos服务器地址 | ||||
|   nacos-server-addr: 127.0.0.1:8848 | ||||
|   # 使用eureka,填:eureka,使用nacos填:nacos | ||||
|   name: nacos | ||||
| ``` | ||||
| 
 | ||||
| - website-server修改 | ||||
| 
 | ||||
| 步骤同`SOP-admin修改` | ||||
| 
 | ||||
| 如果要改成consul注册中心,可参照以上步骤。 | ||||
| 
 | ||||
| - 参考资料 | ||||
| 
 | ||||
| 1.[nacos介绍及安装](https://nacos.io/zh-cn/docs/quick-start.html) | ||||
| 
 | ||||
| 2.[nacos spring cloud注册发现](https://nacos.io/zh-cn/docs/quick-start-spring-cloud.html) | ||||
| @ -1,112 +0,0 @@ | ||||
| # 扩展其它注册中心 | ||||
| 
 | ||||
| **注: nacos注册中心已经实现,本篇以nacos为例介绍如何扩展,如果要改成consul,可按照此方式进行修改** | ||||
| 
 | ||||
| SOP默认使用eureka注册中心,如果要换成nacos注册中心,步骤如下: | ||||
| 
 | ||||
| - 实现`com.gitee.sop.registryapi.service.RegistryService`接口 | ||||
| 
 | ||||
| 1.找到`SOP/sop-common/sop-registry-api`工程,在service.impl包下新建一个类,实现RegistryService接口 | ||||
| 
 | ||||
| ```java | ||||
| public class RegistryServiceNacos implements RegistryService { | ||||
|      | ||||
|     @Override | ||||
|     public List<ServiceInfo> listAllService(int pageNo, int pageSize) throws Exception { | ||||
|         // TODO: 返回服务实例     | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onlineInstance(ServiceInstance serviceInstance) throws Exception { | ||||
|         // TODO: 实例上线 | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void offlineInstance(ServiceInstance serviceInstance) throws Exception { | ||||
|         // TODO: 实例下线 | ||||
|     } | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| 2.在`com.gitee.sop.registryapi.config.BaseRegistryConfig`中新增 | ||||
| 
 | ||||
| ```java | ||||
| /** | ||||
|  * 当配置了registry.name=nacos生效 | ||||
|  * | ||||
|  * @return | ||||
|  */ | ||||
| @Bean | ||||
| @ConditionalOnProperty(prefix = "registry", name = "name", havingValue = "nacos") | ||||
| RegistryService registryServiceNacos() { | ||||
|     return new RegistryServiceNacos(); | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| 其中`@ConditionalOnProperty(prefix = "registry", name = "name", havingValue = "nacos")` | ||||
| 表示`application.properties`配置了`registry.name=nacos`参数才能生效,registry.name=nacos下文会讲到。 | ||||
| 
 | ||||
| 
 | ||||
| - 微服务端修改 | ||||
| 
 | ||||
| 1.修改微服务应用pom.xml,注释eureka服务发现依赖,添加nacos服务发现依赖 | ||||
| 
 | ||||
| ```xml | ||||
| <!-- 注册中心【只能用一个,不用的注释掉】 --> | ||||
| <!-- 使用eureka注册中心 | ||||
| <dependency> | ||||
|     <groupId>org.springframework.cloud</groupId> | ||||
|     <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> | ||||
| </dependency> | ||||
| --> | ||||
| 
 | ||||
| <!-- 使用nacos注册中心 | ||||
|     版本 0.2.x.RELEASE 对应的是 Spring Boot 2.x 版本,版本 0.1.x.RELEASE 对应的是 Spring Boot 1.x 版本。 | ||||
|    https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-alibaba-nacos-discovery | ||||
| --> | ||||
| <dependency> | ||||
|     <groupId>org.springframework.cloud</groupId> | ||||
|     <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> | ||||
|     <version>0.2.2.RELEASE</version> | ||||
| </dependency> | ||||
| <!-- 注册中心end --> | ||||
| ``` | ||||
| 
 | ||||
| 2.yml文件新增nacos配置,并注释掉eureka相关配置 | ||||
| 
 | ||||
| ```yaml | ||||
| spring: | ||||
|   cloud: | ||||
|     # nacos注册中心,和eureka只能用一个 | ||||
|     nacos: | ||||
|       discovery: | ||||
|         server-addr: 127.0.0.1:8848 | ||||
| ``` | ||||
| 
 | ||||
| - 网关修改 | ||||
| 
 | ||||
| 找到`sop-gateway`工程,步骤同上 | ||||
| 
 | ||||
| - SOP-admin修改 | ||||
| 
 | ||||
| 
 | ||||
| 修改yml文件,新增nacos服务器地址,`registry.name`填nacos | ||||
| 
 | ||||
| ```yaml | ||||
| # 注册中心地址,根据实际情况改,这里只是参数,并不会去注册 | ||||
| registry: | ||||
|   # 使用eureka,填:eureka,使用nacos填:nacos | ||||
|   name: nacos | ||||
|   eureka-server-addr: http://localhost:1111/eureka/ | ||||
|   nacos-server-addr: 127.0.0.1:8848 | ||||
| ``` | ||||
| 
 | ||||
| - website-server修改 | ||||
| 
 | ||||
| 步骤同`SOP-admin修改` | ||||
| 
 | ||||
| - 参考资料 | ||||
| 
 | ||||
| 1.[nacos介绍及安装](https://nacos.io/zh-cn/docs/quick-start.html) | ||||
| 
 | ||||
| 2.[nacos spring cloud注册发现](https://nacos.io/zh-cn/docs/quick-start-spring-cloud.html) | ||||
| @ -1,25 +0,0 @@ | ||||
| # 原理分析之路由存储 | ||||
| 
 | ||||
| SOP将路由信息存到了zookeeper当中,服务在启动时,将自己的路由信息上传到zookeeper中。 | ||||
| 网关监听存放路由的节点,动态更新到本地。 | ||||
| 
 | ||||
| zookeeper存储路由的结构如下: | ||||
| 
 | ||||
| ```xml | ||||
| /com.gitee.sop.route   根节点 | ||||
|       /serviceId        服务节点,名字为服务名 | ||||
|            /route1      路由节点,名字为:name+version,存放路由信息 | ||||
|            /route2 | ||||
|            /... | ||||
| ``` | ||||
| 
 | ||||
| 服务启动时,创建`/serviceId`节点,然后遍历创建`/routeN`节点 | ||||
| 
 | ||||
| 同时,网关监听`服务节点`和`路由节点`,当有新服务加入时,网关会获取到新加入的路由节点信息, | ||||
| 同时路由节点下面的子节点也会被监听到。后续子节点的增删改都会被网关监听到,然后更新到本地。 | ||||
| 
 | ||||
| 服务上传路由相关代码在`com.gitee.sop.servercommon.manager.ServiceZookeeperApiMetaManager`类中 | ||||
| 
 | ||||
| 网关监听相关代码在`com.gitee.sop.gatewaycommon.manager.BaseRouteManager`中 | ||||
| 
 | ||||
| 
 | ||||
| @ -1,13 +0,0 @@ | ||||
| DROP TABLE IF EXISTS `config_common`; | ||||
| 
 | ||||
| CREATE TABLE `config_common` ( | ||||
|   `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `config_group` varchar(64) NOT NULL DEFAULT '' COMMENT '配置分组', | ||||
|   `config_key` varchar(64) NOT NULL DEFAULT '' COMMENT '配置key', | ||||
|   `content` varchar(128) NOT NULL DEFAULT '' COMMENT '内容', | ||||
|   `remark` varchar(128) DEFAULT NULL COMMENT '备注', | ||||
|   `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||||
|   `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, | ||||
|   PRIMARY KEY (`id`), | ||||
|   UNIQUE KEY `uk_groupkey` (`config_group`,`config_key`) USING BTREE | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='通用配置表'; | ||||
| @ -1,20 +0,0 @@ | ||||
| DROP TABLE IF EXISTS `isv_keys`; | ||||
| 
 | ||||
| CREATE TABLE `isv_keys` ( | ||||
|   `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `app_key` varchar(128) NOT NULL DEFAULT '应用id(交给开发者)', | ||||
|   `sign_type` tinyint(4) NOT NULL DEFAULT '1' COMMENT '1:RSA2,2:MD5', | ||||
|   `secret` varchar(200) NOT NULL DEFAULT '' COMMENT 'sign_type=2时使用', | ||||
|   `key_format` tinyint(4) NOT NULL DEFAULT '1' COMMENT '秘钥格式,1:PKCS8(JAVA适用),2:PKCS1(非JAVA适用)', | ||||
|   `public_key_isv` text NOT NULL COMMENT '开发者生成的公钥', | ||||
|   `private_key_isv` text NOT NULL COMMENT '开发者生成的私钥(交给开发者)', | ||||
|   `public_key_platform` text NOT NULL COMMENT '平台生成的公钥(交给开发者)', | ||||
|   `private_key_platform` text NOT NULL COMMENT '平台生成的私钥', | ||||
|   `gmt_create` datetime DEFAULT CURRENT_TIMESTAMP, | ||||
|   `gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, | ||||
|   PRIMARY KEY (`id`), | ||||
|   UNIQUE KEY `uk_appkey` (`app_key`) USING BTREE | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='ISV秘钥'; | ||||
| 
 | ||||
| INSERT INTO `sop`.`isv_keys` (`app_key`,`sign_type`, `secret`,`key_format`, `public_key_isv`, `private_key_isv`, `public_key_platform`, `private_key_platform`) | ||||
| select app_key, sign_type, secret, 1, pub_key,pri_key,'','' from isv_info; | ||||
| @ -1,2 +0,0 @@ | ||||
| ALTER TABLE `sop`.`isv_info` ADD COLUMN `remark` VARCHAR(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注' AFTER `sign_type`; | ||||
| 
 | ||||
| @ -1,11 +0,0 @@ | ||||
| use sop; | ||||
| 
 | ||||
| CREATE TABLE `config_ip_blacklist` ( | ||||
|   `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `ip` varchar(64) NOT NULL DEFAULT '' COMMENT 'ip', | ||||
|   `remark` varchar(128) DEFAULT NULL COMMENT '备注', | ||||
|   `gmt_create` datetime DEFAULT CURRENT_TIMESTAMP, | ||||
|   `gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, | ||||
|   PRIMARY KEY (`id`), | ||||
|   UNIQUE KEY `uk_ip` (`ip`) USING BTREE | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='IP黑名单'; | ||||
| @ -1,25 +0,0 @@ | ||||
| use sop; | ||||
| 
 | ||||
| CREATE TABLE `config_gray` ( | ||||
|   `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `service_id` varchar(64) NOT NULL DEFAULT '', | ||||
|   `user_key_content` text COMMENT '用户key,多个用引文逗号隔开', | ||||
|   `name_version_content` text COMMENT '需要灰度的接口,goods.get1.0=1.2,多个用英文逗号隔开', | ||||
|   `gmt_create` datetime DEFAULT CURRENT_TIMESTAMP, | ||||
|   `gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, | ||||
|   PRIMARY KEY (`id`), | ||||
|   UNIQUE KEY `uk_serviceid` (`service_id`) USING BTREE | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='服务灰度配置'; | ||||
| 
 | ||||
| 
 | ||||
| CREATE TABLE `config_gray_instance` ( | ||||
|   `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'instance_id', | ||||
|   `service_id` varchar(64) NOT NULL DEFAULT '' COMMENT 'service_id', | ||||
|   `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0:禁用,1:启用', | ||||
|   `gmt_create` datetime DEFAULT CURRENT_TIMESTAMP, | ||||
|   `gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, | ||||
|   PRIMARY KEY (`id`), | ||||
|   UNIQUE KEY `uk_instanceid` (`instance_id`) USING BTREE, | ||||
|   KEY `idx_serviceid` (`service_id`) USING BTREE | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='开启灰度服务器实例'; | ||||
| @ -1,3 +0,0 @@ | ||||
| ALTER TABLE `sop`.`isv_info` ADD COLUMN `sign_type` TINYINT NOT NULL DEFAULT 1 COMMENT '签名类型,1:RSA2,2:MD5' AFTER `status`; | ||||
| 
 | ||||
| update isv_info set sign_type=2 where secret <> ''; | ||||
| @ -1,16 +0,0 @@ | ||||
| DROP TABLE IF EXISTS `user_info`; | ||||
| 
 | ||||
| CREATE TABLE `user_info` ( | ||||
|   `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `username` varchar(64) NOT NULL DEFAULT '' COMMENT '用户名', | ||||
|   `password` varchar(128) NOT NULL DEFAULT '' COMMENT '密码', | ||||
|   `nickname` varchar(64) NOT NULL DEFAULT '' COMMENT '昵称', | ||||
|   `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||||
|   `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, | ||||
|   PRIMARY KEY (`id`), | ||||
|   KEY `idx_unamepwd` (`username`,`password`) USING BTREE | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户信息表'; | ||||
| 
 | ||||
| 
 | ||||
| INSERT INTO `user_info` ( `username`, `password`, `nickname`, `gmt_create`, `gmt_modified`) VALUES | ||||
| 	('zhangsan','123456','张三','2019-04-27 08:32:57','2019-04-27 08:32:57'); | ||||
| @ -1,32 +0,0 @@ | ||||
| 
 | ||||
| DROP TABLE IF EXISTS `config_limit`; | ||||
| 
 | ||||
| 
 | ||||
| CREATE TABLE `config_limit` ( | ||||
|   `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `route_id` varchar(128) DEFAULT NULL COMMENT '路由id', | ||||
|   `app_key` varchar(128) DEFAULT NULL, | ||||
|   `limit_ip` varchar(300) DEFAULT NULL COMMENT '限流ip,多个用英文逗号隔开', | ||||
|   `service_id` varchar(64) NOT NULL DEFAULT '' COMMENT '服务id', | ||||
|   `limit_type` tinyint(4) NOT NULL DEFAULT '1' COMMENT '限流策略,1:漏桶策略,2:令牌桶策略', | ||||
|   `exec_count_per_second` int(11) DEFAULT NULL COMMENT '每秒可处理请求数', | ||||
|   `limit_code` varchar(64) DEFAULT NULL COMMENT '返回的错误码', | ||||
|   `limit_msg` varchar(100) DEFAULT NULL COMMENT '返回的错误信息', | ||||
|   `token_bucket_count` int(11) DEFAULT NULL COMMENT '令牌桶容量', | ||||
|   `limit_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '限流开启状态,1:开启,0关闭', | ||||
|   `order_index` int(11) NOT NULL DEFAULT '0' COMMENT '顺序,值小的优先执行', | ||||
|   `remark` varchar(128) DEFAULT NULL COMMENT '备注', | ||||
|   `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||||
|   `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, | ||||
|   PRIMARY KEY (`id`) | ||||
| ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 COMMENT='限流配置'; | ||||
| 
 | ||||
| INSERT INTO `config_limit` (`id`, `route_id`, `app_key`, `limit_ip`, `service_id`, `limit_type`, `exec_count_per_second`, `limit_code`, `limit_msg`, `token_bucket_count`, `limit_status`, `order_index`, `remark`, `gmt_create`, `gmt_modified`) VALUES | ||||
| 	(1,'alipay.story.get1.0','','192.168.1.1,172.2.2.3','story-service',2,5,'','',6,1,3,NULL,'2019-05-17 19:21:35','2019-05-21 09:12:15'), | ||||
| 	(2,'alipay.story.get1.0','2019032617262200001','','story-service',1,5,'service-budy','服务器忙',5,1,0,NULL,'2019-05-17 19:39:30','2019-05-21 15:36:52'), | ||||
| 	(3,'alipay.story.find1.0','20190331562013861008375808','','story-service',1,3,'service-busy','服务器忙',5,1,1,NULL,'2019-05-17 20:20:32','2019-05-20 17:40:17'), | ||||
| 	(4,'alipay.story.get1.2','','','story-service',2,5,'','',3,1,1,NULL,'2019-05-20 16:27:21','2019-05-21 15:53:10'), | ||||
| 	(5,'','20190401562373796095328256','','story-service',1,5,'service-busy','服务器忙',5,1,0,'这个appKey调用很频繁,重点照顾','2019-05-21 15:48:08','2019-05-21 18:45:32'), | ||||
| 	(6,'','','10.1.30.54','story-service',1,5,'service-busy','服务器忙',5,1,0,'这个ip在攻击我们','2019-05-21 15:55:33','2019-05-21 18:17:29'), | ||||
| 	(7,'story.get1.1','','10.1.30.54','story-service',1,5,'service-busy','服务器忙',5,1,0,NULL,'2019-05-21 16:30:48','2019-05-21 16:30:48'), | ||||
| 	(8,'','20190513577548661718777857','10.1.30.54','story-service',1,5,'service-busy','服务器忙',5,1,0,NULL,'2019-05-21 17:10:45','2019-05-21 17:10:52'); | ||||
| @ -1,5 +1,5 @@ | ||||
| # 后台admin | ||||
| 
 | ||||
| - sop-admin-front: admin前端layui实现(停止维护,改用sop-admin-vue) | ||||
| - sop-admin-server: admin服务端 | ||||
| - sop-admin-server: admin服务端,使用方式见readme.md | ||||
| - sop-admin-vue: admin前端vue实现 | ||||
| 
 | ||||
|  | ||||
| @ -1,23 +0,0 @@ | ||||
| # admin前端页面(停止维护,改用sop-admin-vue) | ||||
| 
 | ||||
| 做到前后端分离。 | ||||
| 
 | ||||
| 当然也可以不分离,直接把前端页面放入到server中。这样做的好处是启动服务器即可访问页面。 | ||||
| 
 | ||||
| 步骤如下: | ||||
| 
 | ||||
| - cd到sop-admin-front目录,执行命令`mvn clean install` | ||||
| - sop-admin-server工程添加maven依赖 | ||||
| 
 | ||||
| ``` | ||||
| <dependency> | ||||
|     <groupId>com.gitee.sop</groupId> | ||||
|     <artifactId>sop-admin-front</artifactId> | ||||
|     <version>1.0.0-SNAPSHOT</version> | ||||
| </dependency> | ||||
| ``` | ||||
| 
 | ||||
| 启动服务端,访问:http://localhost:8082 | ||||
| 
 | ||||
| 原理就是springboot访问webjars资源,建议在开发的时候前后端分离,开发完成后再打包成webjars。 | ||||
| 
 | ||||
| @ -1,16 +0,0 @@ | ||||
| @font-face { | ||||
|   font-family: 'iconfont'; | ||||
|   src: url('../fonts/iconfont.eot'); | ||||
|   src: url('../fonts/iconfont.eot?#iefix') format('embedded-opentype'), | ||||
|   url('../fonts/iconfont.woff') format('woff'), | ||||
|   url('../fonts/iconfont.ttf') format('truetype'), | ||||
|   url('../fonts/iconfont.svg#iconfont') format('svg'); | ||||
| } | ||||
| .iconfont{ | ||||
|   font-family:"iconfont" !important; | ||||
|   font-size:16px;font-style:normal; | ||||
|   -webkit-font-smoothing: antialiased; | ||||
|   -webkit-text-stroke-width: 0.2px; | ||||
|   -moz-osx-font-smoothing: grayscale; | ||||
| } | ||||
| 
 | ||||
| @ -1,680 +0,0 @@ | ||||
| @charset "utf-8"; | ||||
| @import url(../lib/layui/css/layui.css); | ||||
| *{ | ||||
|     margin: 0px; | ||||
|     padding: 0px; | ||||
|     font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | ||||
| } | ||||
| a{ | ||||
|     text-decoration: none; | ||||
| } | ||||
| html{ | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
|     overflow-x:hidden;  | ||||
|     overflow-y:auto; | ||||
| } | ||||
| body{ | ||||
|     width: 100%; | ||||
|     min-height: 100%; | ||||
| } | ||||
| .login-bg{ | ||||
|     /*background: #eeeeee url() 0 0 no-repeat;*/ | ||||
|      background:url(../images/bg.png) no-repeat center; | ||||
|     background-size: cover; | ||||
|     overflow: hidden; | ||||
| } | ||||
| .login{ | ||||
|     margin: 120px auto 0 auto; | ||||
|     min-height: 420px; | ||||
|     max-width: 420px; | ||||
|     padding: 40px; | ||||
|     background-color: #ffffff; | ||||
|     margin-left: auto; | ||||
|     margin-right: auto; | ||||
|     border-radius: 4px; | ||||
|     /* overflow-x: hidden; */ | ||||
|     box-sizing: border-box; | ||||
| } | ||||
| .login a.logo{ | ||||
|     display: block; | ||||
|     height: 58px; | ||||
|     width: 167px; | ||||
|     margin: 0 auto 30px auto; | ||||
|     background-size: 167px 42px; | ||||
| } | ||||
| .login .message { | ||||
|     margin: 10px 0 0 -58px; | ||||
|     padding: 18px 10px 18px 60px; | ||||
|     background: #189F92; | ||||
|     position: relative; | ||||
|     color: #fff; | ||||
|     font-size: 16px; | ||||
| } | ||||
| .login #darkbannerwrap { | ||||
|     background: url(../images/aiwrap.png); | ||||
|     width: 18px; | ||||
|     height: 10px; | ||||
|     margin: 0 0 20px -58px; | ||||
|     position: relative; | ||||
| } | ||||
| 
 | ||||
| .login input[type=text], | ||||
| .login input[type=file], | ||||
| .login input[type=password], | ||||
| .login input[type=email], select { | ||||
|     border: 1px solid #DCDEE0; | ||||
|     vertical-align: middle; | ||||
|     border-radius: 3px; | ||||
|     height: 50px; | ||||
|     padding: 0px 16px; | ||||
|     font-size: 14px; | ||||
|     color: #555555; | ||||
|     outline:none; | ||||
|     width:100%; | ||||
|     box-sizing: border-box; | ||||
| } | ||||
| .login input[type=text]:focus, | ||||
| .login input[type=file]:focus, | ||||
| .login input[type=password]:focus, | ||||
| .login input[type=email]:focus, select:focus { | ||||
|     border: 1px solid #27A9E3; | ||||
| } | ||||
| .login input[type=submit], | ||||
| .login input[type=button]{ | ||||
|     display: inline-block; | ||||
|     vertical-align: middle; | ||||
|     padding: 12px 24px; | ||||
|     margin: 0px; | ||||
|     font-size: 18px; | ||||
|     line-height: 24px; | ||||
|     text-align: center; | ||||
|     white-space: nowrap; | ||||
|     vertical-align: middle; | ||||
|     cursor: pointer; | ||||
|     color: #ffffff; | ||||
|     background-color: #189F92; | ||||
|     border-radius: 3px; | ||||
|     border: none; | ||||
|     -webkit-appearance: none; | ||||
|     outline:none; | ||||
|     width:100%; | ||||
| } | ||||
| .login hr { | ||||
|     background: #fff 0 0 no-repeat; | ||||
| } | ||||
| .login hr.hr15 { | ||||
|     height: 15px; | ||||
|     border: none; | ||||
|     margin: 0px; | ||||
|     padding: 0px; | ||||
|     width: 100%; | ||||
| } | ||||
| .login hr.hr20 { | ||||
|     height: 20px; | ||||
|     border: none; | ||||
|     margin: 0px; | ||||
|     padding: 0px; | ||||
|     width: 100%; | ||||
| } | ||||
| .x-body{ | ||||
|     padding: 10px; | ||||
| } | ||||
| .x-nav{ | ||||
|     padding: 0 20px; | ||||
|     position: relative; | ||||
|     z-index: 99; | ||||
|     border-bottom: 1px solid #e5e5e5; | ||||
|     line-height: 39px; | ||||
|     height: 37px; | ||||
|     overflow: hidden; | ||||
| } | ||||
| xblock{ | ||||
|     display: block; | ||||
|     margin-bottom: 10px; | ||||
|     padding: 5px; | ||||
|     line-height: 22px; | ||||
|     /* border-left: 5px solid #009688; */ | ||||
|     border-radius: 0 2px 2px 0; | ||||
|     background-color: #f2f2f2; | ||||
| } | ||||
| .x-right{ | ||||
|   float: right; | ||||
| } | ||||
| .x-so{ | ||||
|     /*text-align: center;*/ | ||||
|     /*background: #f2f2f2 url() 0 0 no-repeat;*/ | ||||
|     margin-bottom: 20px; | ||||
| } | ||||
| .x-so input.layui-input{ | ||||
|     width: 150px; | ||||
| } | ||||
| .x-so .layui-form-label{ | ||||
|     display: inline-block; | ||||
| } | ||||
| .x-so input.layui-input,.x-so input.layui-btn{ | ||||
|     display: inline-block; | ||||
| } | ||||
| .x-red{ | ||||
|     color: red; | ||||
| } | ||||
| .x-green{ | ||||
|     color: green; | ||||
| } | ||||
| .x-yellow{ | ||||
|     color: #ffae19; | ||||
| } | ||||
| .x-a{ | ||||
|     color: #1AA093; | ||||
| } | ||||
| .x-a:hover{ | ||||
|     color: #127F74; | ||||
| } | ||||
| .x-sort{ | ||||
|     height: 30px; | ||||
| } | ||||
| .x-show{ | ||||
|     cursor: pointer; | ||||
| } | ||||
| .layui-form-switch{ | ||||
|     margin-top: 0px; | ||||
| } | ||||
| .layui-input:focus, .layui-textarea:focus { | ||||
|     border-color: #189f92!important; | ||||
| } | ||||
| 
 | ||||
| .page{ | ||||
|     margin-top: 20px; | ||||
|     text-align: center; | ||||
| 
 | ||||
| } | ||||
| .page a{ | ||||
|     display: inline-block; | ||||
|     background: #fff 0 0 no-repeat; | ||||
|     color: #888; | ||||
|     padding: 10px; | ||||
|     min-width: 15px; | ||||
|     border: 1px solid #E2E2E2; | ||||
| 
 | ||||
| } | ||||
| .page span{ | ||||
|     display: inline-block; | ||||
|     padding: 10px; | ||||
|     min-width: 15px; | ||||
|     border: 1px solid #E2E2E2; | ||||
| } | ||||
| .page span.current{ | ||||
|     display: inline-block; | ||||
|     background: #009688 0 0 no-repeat; | ||||
|     color: #fff; | ||||
|     padding: 10px; | ||||
|     min-width: 15px; | ||||
|     border: 1px solid #009688; | ||||
| } | ||||
| .page .pagination li{ | ||||
|     display: inline-block; | ||||
|     margin-right: 5px; | ||||
|     text-align: center; | ||||
| } | ||||
| .page .pagination li.active span{ | ||||
|     background: #009688 0 0 no-repeat; | ||||
|     color: #fff; | ||||
|     border: 1px solid #009688; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| /*登录样式*/ | ||||
| /*头部*/ | ||||
| .container{ | ||||
|     width: 100%; | ||||
|     height: 45px; | ||||
|     background-color: #222; | ||||
|     border-bottom: 1px solid rgba(255, 255, 255, 0.2); | ||||
| } | ||||
| .container .logo a{ | ||||
|     float: left; | ||||
|     color: #fff; | ||||
|     font-size: 18px; | ||||
|     padding-left: 20px; | ||||
|     line-height: 45px; | ||||
|     width: 200px; | ||||
| } | ||||
| .container .right{ | ||||
|     background-color:rgba(0,0,0,0); | ||||
|     float: right; | ||||
| 
 | ||||
| } | ||||
| .container .left_open{ | ||||
|     height: 45px; | ||||
|     float: left; | ||||
| } | ||||
| .container .left_open i{ | ||||
|     display: block; | ||||
|     background: rgba(255,255,255,0.1) 0 0 no-repeat; | ||||
|     color: #fff; | ||||
|     width: 32px; | ||||
|     height: 32px; | ||||
|     line-height: 32px; | ||||
|     border-radius: 3px; | ||||
|     text-align: center; | ||||
|     margin-top: 7px; | ||||
|     cursor: pointer; | ||||
| } | ||||
| .container .left_open i:hover{ | ||||
|     background: rgba(255,255,255,0.3) 0 0 no-repeat; | ||||
| } | ||||
| 
 | ||||
| .container .left{ | ||||
|     background-color:rgba(0,0,0,0); | ||||
|     float: left; | ||||
| 
 | ||||
| } | ||||
| .container .layui-nav-item{ | ||||
|     line-height: 45px; | ||||
| } | ||||
| .container .layui-nav-more{ | ||||
|     top: 20px; | ||||
| } | ||||
| .container .layui-nav-child{ | ||||
|     top: 50px; | ||||
| } | ||||
| .container .layui-nav-child i{ | ||||
|     margin-right: 10px; | ||||
| } | ||||
| .layui-nav .layui-nav-item a{ | ||||
|     color: #fff; | ||||
|     cursor: pointer; | ||||
| } | ||||
| .layui-nav .layui-nav-child a{ | ||||
|     color: #333; | ||||
|     cursor: pointer; | ||||
| } | ||||
| .left-nav{ | ||||
|     position: absolute; | ||||
|     top: 46px; | ||||
|     bottom: 42px; | ||||
|     left: 0; | ||||
|     z-index: 2; | ||||
|     /*padding-top: 1px;*/ | ||||
|     background-color: #EEEEEE; | ||||
|     width: 220px; | ||||
|     max-width: 220px; | ||||
|     overflow: auto; | ||||
|     overflow-x:hidden; | ||||
|     border-right: 1px solid #e5e5e5; | ||||
| 
 | ||||
|     /*width: 0px;*/ | ||||
| } | ||||
| .left-nav #nav li{ | ||||
|     border-bottom: 1px solid #e5e5e5; | ||||
| } | ||||
| .left-nav #nav li:hover > a{ | ||||
|     /*color: blue;*/ | ||||
| } | ||||
| .left-nav #nav .current{ | ||||
|     background-color: rgba(0, 0, 0, 0.3); | ||||
| } | ||||
| .left-nav #nav li a{ | ||||
|     font-size: 14px; | ||||
|     padding: 10px 15px 10px 20px; | ||||
|     display: block; | ||||
|     cursor: pointer; | ||||
| } | ||||
| .left-nav #nav li a cite{ | ||||
|     font-size: 14px; | ||||
| } | ||||
| 
 | ||||
| .left-nav #nav li .sub-menu{ | ||||
|     display: block; | ||||
| } | ||||
| .left-nav #nav li .opened{ | ||||
|     display: block; | ||||
| } | ||||
| .left-nav #nav li .opened:hover{ | ||||
|     /*background: #fff url() 0 0 no-repeat;*/ | ||||
| } | ||||
| .left-nav #nav li .opened .current{ | ||||
|      | ||||
| } | ||||
| .left-nav #nav li .sub-menu li:hover{ | ||||
|     /*color: blue;*/ | ||||
|      /*background: #fff url() 0 0 no-repeat;*/ | ||||
| } | ||||
| .left-nav #nav li .sub-menu li a{ | ||||
|     padding: 12px 15px 12px 30px; | ||||
|     font-size: 14px; | ||||
|     cursor: pointer; | ||||
| } | ||||
| .left-nav #nav li .sub-menu li .sub-menu li a{ | ||||
|     padding-left: 45px; | ||||
| } | ||||
| .left-nav #nav li .sub-menu li a:hover{ | ||||
|     color: #148cf1; | ||||
| } | ||||
| .left-nav #nav li .sub-menu li a i{ | ||||
|     font-size: 12px; | ||||
|     margin-left: 8px; | ||||
| } | ||||
| .left-nav #nav li a i{ | ||||
|     /*padding-right: 10px;*/ | ||||
|     line-height: 14px; | ||||
| } | ||||
| .left-nav #nav li .nav_right{ | ||||
|     float: right; | ||||
|     font-size: 16px; | ||||
| } | ||||
| .left-nav #nav li.active { | ||||
|     background: #ddd; | ||||
| } | ||||
| .left-nav #nav li.active a { | ||||
|     color: #148cf1; | ||||
| } | ||||
| 
 | ||||
| .x-slide_left { | ||||
|     width: 17px; | ||||
|     height: 61px; | ||||
|     position: absolute; | ||||
|     top: 200px; | ||||
|     left: 221px; | ||||
|     cursor: pointer; | ||||
|     z-index: 3; | ||||
| } | ||||
| .page-content{ | ||||
|     position: absolute; | ||||
|     top: 46px; | ||||
|     right: 0; | ||||
|     bottom: 42px; | ||||
|     left: 221px; | ||||
|     overflow: hidden; | ||||
|     z-index: 1; | ||||
| } | ||||
| .page-content-bg{ | ||||
|     position: absolute; | ||||
|     top: 46px; | ||||
|     right: 0; | ||||
|     bottom: 42px; | ||||
|     left: 221px; | ||||
|     background: rgba(0,0,0,0.5); url() 0 0 no-repeat; | ||||
|     overflow: hidden; | ||||
|     z-index: 100; | ||||
|     display: none; | ||||
| } | ||||
| 
 | ||||
| .page-content .tab{ | ||||
|     height: 100%; | ||||
|     width: 100%; | ||||
|     background: #EFEEF0 0 0 no-repeat; | ||||
|     margin: 0px; | ||||
| } | ||||
| .page-content .layui-tab-title{ | ||||
|     /*padding-top: 5px;*/ | ||||
|     height: 35px; | ||||
|     background: #EFEEF0 0 0 no-repeat; | ||||
|     position: relative; | ||||
|     z-index: 100; | ||||
| } | ||||
| .page-content .layui-tab-title li.home i{ | ||||
|     padding-right: 5px; | ||||
| } | ||||
| .page-content .layui-tab-title li.home .layui-tab-close{ | ||||
|     display: none; | ||||
| } | ||||
| .page-content .layui-tab-title li{ | ||||
|     line-height: 35px; | ||||
| } | ||||
| .page-content .layui-tab-title .layui-this:after{ | ||||
|     height: 36px; | ||||
| } | ||||
| .page-content .layui-tab-title li .layui-tab-close{ | ||||
|     border-radius: 50%; | ||||
| } | ||||
| .page-content .layui-tab-title .layui-this{ | ||||
|     background: #fff 0 0 no-repeat; | ||||
| } | ||||
| .page-content .layui-tab-bar{ | ||||
|     height:34px; | ||||
|     line-height: 35px; | ||||
| } | ||||
| .page-content .layui-tab-content{ | ||||
|     position: absolute; | ||||
|     top: 36px; | ||||
|     bottom: 0px; | ||||
|     width: 100%; | ||||
|     background: #fff 0 0 no-repeat; | ||||
|     padding: 0px; | ||||
|     overflow: hidden; | ||||
| } | ||||
| .page-content .layui-tab-content .layui-tab-item{ | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
|      | ||||
| } | ||||
| .page-content .layui-tab-content .layui-tab-item iframe{ | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
| 
 | ||||
| } | ||||
| .x-admin-carousel,.layui-carousel,.x-admin-carousel>[carousel-item]>* { | ||||
|     background-color:#fff | ||||
| } | ||||
| 
 | ||||
| .x-admin-backlog .x-admin-backlog-body { | ||||
|     display:block; | ||||
|     padding:10px 15px; | ||||
|     background-color:#f8f8f8; | ||||
|     color:#999; | ||||
|     border-radius:2px; | ||||
|     transition:all .3s; | ||||
|     -webkit-transition:all .3s | ||||
| } | ||||
| .x-admin-backlog-body h3 { | ||||
|     padding-bottom:10px; | ||||
|     font-size:12px | ||||
| } | ||||
| .x-admin-backlog-body p cite { | ||||
|     font-style:normal; | ||||
|     font-size:30px; | ||||
|     font-weight:300; | ||||
|     color:#009688 | ||||
| } | ||||
| .x-admin-backlog-body:hover { | ||||
|     background-color:#CFCFCF; | ||||
|     color:#888 | ||||
| } | ||||
| 
 | ||||
| .welcome-footer{padding: 30px 0; line-height: 30px; text-align: center; background-color: #eee; color: #666; font-weight: 300;} | ||||
| body .layui-layout-admin .footer-demo{height: auto; padding: 15px 0; line-height: 26px;} | ||||
| .welcome-footer a{padding: 0 5px;} | ||||
| 
 | ||||
| table th, table td { | ||||
|     word-break: break-all; | ||||
| } | ||||
| 
 | ||||
| .footer{ | ||||
|     position: fixed; | ||||
|     bottom: 0px; | ||||
|     width: 100%; | ||||
|     background-color: #222; | ||||
|     border-top: 1px solid rgba(255, 255, 255, 0.2); | ||||
|     line-height: 41px; | ||||
|     color: #fff; | ||||
|     /*padding-left: 10px;*/ | ||||
| } | ||||
| .footer .copyright{ | ||||
|     margin-left: 10px; | ||||
| } | ||||
| 
 | ||||
| /*404页面样式*/ | ||||
| .fly-panel { | ||||
|     margin-bottom: 15px; | ||||
|     border-radius: 2px; | ||||
|     background-color: #fff; | ||||
|     box-shadow: 0 1px 2px 0 rgba(0,0,0,.05); | ||||
| } | ||||
| .fly-none { | ||||
|     min-height: 600px; | ||||
|     text-align: center; | ||||
|     padding-top: 50px; | ||||
|     color: #999; | ||||
| } | ||||
| .fly-none .layui-icon { | ||||
|     line-height: 300px; | ||||
|     font-size: 300px; | ||||
|     color: #393D49; | ||||
| } | ||||
| .fly-none p { | ||||
|     margin-top: 50px; | ||||
|     padding: 0 15px; | ||||
|     font-size: 20px; | ||||
|     color: #999; | ||||
|     font-weight: 300; | ||||
| } | ||||
| #tab_right{ | ||||
|     display: none; | ||||
|     width: 80px; | ||||
|     position: absolute; | ||||
|     top: 35px; | ||||
|     left: 0px; | ||||
| } | ||||
| #tab_right dl{ | ||||
|     top: 0px; | ||||
| } | ||||
| #tab_show{ | ||||
|     position: absolute; | ||||
|     top: 36px; | ||||
|     bottom: 0px; | ||||
|     width: 100%; | ||||
|     background:rgb(255, 255, 255); | ||||
|     padding: 0px; | ||||
|     overflow: hidden; | ||||
|     display: none; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| @media screen and (max-width: 768px){ | ||||
|     .fast-add{ | ||||
|         display: none; | ||||
|     } | ||||
|     .layui-nav .to-index{ | ||||
|         display: none; | ||||
|     } | ||||
|     .container .logo a{ | ||||
|         width: 140px; | ||||
|     } | ||||
|     .container .left_open { | ||||
|         /*float: right;*/ | ||||
|     } | ||||
|     .left-nav{ | ||||
|         left: -221px; | ||||
|     } | ||||
|     .page-content{ | ||||
|         left: 0px; | ||||
|     } | ||||
|     .page-content .layui-tab-content .layui-tab-item{ | ||||
|         -webkit-overflow-scrolling: touch;  | ||||
|         overflow-y: scroll;  | ||||
|     } | ||||
|     .x-so input.layui-input{ | ||||
|         width: 100%; | ||||
|         margin: 10px; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*精细版样式*/ | ||||
| 
 | ||||
| .x-admin-sm{ | ||||
|     font-size: 12px; | ||||
| } | ||||
| .x-admin-sm body{ | ||||
|     font-size: 12px; | ||||
| } | ||||
| /*登录页面样式*/ | ||||
| .x-admin-sm .login input[type=submit],.x-admin-sm .login input[type=button]{ | ||||
|     font-size: 14px; | ||||
| } | ||||
| .x-admin-sm .login input[type=text], | ||||
| .x-admin-sm .login input[type=file], | ||||
| .x-admin-sm .login input[type=password], | ||||
| .x-admin-sm .login input[type=email], .x-admin-sm select { | ||||
|     font-size: 12px; | ||||
| } | ||||
| .x-admin-sm .login .message{ | ||||
|     font-size: 14px; | ||||
| } | ||||
| 
 | ||||
| .x-admin-sm .layui-table td, .x-admin-sm .layui-table th{ | ||||
|     font-size: 12px; | ||||
| } | ||||
| .x-admin-sm .layui-elem-field legend{ | ||||
|     font-size: 18px; | ||||
| } | ||||
| 
 | ||||
| .x-admin-sm .x-admin-backlog-body p cite{ | ||||
|     font-size: 24px; | ||||
| } | ||||
| .x-admin-sm .left-nav #nav li a cite{ | ||||
|     font-size: 12px; | ||||
| } | ||||
| .x-admin-sm .iconfont{ | ||||
|     font-size: 14px; | ||||
| } | ||||
| .x-admin-sm .layui-tab-title li{ | ||||
|     font-size: 12px; | ||||
| } | ||||
| .x-admin-sm .layui-icon{ | ||||
|     font-size: 14px; | ||||
| } | ||||
| .x-admin-sm .layui-nav *{ | ||||
|     font-size: 12px; | ||||
| } | ||||
| .x-admin-sm  .layui-breadcrumb>*{ | ||||
|    font-size: 12px;  | ||||
| } | ||||
| .x-admin-sm  .layui-btn,.x-admin-sm .layui-btn-xs,.x-admin-sm .layui-btn-sm{ | ||||
|     font-size: 12px; | ||||
| } | ||||
| 
 | ||||
| .x-admin-sm .layui-laydate{ | ||||
|     font-size: 12px; | ||||
| } | ||||
| .x-admin-sm  .layui-btn{ | ||||
|     height: 30px; | ||||
|     line-height: 30px; | ||||
|     padding: 0 10px; | ||||
| } | ||||
| 
 | ||||
| .layui-table-cell .layui-btn { | ||||
|     height: 27px; | ||||
|     line-height: 28px; | ||||
| } | ||||
| 
 | ||||
| .x-admin-sm .layui-btn-lg{ | ||||
|     height: 38px; | ||||
|     line-height: 38px; | ||||
|     padding: 0 18px; | ||||
|     font-size: 14px; | ||||
| } | ||||
| .x-admin-sm .layui-layer-title,.x-admin-sm .layui-layer-dialog .layui-layer-content{ | ||||
|     font-size: 12px; | ||||
| } | ||||
| .x-admin-sm .layui-input,.x-admin-sm .layui-select,.x-admin-sm .layui-textarea{ | ||||
|     height: 30px; | ||||
| } | ||||
| 
 | ||||
| .x-admin-sm .layui-form-pane .layui-form-label{ | ||||
|     height: 30px; | ||||
|     line-height: 14px; | ||||
| } | ||||
| .x-admin-sm .layui-form-checkbox span{ | ||||
|     font-size: 12px; | ||||
| } | ||||
| .x-admin-sm .fly-none .layui-icon { | ||||
|     line-height: 300px; | ||||
|     font-size: 300px; | ||||
|     color: #393D49; | ||||
| } | ||||
| 
 | ||||
| .x-win {display: none;padding: 20px;} | ||||
| 
 | ||||
| .layui-this{font-weight: bold;} | ||||
| Before Width: | Height: | Size: 315 KiB | 
| Before Width: | Height: | Size: 3.0 KiB | 
| Before Width: | Height: | Size: 28 KiB | 
| @ -1,85 +0,0 @@ | ||||
| /** | ||||
|  * 请求工具 | ||||
|  */ | ||||
| var ApiUtil = (function () { | ||||
|     var ACCESS_TOKEN_KEY = "sop_admin_access_token"; | ||||
| 
 | ||||
|     // 接口URL,更改此处即可
 | ||||
|     var url = SopConfig.url; | ||||
|     var URI_CHAR = '/'; | ||||
|     var params = {}; | ||||
| 
 | ||||
|     (function () { | ||||
|         var aPairs, aTmp; | ||||
|         var queryString = window.location.search.toString(); | ||||
|         queryString = queryString.substring(1, queryString.length); //remove   "?"
 | ||||
|         aPairs = queryString.split("&"); | ||||
|         for (var i = 0; i < aPairs.length; i++) { | ||||
|             aTmp = aPairs[i].split("="); | ||||
|             params[aTmp[0]] = decodeURIComponent(aTmp[1]); | ||||
|         } | ||||
|     })(); | ||||
| 
 | ||||
|     function formatUri(uri) { | ||||
|         if (uri.substring(0, 1) !== URI_CHAR) { | ||||
|             uri = URI_CHAR + uri; | ||||
|         } | ||||
|         if (uri.substring(uri.length - 1) !== URI_CHAR) { | ||||
|             uri = uri + URI_CHAR; | ||||
|         } | ||||
|         return uri; | ||||
|     } | ||||
| 
 | ||||
|     function getAccessToken() { | ||||
|         return localStorage.getItem(ACCESS_TOKEN_KEY) || ''; | ||||
|     } | ||||
| 
 | ||||
|     return { | ||||
|         post: function (uri, params, callback) { | ||||
|             uri = formatUri(uri); | ||||
|             sdk.post({ | ||||
|                 url: url + uri | ||||
|                 , data: params // 请求参数
 | ||||
|                 , access_token: getAccessToken() | ||||
|                 , callback: function (resp) { // 成功回调
 | ||||
|                     var code = resp.code | ||||
|                     if (!code || code === '-9') { | ||||
|                         alert('系统错误'); | ||||
|                         return | ||||
|                     } | ||||
|                     if (code === '-100' || code === '18' || code === '21') { // 未登录
 | ||||
|                         ApiUtil.logout() | ||||
|                         return | ||||
|                     } | ||||
|                     if (code === '0') { // 成功
 | ||||
|                         callback(resp) | ||||
|                     } else { | ||||
|                         layer.alert(resp.msg); | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|         , setAccessToken:function (accessToken) { | ||||
|             localStorage.setItem(ACCESS_TOKEN_KEY,accessToken); | ||||
|         } | ||||
|         , getAccessToken: function () { | ||||
|             return getAccessToken(); | ||||
|         } | ||||
|         , logout: function () { | ||||
|             localStorage.removeItem(ACCESS_TOKEN_KEY); | ||||
|             top.location.href = '../login/login.html'; | ||||
|         } | ||||
|         , getUrl: function () { | ||||
|             return url; | ||||
|         } | ||||
|         , createUrl: function (uri, params) { | ||||
|             if (!uri) { | ||||
|                 throw new Error('uri不能为空'); | ||||
|             } | ||||
|             return url + formatUri(uri) + (params ? '?data=' + encodeURIComponent(JSON.stringify(params)) : ''); | ||||
|         } | ||||
|         , getParam: function (paramName) { | ||||
|             return params[paramName]; | ||||
|         } | ||||
|     } | ||||
| })(); | ||||
| @ -1,38 +0,0 @@ | ||||
| function setCookie(name, value, expires, path, domain, secure) { | ||||
|     if(typeof is_remember!="undefined") | ||||
|         return false; | ||||
|     var today = new Date(); | ||||
|     today.setTime( today.getTime() ); | ||||
|     var expires_date = new Date( today.getTime() + (expires) ); | ||||
|     document.cookie= name + "=" + escape(value) + | ||||
|         ((expires) ? "; expires=" + expires_date.toGMTString() : "") + | ||||
|         ((path) ? "; path=" + path : "") + | ||||
|         ((domain) ? "; domain=" + domain : "") + | ||||
|         ((secure) ? "; secure" : ""); | ||||
| } | ||||
| function getCookie(name) { | ||||
|     var dc = document.cookie; | ||||
|     var prefix = name + "="; | ||||
|     var begin = dc.indexOf("; " + prefix); | ||||
|     if (begin == -1) { | ||||
|         begin = dc.indexOf(prefix); | ||||
|         if (begin != 0) return null; | ||||
|     } else { | ||||
|         begin += 2; | ||||
|     } | ||||
|     var end = document.cookie.indexOf(";", begin); | ||||
|     if (end == -1) { | ||||
|         end = dc.length; | ||||
|     } | ||||
|     return unescape(dc.substring(begin + prefix.length, end)); | ||||
| } | ||||
| function deleteCookie(name, path, domain) { | ||||
|     if (getCookie(name)) { | ||||
|         document.cookie = name + "=" + | ||||
|             ((path) ? "; path=" + path : "") + | ||||
|             ((domain) ? "; domain=" + domain : "") + | ||||
|             "; expires=Thu, 01-Jan-70 00:00:01 GMT"; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| @ -1,37 +0,0 @@ | ||||
| $(function () { | ||||
|     var $pageFrame = $('#pageFrame'); | ||||
|     var $selectLi = null; | ||||
|     $('.left-nav').on('click', 'li', function (event) { | ||||
|         var $tagLi = $(this); | ||||
|         var $tagA = $tagLi.find('a').eq(0); | ||||
|         var href = $tagA.prop('href'); | ||||
|         if (href) { | ||||
|             $pageFrame.prop('src', href + '?q=' + new Date().getTime()); | ||||
|             if ($selectLi) { | ||||
|                 $selectLi.removeClass('active') | ||||
|             } | ||||
|             $selectLi = $tagLi.addClass('active'); | ||||
|         } | ||||
|         return false; | ||||
|     }); | ||||
| 
 | ||||
|     $('.container .left_open i').click(function(event) { | ||||
|         if($('.left-nav').css('left')=='0px'){ | ||||
|             $('.left-nav').animate({left: '-221px'}, 100); | ||||
|             $('.page-content').animate({left: '0px'}, 100); | ||||
|             $('.page-content-bg').hide(); | ||||
|         }else{ | ||||
|             $('.left-nav').animate({left: '0px'}, 100); | ||||
|             $('.page-content').animate({left: '221px'}, 100); | ||||
|             if($(window).width()<768){ | ||||
|                 $('.page-content-bg').show(); | ||||
|             } | ||||
|         } | ||||
|     }); | ||||
| 
 | ||||
|     ApiUtil.post('admin.userinfo.get', {}, function (resp) { | ||||
|         var userInfo = resp.data; | ||||
|         $('#username').text(userInfo.username); | ||||
|     }); | ||||
| 
 | ||||
| }); | ||||
| @ -1,22 +0,0 @@ | ||||
| var RouteRole = { | ||||
|     loadAllRole: function (form, contentId, callback) { | ||||
|         ApiUtil.post('role.listall', {}, function (resp) { | ||||
|             var roles = resp.data; | ||||
|             var html = [] | ||||
|             for (var i = 0; i < roles.length; i++) { | ||||
|                 if (i > 0 && i % 5 === 0) { | ||||
|                     html.push('<br>'); | ||||
|                 } | ||||
|                 var role = roles[i]; | ||||
|                 html.push('<input type="checkbox" name="roleCode" value="'+role.roleCode+'" lay-skin="primary" title="'+role.description+'">'); | ||||
|             } | ||||
|             $('#' + contentId).html(html.join('')); | ||||
| 
 | ||||
|             // 如果你的HTML是动态生成的,自动渲染就会失效
 | ||||
|             // 因此你需要在相应的地方,执行下述方法来手动渲染,跟这类似的还有 element.init();
 | ||||
|             form.render(); | ||||
| 
 | ||||
|             callback && callback(); | ||||
|         }); | ||||
|     } | ||||
| } | ||||
| @ -1,414 +0,0 @@ | ||||
| // Array.prototype.remove = function(val) { 
 | ||||
| //     var index = this.indexOf(val); 
 | ||||
| //     if (index > -1) { 
 | ||||
| //         return  this.splice(index, 1); 
 | ||||
| //     }
 | ||||
| 
 | ||||
| // };
 | ||||
| 
 | ||||
| $(function () { | ||||
| 
 | ||||
|     //加载弹出层
 | ||||
|     layui.use(['form','element'], | ||||
|     function() { | ||||
|         layer = layui.layer; | ||||
|         element = layui.element; | ||||
| 
 | ||||
|         //tab 右键事件
 | ||||
|         $(".layui-tab-title").on('contextmenu', 'li', function(event) { | ||||
|             var tab_left = $(this).position().left; | ||||
|             var left = $(this).position().top; | ||||
|             this_index = $(this).attr('lay-id'); | ||||
|             $('#tab_right').css({'left':tab_left+50}).show(); | ||||
|             $('#tab_show').show(); | ||||
|             return false; | ||||
|         }); | ||||
| 
 | ||||
|         $('.page-content,#tab_show,.container,.left-nav').click(function(event) { | ||||
|             $('#tab_right').hide(); | ||||
|             $('#tab_show').hide(); | ||||
|         }); | ||||
| 
 | ||||
|         $('#tab_right').on('click', 'dd', function(event) { | ||||
| 
 | ||||
|             if(getCookie('tab_list')){ | ||||
|                 var tab_list = getCookie('tab_list').split(','); | ||||
|             }else{ | ||||
|                 var tab_list = []; | ||||
|             } | ||||
| 
 | ||||
|             var type = $(this).attr('data-type'); | ||||
| 
 | ||||
|             if(type=='this'){ | ||||
| 
 | ||||
|                 tab.tabDelete(this_index); | ||||
| 
 | ||||
|                 var index = -1; | ||||
| 
 | ||||
|                 for (var i in tab_list) { | ||||
|                     if(tab_list[i]==(this_index-1)){ | ||||
|                         index = i; | ||||
|                     } | ||||
|                  } 
 | ||||
|                 if (index > -1) { 
 | ||||
|                     tab_list.splice(index, 1); 
 | ||||
|                 } | ||||
| 
 | ||||
|                 setCookie('tab_list',tab_list); | ||||
|             } | ||||
|             if(type=='all'){ | ||||
| 
 | ||||
|                 for (var i in tab_list) { | ||||
|                    tab.tabDelete(Number(tab_list[i])+1); 
 | ||||
|                 } | ||||
| 
 | ||||
|                 setCookie('tab_list',[]); | ||||
|             } | ||||
| 
 | ||||
|             if(type=='other'){ | ||||
| 
 | ||||
|                 for (var i in tab_list) { | ||||
|                     if(tab_list[i]!=(this_index-1)){ | ||||
|                         tab.tabDelete(Number(tab_list[i])+1); 
 | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 setCookie('tab_list',[this_index-1]); | ||||
|             } | ||||
|             // alert(this_index);
 | ||||
|             $('#tab_right').hide(); | ||||
|         }); | ||||
| 
 | ||||
|         // tab 双击事件
 | ||||
|         $(".layui-tab-title").on('dblclick', 'li', function(event) { | ||||
|             var id = $(this).attr('lay-id'); | ||||
|             tab.tabDelete(id); | ||||
| 
 | ||||
|             if(getCookie('tab_list')){ | ||||
|                 tab_list = getCookie('tab_list').split(','); | ||||
|             }else{ | ||||
|                 tab_list = []; | ||||
|             } | ||||
| 
 | ||||
| 
 | ||||
|             var index = -1; | ||||
| 
 | ||||
|             for (var i in tab_list) { | ||||
|                 if(tab_list[i]==(id-1)){ | ||||
|                     index = i; | ||||
|                 } | ||||
|              } 
 | ||||
| 
 | ||||
| 
 | ||||
|             if (index > -1) { 
 | ||||
|                 tab_list.splice(index, 1); 
 | ||||
|             } | ||||
| 
 | ||||
|             setCookie('tab_list',tab_list); | ||||
|             return false; | ||||
|         }); | ||||
| 
 | ||||
|         // tab 删除事件
 | ||||
|         element.on('tabDelete(xbs_tab)', function(data){ | ||||
|             var id  = $(this).parent().attr('lay-id')-1; | ||||
| 
 | ||||
|             if(getCookie('tab_list')){ | ||||
|                 tab_list = getCookie('tab_list').split(','); | ||||
|             }else{ | ||||
|                 tab_list = []; | ||||
|             } | ||||
| 
 | ||||
| 
 | ||||
|             var index = -1; | ||||
| 
 | ||||
|             for (var i in tab_list) { | ||||
|                 if(tab_list[i]==id){ | ||||
|                     index = i; | ||||
|                 } | ||||
|              } 
 | ||||
| 
 | ||||
| 
 | ||||
|             if (index > -1) { 
 | ||||
|                 tab_list.splice(index, 1); 
 | ||||
|             } | ||||
| 
 | ||||
|             setCookie('tab_list',tab_list); | ||||
| 
 | ||||
|         }); | ||||
| 
 | ||||
|         if(getCookie('tab_list')){ | ||||
|             tab_list = getCookie('tab_list').split(','); | ||||
| 
 | ||||
|             for (var i in tab_list) { | ||||
|                  $('.left-nav #nav li').eq(tab_list[i]).click(); | ||||
|             } | ||||
|          } | ||||
|     }); | ||||
| 
 | ||||
|     //触发事件
 | ||||
|   var tab = { | ||||
|         tabAdd: function(title,url,id){ | ||||
|           //新增一个Tab项
 | ||||
|           element.tabAdd('xbs_tab', { | ||||
|             title: title 
 | ||||
|             ,content: '<iframe tab-id="'+id+'" frameborder="0" src="'+url+'" scrolling="yes" class="x-iframe"></iframe>' | ||||
|             ,id: id | ||||
|           }) | ||||
|         } | ||||
|         ,tabDelete: function(othis){ | ||||
|           //删除指定Tab项
 | ||||
|           element.tabDelete('xbs_tab', othis); //删除:“商品管理”
 | ||||
|           
 | ||||
|            
 | ||||
|           // othis.addClass('layui-btn-disabled');
 | ||||
|         } | ||||
|         ,tabChange: function(id){ | ||||
|           //切换到指定Tab项
 | ||||
|           element.tabChange('xbs_tab', id); //切换到:用户管理
 | ||||
|         } | ||||
|       }; | ||||
| 
 | ||||
| 
 | ||||
|     tableCheck = { | ||||
|         init:function  () { | ||||
|             $(".x-admin .layui-form-checkbox").click(function(event) { | ||||
|                 if($(this).hasClass('layui-form-checked')){ | ||||
|                     $(this).removeClass('layui-form-checked'); | ||||
|                     if($(this).hasClass('header')){ | ||||
|                         $(".x-admin .layui-form-checkbox").removeClass('layui-form-checked'); | ||||
|                     } | ||||
|                 }else{ | ||||
|                     $(this).addClass('layui-form-checked'); | ||||
|                     if($(this).hasClass('header')){ | ||||
|                         $(".x-admin .layui-form-checkbox").addClass('layui-form-checked'); | ||||
|                     } | ||||
|                 } | ||||
|                 
 | ||||
|             }); | ||||
|         }, | ||||
|         getData:function  () { | ||||
|             var obj = $(".x-admin .layui-form-checked").not('.header'); | ||||
|             var arr=[]; | ||||
|             obj.each(function(index, el) { | ||||
|                 arr.push(obj.eq(index).attr('data-id')); | ||||
|             }); | ||||
|             return arr; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // 开启表格多选
 | ||||
|     tableCheck.init(); | ||||
|       
 | ||||
| 
 | ||||
|     $('.container .left_open i').click(function(event) { | ||||
|         if($('.left-nav').css('left')=='0px'){ | ||||
|             $('.left-nav').animate({left: '-221px'}, 100); | ||||
|             $('.page-content').animate({left: '0px'}, 100); | ||||
|             $('.page-content-bg').hide(); | ||||
|         }else{ | ||||
|             $('.left-nav').animate({left: '0px'}, 100); | ||||
|             $('.page-content').animate({left: '221px'}, 100); | ||||
|             if($(window).width()<768){ | ||||
|                 $('.page-content-bg').show(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|     }); | ||||
| 
 | ||||
|     $('.page-content-bg').click(function(event) { | ||||
|         $('.left-nav').animate({left: '-221px'}, 100); | ||||
|         $('.page-content').animate({left: '0px'}, 100); | ||||
|         $(this).hide(); | ||||
|     }); | ||||
| 
 | ||||
|     
 | ||||
| 
 | ||||
|     $('.layui-tab-close').click(function(event) { | ||||
|         $('.layui-tab-title li').eq(0).find('i').remove(); | ||||
|     }); | ||||
| 
 | ||||
|    $("tbody.x-cate tr[fid!='0']").hide(); | ||||
|     // 栏目多级显示效果
 | ||||
|     $('.x-show').click(function () { | ||||
|         if($(this).attr('status')=='true'){ | ||||
|             $(this).html(''); 
 | ||||
|             $(this).attr('status','false'); | ||||
|             cateId = $(this).parents('tr').attr('cate-id'); | ||||
|             $("tbody tr[fid="+cateId+"]").show(); | ||||
|        }else{ | ||||
|             cateIds = []; | ||||
|             $(this).html(''); | ||||
|             $(this).attr('status','true'); | ||||
|             cateId = $(this).parents('tr').attr('cate-id'); | ||||
|             getCateId(cateId); | ||||
|             for (var i in cateIds) { | ||||
|                 $("tbody tr[cate-id="+cateIds[i]+"]").hide().find('.x-show').html('').attr('status','true'); | ||||
|             } | ||||
|        } | ||||
|     }) | ||||
| 
 | ||||
|     //左侧菜单效果
 | ||||
|     
 | ||||
|     $('.left-nav #nav').on('click', 'li', function(event) { | ||||
| 
 | ||||
|         var index = $('.left-nav #nav li').index($(this)); | ||||
| 
 | ||||
|         if($(this).children('.sub-menu').length){ | ||||
|             if($(this).hasClass('open')){ | ||||
| 
 | ||||
|                 if($(this).parent().hasClass('sub-menu')){ | ||||
|                     deleteCookie('left_menu_son'); | ||||
|                 }else{ | ||||
|                     deleteCookie('left_menu_father'); | ||||
|                 } | ||||
| 
 | ||||
|                 $(this).removeClass('open'); | ||||
|                 $(this).find('.nav_right').html(''); | ||||
|                 $(this).children('.sub-menu').stop().slideUp(); | ||||
|                 // $(this).siblings().children('.sub-menu').slideUp();
 | ||||
|             }else{ | ||||
|                 
 | ||||
| 
 | ||||
|                 if($(this).parent().hasClass('sub-menu')){ | ||||
|                     setCookie('left_menu_son',index); | ||||
|                 }else{ | ||||
|                     setCookie('left_menu_father',index); | ||||
|                 } | ||||
| 
 | ||||
|                 $(this).addClass('open'); | ||||
|                 $(this).children('a').find('.nav_right').html(''); | ||||
|                 $(this).children('.sub-menu').stop().slideDown(); | ||||
|                 // $(this).siblings().children('.sub-menu').stop().slideUp();
 | ||||
|                 // $(this).siblings().find('.nav_right').html('');
 | ||||
|                 // $(this).siblings().removeClass('open');
 | ||||
|             } | ||||
|         }else{ | ||||
| 
 | ||||
|             var url = $(this).children('a').attr('_href'); | ||||
|             var title = $(this).find('cite').html(); | ||||
|             // var index  = $('.left-nav #nav li').index($(this));
 | ||||
| 
 | ||||
|             var is_refresh = $(this).attr('date-refresh')?true:false; 
 | ||||
| 
 | ||||
|             for (var i = 0; i <$('.x-iframe').length; i++) { | ||||
|                 if($('.x-iframe').eq(i).attr('tab-id')==index+1){ | ||||
|                     tab.tabChange(index+1); | ||||
|                     event.stopPropagation(); | ||||
| 
 | ||||
|                     if(is_refresh) | ||||
|                         $('.x-iframe').eq(i).attr("src",$('.x-iframe').eq(i).attr('src')); | ||||
| 
 | ||||
|                     return; | ||||
|                 } | ||||
|             }; | ||||
|             
 | ||||
|             if(getCookie('tab_list')){ | ||||
|                 tab_list = getCookie('tab_list').split(','); | ||||
|             }else{ | ||||
|                 tab_list = []; | ||||
|             } | ||||
| 
 | ||||
|             var is_exist = false; | ||||
| 
 | ||||
|             for (var i in tab_list) { | ||||
|                 if(tab_list[i]==index) | ||||
|                     is_exist = true; | ||||
|             } | ||||
| 
 | ||||
|             if(!is_exist){ | ||||
|                 tab_list.push(index); | ||||
|             } | ||||
| 
 | ||||
|             setCookie('tab_list',tab_list); | ||||
| 
 | ||||
|             tab.tabAdd(title,url,index+1); | ||||
|             tab.tabChange(index+1); | ||||
|         } | ||||
|         
 | ||||
|         event.stopPropagation(); | ||||
|          
 | ||||
|     }) | ||||
| 
 | ||||
|     // 左侧菜单记忆功能
 | ||||
|     /*if(getCookie('left_menu_father')!=null){ | ||||
|         $('.left-nav #nav li').eq(getCookie('left_menu_father')).click(); | ||||
|     } | ||||
| 
 | ||||
|     if(getCookie('left_menu_son')!=null){ | ||||
|         $('.left-nav #nav li').eq(getCookie('left_menu_son')).click(); | ||||
|     }*/ | ||||
|      
 | ||||
|      
 | ||||
|      
 | ||||
|     
 | ||||
| }) | ||||
| 
 | ||||
| var cateIds = []; | ||||
| function getCateId(cateId) { | ||||
|     
 | ||||
|     $("tbody tr[fid="+cateId+"]").each(function(index, el) { | ||||
|         id = $(el).attr('cate-id'); | ||||
|         cateIds.push(id); | ||||
|         getCateId(id); | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| /*弹出层*/ | ||||
| /* | ||||
|     参数解释: | ||||
|     title   标题 | ||||
|     url     请求的url | ||||
|     id      需要操作的数据id | ||||
|     w       弹出层宽度(缺省调默认值) | ||||
|     h       弹出层高度(缺省调默认值) | ||||
| */ | ||||
| function x_admin_show(title,url,w,h){ | ||||
|     if (title == null || title == '') { | ||||
|         title=false; | ||||
|     }; | ||||
|     if (url == null || url == '') { | ||||
|         url="404.html"; | ||||
|     }; | ||||
|     if (w == null || w == '') { | ||||
|         w=($(window).width()*0.9); | ||||
|     }; | ||||
|     if (h == null || h == '') { | ||||
|         h=($(window).height() - 50); | ||||
|     }; | ||||
|     layer.open({ | ||||
|         type: 2, | ||||
|         area: [w+'px', h +'px'], | ||||
|         fix: false, //不固定
 | ||||
|         maxmin: true, | ||||
|         shadeClose: true, | ||||
|         shade:0.4, | ||||
|         title: title, | ||||
|         content: url, | ||||
|         success: function(){ | ||||
|           //窗口加载成功刷新frame
 | ||||
|           // location.replace(location.href);
 | ||||
|         }, | ||||
|         cancel:function(){ | ||||
|           //关闭窗口之后刷新frame
 | ||||
|           // location.replace(location.href);
 | ||||
|         }, | ||||
|         end:function(){ | ||||
|           //窗口销毁之后刷新frame
 | ||||
|           // location.replace(location.href);
 | ||||
|         } | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| /*关闭弹出框口*/ | ||||
| function x_admin_close(){ | ||||
|     var index = parent.layer.getFrameIndex(window.name); | ||||
|     parent.layer.close(index); | ||||
| } | ||||
| 
 | ||||
| function x_admin_father_reload(){ | ||||
|     
 | ||||
|     parent.location.reload(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| @ -1,136 +0,0 @@ | ||||
| <!DOCTYPE html> | ||||
| <html> | ||||
| <head> | ||||
| <meta charset="UTF-8"> | ||||
| <title>sdk</title> | ||||
| <script type="text/javascript" src="sdk.js"></script> | ||||
| <script type="text/javascript"> | ||||
| //需要发布到服务器上运行,并且server端需要处理跨域 | ||||
| //在IndexController.java上加@CrossOrigin(origins={"*"}) | ||||
| 
 | ||||
| // 初始化配置,执行一次即可 | ||||
| sdk.config({ | ||||
|     url : 'http://localhost:8080/api' | ||||
|     ,app_key : 'test' | ||||
|     ,secret : '123456' | ||||
| }); | ||||
| 
 | ||||
| sdk.get({ | ||||
| 	name   : 'goods.get' // 接口名 | ||||
| // 	,version:'1.0' | ||||
| // 	,access_token:'' | ||||
| 	,data  : {'goods_name':'iphone'} // 请求参数 | ||||
| 	,callback:function(resp) { // 成功回调 | ||||
| 		console.log(resp) | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
| </head> | ||||
| <body> | ||||
| 
 | ||||
| <h1>打开F12查看效果</h1> | ||||
| 
 | ||||
| <fieldset> | ||||
|     <legend>GET/POST</legend> | ||||
|     <button onclick="getTest()">GET</button> | ||||
|     <button onclick="postTest()">POST</button> | ||||
| </fieldset> | ||||
| <hr> | ||||
| <fieldset> | ||||
|     <legend>上传文件demo</legend> | ||||
|     <form id="frm"> | ||||
| 	    头像图片:<input type="file" name="headImg"/> <br><br> | ||||
| 	    身份证图片:<input type="file" name="idcardImg"/> | ||||
| 	</form> | ||||
|     <br> | ||||
|     <button onclick="uploadTest()">上传文件请求</button> | ||||
| </fieldset> | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| <pre> | ||||
| //需要发布到服务器上运行,并且server端需要处理跨域 | ||||
| //在IndexController.java上加@CrossOrigin(origins={"*"}) | ||||
| 
 | ||||
| sdk.config({ | ||||
|     url : 'http://localhost:8080/api' | ||||
|     ,app_key : 'test' | ||||
|     ,secret : '123456' | ||||
| }); | ||||
| 
 | ||||
| sdk.get({ | ||||
|     name   : 'goods.get' // 接口名 | ||||
|     ,data  : {'goods_name':'iphone'} // 请求参数 | ||||
|     ,callback:function(resp) { // 成功回调 | ||||
|         console.log(resp) | ||||
|     } | ||||
| }); // get方式不支持上传 | ||||
| 
 | ||||
| sdk.post({ | ||||
|     name   : 'goods.get' // 接口名 | ||||
|     ,data  : {'goods_name':'iphone'} // 请求参数 | ||||
|     ,callback:function(resp) { // 成功回调 | ||||
|         console.log(resp) | ||||
|     } | ||||
| }); | ||||
| 
 | ||||
| 
 | ||||
| /* ****************上传文件**************** */ | ||||
| <form id="frm"> | ||||
|     上传文件1:<input type="file" name="headImg"/> | ||||
|     上传文件2:<input type="file" name="idcardImg"/> | ||||
| </form> | ||||
| 
 | ||||
| function uploadTest() { | ||||
|     sdk.get({ | ||||
|         name   : 'file.upload' // 接口名 | ||||
|         ,data  : {'goods_name':'iphone'} // 请求参数 | ||||
|         ,form  : document.getElementById('frm') | ||||
|         ,callback:function(resp) { // 成功回调 | ||||
|             if(resp.code == '0') { | ||||
|                 alert('上传成功,' + resp.msg); | ||||
|             } else { | ||||
|                 alert('上传失败,' + resp.msg) | ||||
|             } | ||||
|         } | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| </pre> | ||||
| 
 | ||||
| <script type="text/javascript"> | ||||
| function uploadTest() { | ||||
| 	sdk.post({ | ||||
| 	    name   : 'file.upload' // 接口名 | ||||
| 	    ,data  : {'goods_name':'iphone'} // 请求参数 | ||||
| 	    ,form  : document.getElementById('frm') | ||||
| 	    ,callback:function(resp) { // 成功回调 | ||||
| 	        if(resp.code == '0') { | ||||
| 	        	alert('上传成功,' + resp.data); | ||||
| 	        } else { | ||||
| 	        	alert('上传失败,' + resp.msg) | ||||
| 	        } | ||||
| 	    } | ||||
| 	}); | ||||
| } | ||||
| function getTest() { | ||||
| 	sdk.get({ | ||||
|         name   : 'goods.get' // 接口名 | ||||
|         ,data  : {'goods_name':'iphone'} // 请求参数 | ||||
|         ,callback:function(resp) { // 成功回调 | ||||
|             console.log(resp); | ||||
|         } | ||||
|     }); | ||||
| } | ||||
| function postTest() { | ||||
| 	sdk.post({ | ||||
| 	    name   : 'goods.get' // 接口名 | ||||
| 	    ,data  : {'goods_name':'iphone'} // 请求参数 | ||||
| 	    ,callback:function(resp) { // 成功回调 | ||||
| 	        console.log(resp); | ||||
| 	    } | ||||
| 	}); | ||||
| } | ||||
| </script> | ||||
| </body> | ||||
| </html> | ||||
| @ -1,2 +0,0 @@ | ||||
| /** layui-v2.4.5 MIT License By https://www.layui.com */ | ||||
|  html #layuicss-skincodecss{display:none;position:absolute;width:1989px}.layui-code-h3,.layui-code-view{position:relative;font-size:12px}.layui-code-view{display:block;margin:10px 0;padding:0;border:1px solid #e2e2e2;border-left-width:6px;background-color:#F2F2F2;color:#333;font-family:Courier New}.layui-code-h3{padding:0 10px;height:32px;line-height:32px;border-bottom:1px solid #e2e2e2}.layui-code-h3 a{position:absolute;right:10px;top:0;color:#999}.layui-code-view .layui-code-ol{position:relative;overflow:auto}.layui-code-view .layui-code-ol li{position:relative;margin-left:45px;line-height:20px;padding:0 5px;border-left:1px solid #e2e2e2;list-style-type:decimal-leading-zero;*list-style-type:decimal;background-color:#fff}.layui-code-view pre{margin:0}.layui-code-notepad{border:1px solid #0C0C0C;border-left-color:#3F3F3F;background-color:#0C0C0C;color:#C2BE9E}.layui-code-notepad .layui-code-h3{border-bottom:none}.layui-code-notepad .layui-code-ol li{background-color:#3F3F3F;border-left:none} | ||||
| Before Width: | Height: | Size: 5.8 KiB | 
| Before Width: | Height: | Size: 11 KiB | 
| Before Width: | Height: | Size: 5.7 KiB | 
| Before Width: | Height: | Size: 701 B | 
| Before Width: | Height: | Size: 1.7 KiB | 
| Before Width: | Height: | Size: 274 KiB | 
| Before Width: | Height: | Size: 2.6 KiB | 
| Before Width: | Height: | Size: 5.4 KiB | 
| Before Width: | Height: | Size: 2.7 KiB | 
| Before Width: | Height: | Size: 4.0 KiB | 
| Before Width: | Height: | Size: 3.3 KiB | 
| Before Width: | Height: | Size: 7.3 KiB | 
| Before Width: | Height: | Size: 2.3 KiB | 
| Before Width: | Height: | Size: 1.8 KiB | 
| Before Width: | Height: | Size: 6.6 KiB | 
| Before Width: | Height: | Size: 4.3 KiB | 
| Before Width: | Height: | Size: 2.9 KiB | 
| Before Width: | Height: | Size: 3.0 KiB | 
| Before Width: | Height: | Size: 3.1 KiB | 
| Before Width: | Height: | Size: 5.0 KiB | 
| Before Width: | Height: | Size: 5.1 KiB | 
| Before Width: | Height: | Size: 9.6 KiB | 
| Before Width: | Height: | Size: 3.7 KiB | 
| Before Width: | Height: | Size: 7.9 KiB | 
| Before Width: | Height: | Size: 3.1 KiB | 
| Before Width: | Height: | Size: 3.2 KiB | 
| Before Width: | Height: | Size: 4.3 KiB | 
| Before Width: | Height: | Size: 2.7 KiB | 
| Before Width: | Height: | Size: 4.7 KiB | 
| Before Width: | Height: | Size: 3.9 KiB | 
| Before Width: | Height: | Size: 2.5 KiB | 
| Before Width: | Height: | Size: 2.0 KiB | 
| Before Width: | Height: | Size: 3.4 KiB | 
| Before Width: | Height: | Size: 2.4 KiB | 
| Before Width: | Height: | Size: 3.6 KiB | 
| Before Width: | Height: | Size: 1.8 KiB | 
| Before Width: | Height: | Size: 2.3 KiB | 
| Before Width: | Height: | Size: 1.5 KiB | 
| Before Width: | Height: | Size: 3.5 KiB | 
| Before Width: | Height: | Size: 6.3 KiB | 
| Before Width: | Height: | Size: 5.6 KiB | 
| Before Width: | Height: | Size: 3.1 KiB | 
| Before Width: | Height: | Size: 3.6 KiB |